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.
- package/dist/cjs/feedback-button_2.cjs.entry.js +728 -153
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/pushfeedback.cjs.js +1 -1
- package/dist/collection/components/feedback-button/feedback-button.js +80 -0
- package/dist/collection/components/feedback-modal/feedback-modal.css +439 -12
- package/dist/collection/components/feedback-modal/feedback-modal.js +771 -127
- package/dist/components/feedback-button.js +12 -0
- package/dist/components/feedback-modal2.js +745 -154
- package/dist/esm/feedback-button_2.entry.js +728 -153
- package/dist/esm/loader.js +1 -1
- package/dist/esm/pushfeedback.js +1 -1
- package/dist/pushfeedback/p-7406f7be.entry.js +7 -0
- package/dist/pushfeedback/pushfeedback.css +1 -1
- package/dist/pushfeedback/pushfeedback.esm.js +1 -1
- package/dist/types/components/feedback-button/feedback-button.d.ts +4 -0
- package/dist/types/components/feedback-modal/feedback-modal.d.ts +79 -14
- package/dist/types/components.d.ts +16 -0
- package/package.json +1 -1
- package/dist/pushfeedback/p-e6c2f829.entry.js +0 -22
|
@@ -30,6 +30,9 @@ const FeedbackButton = class {
|
|
|
30
30
|
this.project = '';
|
|
31
31
|
this.rating = undefined;
|
|
32
32
|
this.ratingMode = 'thumbs';
|
|
33
|
+
this.canvasEditorTitle = 'Edit screenshot';
|
|
34
|
+
this.canvasEditorCancelText = 'Cancel';
|
|
35
|
+
this.canvasEditorSaveText = 'Save';
|
|
33
36
|
this.emailPlaceholder = 'Email address (optional)';
|
|
34
37
|
this.errorMessage = 'Please try again later.';
|
|
35
38
|
this.errorMessage403 = 'The request URL does not match the one defined in PushFeedback for this project.';
|
|
@@ -44,6 +47,7 @@ const FeedbackButton = class {
|
|
|
44
47
|
this.ratingStarsPlaceholder = 'How would you rate this page?';
|
|
45
48
|
this.screenshotAttachedText = 'Screenshot attached';
|
|
46
49
|
this.screenshotButtonText = 'Add a screenshot';
|
|
50
|
+
this.screenshotTakingText = 'Taking screenshot...';
|
|
47
51
|
this.screenshotTopbarText = 'Select an element on this page';
|
|
48
52
|
this.sendButtonText = 'Send';
|
|
49
53
|
this.successMessage = '';
|
|
@@ -89,6 +93,9 @@ const FeedbackButton = class {
|
|
|
89
93
|
'project',
|
|
90
94
|
'rating',
|
|
91
95
|
'ratingMode',
|
|
96
|
+
'canvasEditorTitle',
|
|
97
|
+
'canvasEditorCancelText',
|
|
98
|
+
'canvasEditorSaveText',
|
|
92
99
|
'emailPlaceholder',
|
|
93
100
|
'errorMessage',
|
|
94
101
|
'errorMessage403',
|
|
@@ -104,6 +111,7 @@ const FeedbackButton = class {
|
|
|
104
111
|
'ratingStarsPlaceholder',
|
|
105
112
|
'screenshotAttachedText',
|
|
106
113
|
'screenshotButtonText',
|
|
114
|
+
'screenshotTakingText',
|
|
107
115
|
'screenshotTopbarText',
|
|
108
116
|
'sendButtonText',
|
|
109
117
|
'successMessage',
|
|
@@ -201,14 +209,14 @@ function commonjsRequire () {
|
|
|
201
209
|
|
|
202
210
|
var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
203
211
|
/*!
|
|
204
|
-
* html2canvas-pro 1.5.
|
|
205
|
-
* Copyright (c) 2024 yorickshan
|
|
212
|
+
* html2canvas-pro 1.5.11 <https://yorickshan.github.io/html2canvas-pro/>
|
|
213
|
+
* Copyright (c) 2024-present yorickshan and html2canvas-pro contributors
|
|
206
214
|
* Released under MIT License
|
|
207
215
|
*/
|
|
208
216
|
(function (global, factory) {
|
|
209
217
|
module.exports = factory() ;
|
|
210
218
|
})(commonjsGlobal, (function () {
|
|
211
|
-
|
|
219
|
+
/******************************************************************************
|
|
212
220
|
Copyright (c) Microsoft Corporation.
|
|
213
221
|
|
|
214
222
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
@@ -222,7 +230,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
222
230
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
223
231
|
PERFORMANCE OF THIS SOFTWARE.
|
|
224
232
|
***************************************************************************** */
|
|
225
|
-
/* global Reflect, Promise */
|
|
233
|
+
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
226
234
|
|
|
227
235
|
var extendStatics = function(d, b) {
|
|
228
236
|
extendStatics = Object.setPrototypeOf ||
|
|
@@ -266,7 +274,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
266
274
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
267
275
|
function step(op) {
|
|
268
276
|
if (f) throw new TypeError("Generator is already executing.");
|
|
269
|
-
while (_) try {
|
|
277
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
270
278
|
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;
|
|
271
279
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
272
280
|
switch (op[0]) {
|
|
@@ -295,8 +303,13 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
295
303
|
ar[i] = from[i];
|
|
296
304
|
}
|
|
297
305
|
}
|
|
298
|
-
return to.concat(ar || from);
|
|
299
|
-
}
|
|
306
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
310
|
+
var e = new Error(message);
|
|
311
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
312
|
+
};
|
|
300
313
|
|
|
301
314
|
var Bounds = /** @class */ (function () {
|
|
302
315
|
function Bounds(left, top, width, height) {
|
|
@@ -3931,7 +3944,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
3931
3944
|
case 'gurmukhi':
|
|
3932
3945
|
return 22 /* LIST_STYLE_TYPE.GURMUKHI */;
|
|
3933
3946
|
case 'hebrew':
|
|
3934
|
-
return
|
|
3947
|
+
return 52 /* LIST_STYLE_TYPE.HEBREW */;
|
|
3935
3948
|
case 'hiragana':
|
|
3936
3949
|
return 23 /* LIST_STYLE_TYPE.HIRAGANA */;
|
|
3937
3950
|
case 'hiragana-iroha':
|
|
@@ -6207,7 +6220,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
6207
6220
|
return createCounterStyleFromRange(value, 0xae6, 0xaef, true, defaultSuffix);
|
|
6208
6221
|
case 22 /* LIST_STYLE_TYPE.GURMUKHI */:
|
|
6209
6222
|
return createCounterStyleFromRange(value, 0xa66, 0xa6f, true, defaultSuffix);
|
|
6210
|
-
case
|
|
6223
|
+
case 52 /* LIST_STYLE_TYPE.HEBREW */:
|
|
6211
6224
|
return createAdditiveCounter(value, 1, 10999, HEBREW, 3 /* LIST_STYLE_TYPE.DECIMAL */, defaultSuffix);
|
|
6212
6225
|
case 23 /* LIST_STYLE_TYPE.HIRAGANA */:
|
|
6213
6226
|
return createCounterStyleFromSymbols(value, 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわゐゑをん');
|
|
@@ -6666,8 +6679,8 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
6666
6679
|
});
|
|
6667
6680
|
};
|
|
6668
6681
|
var ignoredStyleProperties = [
|
|
6669
|
-
'all',
|
|
6670
|
-
'd',
|
|
6682
|
+
'all', // #2476
|
|
6683
|
+
'd', // #2483
|
|
6671
6684
|
'content' // Safari shows pseudoelements if content is set
|
|
6672
6685
|
];
|
|
6673
6686
|
var copyCSSStyles = function (style, target) {
|
|
@@ -6784,12 +6797,21 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
6784
6797
|
};
|
|
6785
6798
|
Cache.prototype.loadImage = function (key) {
|
|
6786
6799
|
return __awaiter(this, void 0, void 0, function () {
|
|
6787
|
-
var isSameOrigin, useCORS, useProxy, src;
|
|
6800
|
+
var isSameOrigin, _a, useCORS, useProxy, src;
|
|
6788
6801
|
var _this = this;
|
|
6789
|
-
return __generator(this, function (
|
|
6790
|
-
switch (
|
|
6802
|
+
return __generator(this, function (_b) {
|
|
6803
|
+
switch (_b.label) {
|
|
6791
6804
|
case 0:
|
|
6792
|
-
|
|
6805
|
+
if (!(typeof this._options.customIsSameOrigin === 'function')) return [3 /*break*/, 2];
|
|
6806
|
+
return [4 /*yield*/, this._options.customIsSameOrigin(key, CacheStorage.isSameOrigin)];
|
|
6807
|
+
case 1:
|
|
6808
|
+
_a = _b.sent();
|
|
6809
|
+
return [3 /*break*/, 3];
|
|
6810
|
+
case 2:
|
|
6811
|
+
_a = CacheStorage.isSameOrigin(key);
|
|
6812
|
+
_b.label = 3;
|
|
6813
|
+
case 3:
|
|
6814
|
+
isSameOrigin = _a;
|
|
6793
6815
|
useCORS = !isInlineImage(key) && this._options.useCORS === true && FEATURES.SUPPORT_CORS_IMAGES && !isSameOrigin;
|
|
6794
6816
|
useProxy = !isInlineImage(key) &&
|
|
6795
6817
|
!isSameOrigin &&
|
|
@@ -6806,12 +6828,12 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
6806
6828
|
return [2 /*return*/];
|
|
6807
6829
|
}
|
|
6808
6830
|
src = key;
|
|
6809
|
-
if (!useProxy) return [3 /*break*/,
|
|
6831
|
+
if (!useProxy) return [3 /*break*/, 5];
|
|
6810
6832
|
return [4 /*yield*/, this.proxy(src)];
|
|
6811
|
-
case
|
|
6812
|
-
src =
|
|
6813
|
-
|
|
6814
|
-
case
|
|
6833
|
+
case 4:
|
|
6834
|
+
src = _b.sent();
|
|
6835
|
+
_b.label = 5;
|
|
6836
|
+
case 5:
|
|
6815
6837
|
this.context.logger.debug("Added image ".concat(key.substring(0, 256)));
|
|
6816
6838
|
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
|
6817
6839
|
var img = new Image();
|
|
@@ -6830,7 +6852,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
6830
6852
|
setTimeout(function () { return reject("Timed out (".concat(_this._options.imageTimeout, "ms) loading image")); }, _this._options.imageTimeout);
|
|
6831
6853
|
}
|
|
6832
6854
|
})];
|
|
6833
|
-
case
|
|
6855
|
+
case 6: return [2 /*return*/, _b.sent()];
|
|
6834
6856
|
}
|
|
6835
6857
|
});
|
|
6836
6858
|
});
|
|
@@ -7956,7 +7978,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
7956
7978
|
};
|
|
7957
7979
|
CanvasRenderer.prototype.renderNodeContent = function (paint) {
|
|
7958
7980
|
return __awaiter(this, void 0, void 0, function () {
|
|
7959
|
-
var container, curves, styles, _i, _a, child, image, image, iframeRenderer, canvas, size, _b, fontFamily, fontSize, baseline, bounds, x, textBounds, img, image, url,
|
|
7981
|
+
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;
|
|
7960
7982
|
return __generator(this, function (_c) {
|
|
7961
7983
|
switch (_c.label) {
|
|
7962
7984
|
case 0:
|
|
@@ -8056,9 +8078,9 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
8056
8078
|
}
|
|
8057
8079
|
}
|
|
8058
8080
|
if (isTextInputElement(container) && container.value.length) {
|
|
8059
|
-
_b = this.createFontStyle(styles),
|
|
8081
|
+
_b = this.createFontStyle(styles), font = _b[0], fontFamily = _b[1], fontSize = _b[2];
|
|
8060
8082
|
baseline = this.fontMetrics.getMetrics(fontFamily, fontSize).baseline;
|
|
8061
|
-
this.ctx.font =
|
|
8083
|
+
this.ctx.font = font;
|
|
8062
8084
|
this.ctx.fillStyle = asString(styles.color);
|
|
8063
8085
|
this.ctx.textBaseline = 'alphabetic';
|
|
8064
8086
|
this.ctx.textAlign = canvasTextAlign(container.styles.textAlign);
|
|
@@ -8107,8 +8129,8 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
8107
8129
|
case 18: return [3 /*break*/, 20];
|
|
8108
8130
|
case 19:
|
|
8109
8131
|
if (paint.listValue && container.styles.listStyleType !== -1 /* LIST_STYLE_TYPE.NONE */) {
|
|
8110
|
-
|
|
8111
|
-
this.ctx.font =
|
|
8132
|
+
font = this.createFontStyle(styles)[0];
|
|
8133
|
+
this.ctx.font = font;
|
|
8112
8134
|
this.ctx.fillStyle = asString(styles.color);
|
|
8113
8135
|
this.ctx.textBaseline = 'middle';
|
|
8114
8136
|
this.ctx.textAlign = 'right';
|
|
@@ -8338,7 +8360,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
8338
8360
|
canvas.height = height;
|
|
8339
8361
|
ctx = canvas.getContext('2d');
|
|
8340
8362
|
gradient_1 = ctx.createLinearGradient(x0, y0, x1, y1);
|
|
8341
|
-
processColorStops(backgroundImage.stops, lineLength).forEach(function (colorStop) {
|
|
8363
|
+
processColorStops(backgroundImage.stops, lineLength || 1).forEach(function (colorStop) {
|
|
8342
8364
|
return gradient_1.addColorStop(colorStop.stop, asString(colorStop.color));
|
|
8343
8365
|
});
|
|
8344
8366
|
ctx.fillStyle = gradient_1;
|
|
@@ -8873,7 +8895,8 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
8873
8895
|
allowTaint: (_b = opts.allowTaint) !== null && _b !== void 0 ? _b : false,
|
|
8874
8896
|
imageTimeout: (_c = opts.imageTimeout) !== null && _c !== void 0 ? _c : 15000,
|
|
8875
8897
|
proxy: opts.proxy,
|
|
8876
|
-
useCORS: (_d = opts.useCORS) !== null && _d !== void 0 ? _d : false
|
|
8898
|
+
useCORS: (_d = opts.useCORS) !== null && _d !== void 0 ? _d : false,
|
|
8899
|
+
customIsSameOrigin: opts.customIsSameOrigin
|
|
8877
8900
|
};
|
|
8878
8901
|
contextOptions = __assign({ logging: (_e = opts.logging) !== null && _e !== void 0 ? _e : true, cache: opts.cache }, resourceOptions);
|
|
8879
8902
|
windowOptions = {
|
|
@@ -8974,7 +8997,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
|
|
|
8974
8997
|
//# sourceMappingURL=html2canvas-pro.js.map
|
|
8975
8998
|
});
|
|
8976
8999
|
|
|
8977
|
-
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)}}";
|
|
9000
|
+
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}}";
|
|
8978
9001
|
|
|
8979
9002
|
const FeedbackModal = class {
|
|
8980
9003
|
constructor(hostRef) {
|
|
@@ -9061,8 +9084,27 @@ const FeedbackModal = class {
|
|
|
9061
9084
|
this.showScreenshotTopBar = false;
|
|
9062
9085
|
this.hasSelectedElement = false;
|
|
9063
9086
|
this.encodedScreenshot = null;
|
|
9064
|
-
|
|
9065
|
-
|
|
9087
|
+
// Remove highlight from ALL selected elements
|
|
9088
|
+
document.querySelectorAll('.feedback-modal-element-selected').forEach(el => {
|
|
9089
|
+
el.classList.remove('feedback-modal-element-selected');
|
|
9090
|
+
});
|
|
9091
|
+
// Reset canvas editor states
|
|
9092
|
+
this.takingScreenshot = false;
|
|
9093
|
+
this.showPreviewModal = false;
|
|
9094
|
+
this.showCanvasEditor = false;
|
|
9095
|
+
this.annotations = [];
|
|
9096
|
+
this.currentAnnotation = null;
|
|
9097
|
+
this.isDrawing = false;
|
|
9098
|
+
this.canvasRef = null;
|
|
9099
|
+
this.canvasContext = null;
|
|
9100
|
+
this.originalImageData = null;
|
|
9101
|
+
// Reset resizing states
|
|
9102
|
+
this.isResizing = false;
|
|
9103
|
+
this.resizingAnnotation = null;
|
|
9104
|
+
this.resizeStartSize = 16;
|
|
9105
|
+
this.hoveredAnnotation = null;
|
|
9106
|
+
this.resizeHandle = false;
|
|
9107
|
+
// Reset form states
|
|
9066
9108
|
this.formSuccess = false;
|
|
9067
9109
|
this.formError = false;
|
|
9068
9110
|
this.formErrorStatus = 500;
|
|
@@ -9071,109 +9113,609 @@ const FeedbackModal = class {
|
|
|
9071
9113
|
this.resetOverflow();
|
|
9072
9114
|
}, 200);
|
|
9073
9115
|
};
|
|
9074
|
-
this.openScreenShot = () => {
|
|
9075
|
-
|
|
9076
|
-
this.
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9116
|
+
this.openScreenShot = async () => {
|
|
9117
|
+
// Show loading state immediately
|
|
9118
|
+
this.takingScreenshot = true;
|
|
9119
|
+
try {
|
|
9120
|
+
// Capture viewport screenshot immediately
|
|
9121
|
+
const dataUrl = await this.captureViewportScreenshot();
|
|
9122
|
+
this.encodedScreenshot = dataUrl;
|
|
9123
|
+
this.originalImageData = dataUrl;
|
|
9124
|
+
// Reset loading state
|
|
9125
|
+
this.takingScreenshot = false;
|
|
9126
|
+
// Skip preview modal and go directly to canvas editor
|
|
9127
|
+
this.showModal = false;
|
|
9128
|
+
this.showCanvasEditor = true;
|
|
9129
|
+
// Initialize canvas after a short delay to ensure DOM is ready
|
|
9130
|
+
setTimeout(() => {
|
|
9131
|
+
this.initializeCanvas();
|
|
9132
|
+
}, 100);
|
|
9133
|
+
}
|
|
9134
|
+
catch (error) {
|
|
9135
|
+
console.error('Failed to capture screenshot:', error);
|
|
9136
|
+
// Reset loading state on error
|
|
9137
|
+
this.takingScreenshot = false;
|
|
9138
|
+
// Show modal anyway
|
|
9139
|
+
this.showModal = true;
|
|
9084
9140
|
}
|
|
9085
|
-
const scrollY = window.scrollY;
|
|
9086
|
-
document.documentElement.style.top = `-${scrollY}px`;
|
|
9087
|
-
window.scrollTo(0, parseInt(document.documentElement.style.top || '0') * -1);
|
|
9088
|
-
document.documentElement.classList.add('feedback-modal-screenshot-open');
|
|
9089
9141
|
};
|
|
9090
|
-
this.
|
|
9142
|
+
this.openCanvasEditor = (event) => {
|
|
9143
|
+
if (event) {
|
|
9144
|
+
event.stopPropagation();
|
|
9145
|
+
}
|
|
9091
9146
|
this.showModal = false;
|
|
9092
|
-
this.
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9147
|
+
this.showCanvasEditor = true;
|
|
9148
|
+
// Initialize canvas after a short delay to ensure DOM is ready
|
|
9149
|
+
setTimeout(() => {
|
|
9150
|
+
this.initializeCanvas();
|
|
9151
|
+
}, 100);
|
|
9152
|
+
};
|
|
9153
|
+
this.closeCanvasEditor = () => {
|
|
9154
|
+
this.showCanvasEditor = false;
|
|
9155
|
+
this.showModal = true;
|
|
9156
|
+
};
|
|
9157
|
+
this.saveAnnotations = () => {
|
|
9158
|
+
if (this.canvasRef) {
|
|
9159
|
+
// Create final image with annotations
|
|
9160
|
+
const finalDataUrl = this.canvasRef.toDataURL('image/png');
|
|
9161
|
+
this.encodedScreenshot = finalDataUrl;
|
|
9162
|
+
}
|
|
9163
|
+
this.showCanvasEditor = false;
|
|
9164
|
+
this.showModal = true;
|
|
9099
9165
|
};
|
|
9100
|
-
this.
|
|
9101
|
-
|
|
9102
|
-
if (this.hasSelectedElement)
|
|
9166
|
+
this.initializeCanvas = () => {
|
|
9167
|
+
if (!this.canvasRef || !this.originalImageData)
|
|
9103
9168
|
return;
|
|
9104
|
-
|
|
9105
|
-
|
|
9106
|
-
|
|
9107
|
-
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9126
|
-
|
|
9127
|
-
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
|
|
9139
|
-
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9169
|
+
this.canvasContext = this.canvasRef.getContext('2d');
|
|
9170
|
+
const img = new Image();
|
|
9171
|
+
img.onload = () => {
|
|
9172
|
+
// Set canvas to original image dimensions
|
|
9173
|
+
this.canvasRef.width = img.width;
|
|
9174
|
+
this.canvasRef.height = img.height;
|
|
9175
|
+
// Get available container dimensions
|
|
9176
|
+
const containerWidth = this.canvasRef.parentElement.clientWidth - 32; // Account for reduced padding (16px * 2)
|
|
9177
|
+
const containerHeight = this.canvasRef.parentElement.clientHeight - 32;
|
|
9178
|
+
// Calculate scale factors for both dimensions
|
|
9179
|
+
const scaleX = containerWidth / img.width;
|
|
9180
|
+
const scaleY = containerHeight / img.height;
|
|
9181
|
+
// Use the smaller scale to ensure complete image fits
|
|
9182
|
+
const scale = Math.min(scaleX, scaleY, 1); // Never scale up, only down
|
|
9183
|
+
// Calculate final display dimensions
|
|
9184
|
+
const displayWidth = img.width * scale;
|
|
9185
|
+
const displayHeight = img.height * scale;
|
|
9186
|
+
// Set CSS size for display (this scales the canvas visually)
|
|
9187
|
+
this.canvasRef.style.width = `${displayWidth}px`;
|
|
9188
|
+
this.canvasRef.style.height = `${displayHeight}px`;
|
|
9189
|
+
console.log('Canvas initialized with complete image fit:', {
|
|
9190
|
+
originalWidth: img.width,
|
|
9191
|
+
originalHeight: img.height,
|
|
9192
|
+
displayWidth,
|
|
9193
|
+
displayHeight,
|
|
9194
|
+
scale,
|
|
9195
|
+
scaleX,
|
|
9196
|
+
scaleY,
|
|
9197
|
+
containerWidth,
|
|
9198
|
+
containerHeight,
|
|
9199
|
+
usingScale: scale === scaleX ? 'width-limited' : 'height-limited'
|
|
9200
|
+
});
|
|
9201
|
+
// Draw the original image at full resolution
|
|
9202
|
+
this.canvasContext.drawImage(img, 0, 0);
|
|
9203
|
+
// Redraw existing annotations
|
|
9204
|
+
this.redrawAnnotations();
|
|
9205
|
+
};
|
|
9206
|
+
img.src = this.originalImageData;
|
|
9207
|
+
};
|
|
9208
|
+
this.redrawAnnotations = () => {
|
|
9209
|
+
if (!this.canvasContext)
|
|
9210
|
+
return;
|
|
9211
|
+
// Clear and redraw background image
|
|
9212
|
+
const img = new Image();
|
|
9213
|
+
img.onload = () => {
|
|
9214
|
+
this.canvasContext.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height);
|
|
9215
|
+
this.canvasContext.drawImage(img, 0, 0);
|
|
9216
|
+
// Draw all annotations
|
|
9217
|
+
this.annotations.forEach(annotation => {
|
|
9218
|
+
this.drawAnnotation(annotation);
|
|
9219
|
+
});
|
|
9220
|
+
};
|
|
9221
|
+
img.src = this.originalImageData;
|
|
9222
|
+
};
|
|
9223
|
+
this.drawAnnotation = (annotation) => {
|
|
9224
|
+
if (!this.canvasContext)
|
|
9151
9225
|
return;
|
|
9226
|
+
this.canvasContext.strokeStyle = annotation.color;
|
|
9227
|
+
this.canvasContext.lineWidth = annotation.lineWidth;
|
|
9228
|
+
this.canvasContext.lineCap = 'round';
|
|
9229
|
+
this.canvasContext.lineJoin = 'round';
|
|
9230
|
+
switch (annotation.type) {
|
|
9231
|
+
case 'rectangle':
|
|
9232
|
+
this.canvasContext.strokeRect(annotation.startX, annotation.startY, annotation.width, annotation.height);
|
|
9233
|
+
// Rectangle resize handles disabled for now
|
|
9234
|
+
break;
|
|
9235
|
+
case 'line':
|
|
9236
|
+
this.canvasContext.beginPath();
|
|
9237
|
+
this.canvasContext.moveTo(annotation.startX, annotation.startY);
|
|
9238
|
+
this.canvasContext.lineTo(annotation.endX, annotation.endY);
|
|
9239
|
+
this.canvasContext.stroke();
|
|
9240
|
+
// Draw resize handles if this annotation is hovered
|
|
9241
|
+
if (this.hoveredAnnotation === annotation) {
|
|
9242
|
+
this.drawLineResizeHandles(annotation);
|
|
9243
|
+
}
|
|
9244
|
+
break;
|
|
9245
|
+
case 'arrow':
|
|
9246
|
+
this.drawArrow(annotation.startX, annotation.startY, annotation.endX, annotation.endY);
|
|
9247
|
+
// Draw resize handles if this annotation is hovered
|
|
9248
|
+
if (this.hoveredAnnotation === annotation) {
|
|
9249
|
+
this.drawLineResizeHandles(annotation); // Same as line
|
|
9250
|
+
}
|
|
9251
|
+
break;
|
|
9252
|
+
case 'text':
|
|
9253
|
+
const fontSize = annotation.fontSize || 16;
|
|
9254
|
+
this.canvasContext.fillStyle = annotation.color;
|
|
9255
|
+
this.canvasContext.font = `${fontSize}px Arial`;
|
|
9256
|
+
this.canvasContext.fillText(annotation.text, annotation.x, annotation.y);
|
|
9257
|
+
// Draw resize handle if this annotation is hovered
|
|
9258
|
+
if (this.hoveredAnnotation === annotation) {
|
|
9259
|
+
this.drawTextResizeHandle(annotation);
|
|
9260
|
+
}
|
|
9261
|
+
break;
|
|
9152
9262
|
}
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
this.
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
this.
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9263
|
+
};
|
|
9264
|
+
// Draw resize handle for text annotation
|
|
9265
|
+
this.drawTextResizeHandle = (annotation) => {
|
|
9266
|
+
if (!this.canvasContext || annotation.type !== 'text')
|
|
9267
|
+
return;
|
|
9268
|
+
const fontSize = annotation.fontSize || 16;
|
|
9269
|
+
const textWidth = this.getTextWidth(annotation.text, fontSize);
|
|
9270
|
+
const handleSize = 8;
|
|
9271
|
+
const handleX = annotation.x + textWidth;
|
|
9272
|
+
const handleY = annotation.y;
|
|
9273
|
+
// Draw resize handle (small square) - using widget primary color
|
|
9274
|
+
this.canvasContext.fillStyle = '#0070F4'; // var(--feedback-primary-color)
|
|
9275
|
+
this.canvasContext.strokeStyle = '#ffffff';
|
|
9276
|
+
this.canvasContext.lineWidth = 2;
|
|
9277
|
+
this.canvasContext.fillRect(handleX - handleSize / 2, handleY - handleSize / 2, handleSize, handleSize);
|
|
9278
|
+
this.canvasContext.strokeRect(handleX - handleSize / 2, handleY - handleSize / 2, handleSize, handleSize);
|
|
9279
|
+
};
|
|
9280
|
+
this.drawArrow = (fromX, fromY, toX, toY) => {
|
|
9281
|
+
const headlen = 15; // Arrow head length
|
|
9282
|
+
const angle = Math.atan2(toY - fromY, toX - fromX);
|
|
9283
|
+
// Draw line
|
|
9284
|
+
this.canvasContext.beginPath();
|
|
9285
|
+
this.canvasContext.moveTo(fromX, fromY);
|
|
9286
|
+
this.canvasContext.lineTo(toX, toY);
|
|
9287
|
+
this.canvasContext.stroke();
|
|
9288
|
+
// Draw arrow head
|
|
9289
|
+
this.canvasContext.beginPath();
|
|
9290
|
+
this.canvasContext.moveTo(toX, toY);
|
|
9291
|
+
this.canvasContext.lineTo(toX - headlen * Math.cos(angle - Math.PI / 6), toY - headlen * Math.sin(angle - Math.PI / 6));
|
|
9292
|
+
this.canvasContext.moveTo(toX, toY);
|
|
9293
|
+
this.canvasContext.lineTo(toX - headlen * Math.cos(angle + Math.PI / 6), toY - headlen * Math.sin(angle + Math.PI / 6));
|
|
9294
|
+
this.canvasContext.stroke();
|
|
9295
|
+
};
|
|
9296
|
+
this.undoLastAnnotation = () => {
|
|
9297
|
+
this.annotations = this.annotations.slice(0, -1);
|
|
9298
|
+
this.redrawAnnotations();
|
|
9299
|
+
};
|
|
9300
|
+
// Handle color slot editing
|
|
9301
|
+
this.handleColorSlotClick = (colorIndex) => {
|
|
9302
|
+
if (this.editingColorIndex === colorIndex) {
|
|
9303
|
+
// If already editing this slot, just select the color
|
|
9304
|
+
this.canvasDrawingColor = this.defaultColors[colorIndex];
|
|
9305
|
+
this.showColorPicker = false;
|
|
9306
|
+
this.editingColorIndex = -1;
|
|
9167
9307
|
}
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
this.
|
|
9308
|
+
else {
|
|
9309
|
+
// Start editing this color slot
|
|
9310
|
+
this.editingColorIndex = colorIndex;
|
|
9311
|
+
this.showColorPicker = true;
|
|
9312
|
+
this.canvasDrawingColor = this.defaultColors[colorIndex];
|
|
9171
9313
|
}
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9314
|
+
};
|
|
9315
|
+
// Update color in slot
|
|
9316
|
+
this.updateColorSlot = (newColor) => {
|
|
9317
|
+
if (this.editingColorIndex >= 0 && this.editingColorIndex < this.defaultColors.length) {
|
|
9318
|
+
this.defaultColors[this.editingColorIndex] = newColor;
|
|
9319
|
+
this.canvasDrawingColor = newColor;
|
|
9320
|
+
this.showColorPicker = false;
|
|
9321
|
+
this.editingColorIndex = -1;
|
|
9322
|
+
// Force reactivity
|
|
9323
|
+
this.defaultColors = [...this.defaultColors];
|
|
9175
9324
|
}
|
|
9176
9325
|
};
|
|
9326
|
+
// Handle color picker input without closing
|
|
9327
|
+
this.handleColorPickerInput = (event) => {
|
|
9328
|
+
event.stopPropagation();
|
|
9329
|
+
const newColor = event.target.value;
|
|
9330
|
+
if (this.editingColorIndex >= 0 && this.editingColorIndex < this.defaultColors.length) {
|
|
9331
|
+
this.defaultColors[this.editingColorIndex] = newColor;
|
|
9332
|
+
this.canvasDrawingColor = newColor;
|
|
9333
|
+
// Force reactivity
|
|
9334
|
+
this.defaultColors = [...this.defaultColors];
|
|
9335
|
+
}
|
|
9336
|
+
};
|
|
9337
|
+
// Handle color picker click to prevent closing
|
|
9338
|
+
this.handleColorPickerClick = (event) => {
|
|
9339
|
+
event.stopPropagation();
|
|
9340
|
+
};
|
|
9341
|
+
// Close color picker
|
|
9342
|
+
this.closeColorPicker = () => {
|
|
9343
|
+
this.showColorPicker = false;
|
|
9344
|
+
this.editingColorIndex = -1;
|
|
9345
|
+
};
|
|
9346
|
+
// Check if point is in resize handle for any annotation type
|
|
9347
|
+
this.isPointInResizeHandle = (x, y, annotation) => {
|
|
9348
|
+
const handleSize = 8;
|
|
9349
|
+
switch (annotation.type) {
|
|
9350
|
+
case 'text':
|
|
9351
|
+
const textWidth = this.getTextWidth(annotation.text, annotation.fontSize || 16);
|
|
9352
|
+
const handleX = annotation.x + textWidth;
|
|
9353
|
+
const handleY = annotation.y;
|
|
9354
|
+
return x >= handleX - handleSize / 2 && x <= handleX + handleSize / 2 &&
|
|
9355
|
+
y >= handleY - handleSize / 2 && y <= handleY + handleSize / 2;
|
|
9356
|
+
case 'rectangle':
|
|
9357
|
+
// Rectangle resizing disabled for now
|
|
9358
|
+
return false;
|
|
9359
|
+
case 'line':
|
|
9360
|
+
case 'arrow':
|
|
9361
|
+
// Check both endpoint handles
|
|
9362
|
+
const lineHandles = [
|
|
9363
|
+
{ x: annotation.startX, y: annotation.startY, point: 'start' },
|
|
9364
|
+
{ x: annotation.endX, y: annotation.endY, point: 'end' }
|
|
9365
|
+
];
|
|
9366
|
+
for (const handle of lineHandles) {
|
|
9367
|
+
if (x >= handle.x - handleSize / 2 && x <= handle.x + handleSize / 2 &&
|
|
9368
|
+
y >= handle.y - handleSize / 2 && y <= handle.y + handleSize / 2) {
|
|
9369
|
+
return handle.point; // Return which endpoint was clicked
|
|
9370
|
+
}
|
|
9371
|
+
}
|
|
9372
|
+
return false;
|
|
9373
|
+
default:
|
|
9374
|
+
return false;
|
|
9375
|
+
}
|
|
9376
|
+
};
|
|
9377
|
+
// Get text width for resize handle positioning
|
|
9378
|
+
this.getTextWidth = (text, fontSize) => {
|
|
9379
|
+
// Approximate text width calculation
|
|
9380
|
+
return text.length * fontSize * 0.6;
|
|
9381
|
+
};
|
|
9382
|
+
// Start text resize
|
|
9383
|
+
this.startTextResize = (annotation, startPos) => {
|
|
9384
|
+
this.isResizing = true;
|
|
9385
|
+
this.resizingAnnotation = annotation;
|
|
9386
|
+
this.resizeStartSize = annotation.fontSize || 16;
|
|
9387
|
+
this.dragStartPos = startPos;
|
|
9388
|
+
};
|
|
9389
|
+
// Handle text resize
|
|
9390
|
+
this.handleTextResize = (currentPos) => {
|
|
9391
|
+
if (!this.resizingAnnotation || !this.dragStartPos)
|
|
9392
|
+
return;
|
|
9393
|
+
const deltaX = currentPos.x - this.dragStartPos.x;
|
|
9394
|
+
const deltaY = currentPos.y - this.dragStartPos.y;
|
|
9395
|
+
const avgDelta = (deltaX + deltaY) / 2;
|
|
9396
|
+
// Calculate new font size (minimum 8px, maximum 72px)
|
|
9397
|
+
const newSize = Math.max(8, Math.min(72, this.resizeStartSize + avgDelta * 0.5));
|
|
9398
|
+
// Update annotation font size
|
|
9399
|
+
const index = this.annotations.findIndex(a => a === this.resizingAnnotation);
|
|
9400
|
+
if (index !== -1) {
|
|
9401
|
+
this.annotations[index] = Object.assign(Object.assign({}, this.resizingAnnotation), { fontSize: Math.round(newSize) });
|
|
9402
|
+
this.resizingAnnotation = this.annotations[index];
|
|
9403
|
+
}
|
|
9404
|
+
this.redrawAnnotations();
|
|
9405
|
+
};
|
|
9406
|
+
// Start resize for any annotation type
|
|
9407
|
+
this.startResize = (annotation, handle, startPos) => {
|
|
9408
|
+
this.isResizing = true;
|
|
9409
|
+
this.resizingAnnotation = annotation;
|
|
9410
|
+
this.resizeHandle = handle;
|
|
9411
|
+
this.dragStartPos = startPos;
|
|
9412
|
+
// Store original values for different annotation types
|
|
9413
|
+
if (annotation.type === 'text') {
|
|
9414
|
+
this.resizeStartSize = annotation.fontSize || 16;
|
|
9415
|
+
}
|
|
9416
|
+
};
|
|
9417
|
+
// Enhanced mouse down handler with resize detection for all annotation types
|
|
9418
|
+
this.handleCanvasMouseDown = (event) => {
|
|
9419
|
+
if (!this.canvasRef)
|
|
9420
|
+
return;
|
|
9421
|
+
// Close color picker if open
|
|
9422
|
+
if (this.showColorPicker) {
|
|
9423
|
+
this.closeColorPicker();
|
|
9424
|
+
}
|
|
9425
|
+
const coords = this.getCanvasCoordinates(event);
|
|
9426
|
+
// Check if clicking on existing annotation first
|
|
9427
|
+
const found = this.findAnnotationAt(coords.x, coords.y);
|
|
9428
|
+
if (found) {
|
|
9429
|
+
// Check if clicking on resize handle for any annotation type
|
|
9430
|
+
const handle = this.isPointInResizeHandle(coords.x, coords.y, found.annotation);
|
|
9431
|
+
if (handle) {
|
|
9432
|
+
this.startResize(found.annotation, handle, coords);
|
|
9433
|
+
this.canvasRef.style.cursor = 'nw-resize';
|
|
9434
|
+
return;
|
|
9435
|
+
}
|
|
9436
|
+
// Start dragging existing annotation
|
|
9437
|
+
if (!this.isDrawing) {
|
|
9438
|
+
this.isDragging = true;
|
|
9439
|
+
this.draggedAnnotation = found.annotation;
|
|
9440
|
+
this.dragStartPos = coords;
|
|
9441
|
+
this.canvasRef.style.cursor = 'grabbing';
|
|
9442
|
+
return;
|
|
9443
|
+
}
|
|
9444
|
+
}
|
|
9445
|
+
// Original drawing logic
|
|
9446
|
+
this.isDrawing = true;
|
|
9447
|
+
if (this.canvasDrawingTool === 'text') {
|
|
9448
|
+
const text = prompt('Enter text:');
|
|
9449
|
+
if (text) {
|
|
9450
|
+
const annotation = {
|
|
9451
|
+
type: 'text',
|
|
9452
|
+
x: coords.x,
|
|
9453
|
+
y: coords.y,
|
|
9454
|
+
text,
|
|
9455
|
+
color: this.canvasDrawingColor,
|
|
9456
|
+
fontSize: 16
|
|
9457
|
+
};
|
|
9458
|
+
this.annotations = [...this.annotations, annotation];
|
|
9459
|
+
this.redrawAnnotations();
|
|
9460
|
+
}
|
|
9461
|
+
this.isDrawing = false;
|
|
9462
|
+
}
|
|
9463
|
+
else {
|
|
9464
|
+
this.currentAnnotation = {
|
|
9465
|
+
type: this.canvasDrawingTool,
|
|
9466
|
+
startX: coords.x,
|
|
9467
|
+
startY: coords.y,
|
|
9468
|
+
color: this.canvasDrawingColor,
|
|
9469
|
+
lineWidth: this.canvasLineWidth
|
|
9470
|
+
};
|
|
9471
|
+
}
|
|
9472
|
+
};
|
|
9473
|
+
this.handleCanvasMouseMove = (event) => {
|
|
9474
|
+
if (!this.canvasRef)
|
|
9475
|
+
return;
|
|
9476
|
+
const coords = this.getCanvasCoordinates(event);
|
|
9477
|
+
// Handle resizing for any annotation type
|
|
9478
|
+
if (this.isResizing && this.resizingAnnotation) {
|
|
9479
|
+
this.handleResize(coords);
|
|
9480
|
+
return;
|
|
9481
|
+
}
|
|
9482
|
+
// Handle dragging existing annotation
|
|
9483
|
+
if (this.isDragging && this.draggedAnnotation && this.dragStartPos) {
|
|
9484
|
+
const deltaX = coords.x - this.dragStartPos.x;
|
|
9485
|
+
const deltaY = coords.y - this.dragStartPos.y;
|
|
9486
|
+
// Update annotation position
|
|
9487
|
+
const updatedAnnotation = Object.assign({}, this.draggedAnnotation);
|
|
9488
|
+
switch (updatedAnnotation.type) {
|
|
9489
|
+
case 'rectangle':
|
|
9490
|
+
updatedAnnotation.startX += deltaX;
|
|
9491
|
+
updatedAnnotation.startY += deltaY;
|
|
9492
|
+
break;
|
|
9493
|
+
case 'line':
|
|
9494
|
+
case 'arrow':
|
|
9495
|
+
updatedAnnotation.startX += deltaX;
|
|
9496
|
+
updatedAnnotation.startY += deltaY;
|
|
9497
|
+
updatedAnnotation.endX += deltaX;
|
|
9498
|
+
updatedAnnotation.endY += deltaY;
|
|
9499
|
+
break;
|
|
9500
|
+
case 'text':
|
|
9501
|
+
updatedAnnotation.x += deltaX;
|
|
9502
|
+
updatedAnnotation.y += deltaY;
|
|
9503
|
+
break;
|
|
9504
|
+
}
|
|
9505
|
+
// Update annotation in array
|
|
9506
|
+
const index = this.annotations.findIndex(a => a === this.draggedAnnotation);
|
|
9507
|
+
if (index !== -1) {
|
|
9508
|
+
this.annotations[index] = updatedAnnotation;
|
|
9509
|
+
this.draggedAnnotation = updatedAnnotation;
|
|
9510
|
+
}
|
|
9511
|
+
this.dragStartPos = coords;
|
|
9512
|
+
this.redrawAnnotations();
|
|
9513
|
+
return;
|
|
9514
|
+
}
|
|
9515
|
+
// Handle drawing new annotation
|
|
9516
|
+
if (this.isDrawing && this.currentAnnotation) {
|
|
9517
|
+
if (this.canvasDrawingTool === 'rectangle') {
|
|
9518
|
+
this.currentAnnotation.width = coords.x - this.currentAnnotation.startX;
|
|
9519
|
+
this.currentAnnotation.height = coords.y - this.currentAnnotation.startY;
|
|
9520
|
+
}
|
|
9521
|
+
else {
|
|
9522
|
+
this.currentAnnotation.endX = coords.x;
|
|
9523
|
+
this.currentAnnotation.endY = coords.y;
|
|
9524
|
+
}
|
|
9525
|
+
this.redrawAnnotations();
|
|
9526
|
+
this.drawAnnotation(this.currentAnnotation);
|
|
9527
|
+
return;
|
|
9528
|
+
}
|
|
9529
|
+
// Handle hover states and cursor changes
|
|
9530
|
+
const found = this.findAnnotationAt(coords.x, coords.y);
|
|
9531
|
+
if (found) {
|
|
9532
|
+
// Check if hovering over resize handle for any annotation type
|
|
9533
|
+
const handle = this.isPointInResizeHandle(coords.x, coords.y, found.annotation);
|
|
9534
|
+
if (handle) {
|
|
9535
|
+
this.canvasRef.style.cursor = 'nw-resize';
|
|
9536
|
+
this.hoveredAnnotation = found.annotation;
|
|
9537
|
+
this.redrawAnnotations();
|
|
9538
|
+
return;
|
|
9539
|
+
}
|
|
9540
|
+
// Regular hover over annotation
|
|
9541
|
+
this.canvasRef.style.cursor = 'grab';
|
|
9542
|
+
if (this.hoveredAnnotation !== found.annotation) {
|
|
9543
|
+
this.hoveredAnnotation = found.annotation;
|
|
9544
|
+
this.redrawAnnotations();
|
|
9545
|
+
}
|
|
9546
|
+
}
|
|
9547
|
+
else {
|
|
9548
|
+
// No annotation under cursor
|
|
9549
|
+
this.canvasRef.style.cursor = 'crosshair';
|
|
9550
|
+
if (this.hoveredAnnotation) {
|
|
9551
|
+
this.hoveredAnnotation = null;
|
|
9552
|
+
this.redrawAnnotations();
|
|
9553
|
+
}
|
|
9554
|
+
}
|
|
9555
|
+
};
|
|
9556
|
+
this.handleCanvasMouseUp = () => {
|
|
9557
|
+
// Handle end of text resizing
|
|
9558
|
+
if (this.isResizing) {
|
|
9559
|
+
this.isResizing = false;
|
|
9560
|
+
this.resizingAnnotation = null;
|
|
9561
|
+
this.dragStartPos = null;
|
|
9562
|
+
this.resizeHandle = false;
|
|
9563
|
+
if (this.canvasRef) {
|
|
9564
|
+
this.canvasRef.style.cursor = 'crosshair';
|
|
9565
|
+
}
|
|
9566
|
+
return;
|
|
9567
|
+
}
|
|
9568
|
+
// Handle end of dragging
|
|
9569
|
+
if (this.isDragging) {
|
|
9570
|
+
this.isDragging = false;
|
|
9571
|
+
this.draggedAnnotation = null;
|
|
9572
|
+
this.dragStartPos = null;
|
|
9573
|
+
if (this.canvasRef) {
|
|
9574
|
+
this.canvasRef.style.cursor = 'crosshair';
|
|
9575
|
+
}
|
|
9576
|
+
return;
|
|
9577
|
+
}
|
|
9578
|
+
// Handle end of drawing
|
|
9579
|
+
if (!this.isDrawing || !this.currentAnnotation)
|
|
9580
|
+
return;
|
|
9581
|
+
this.isDrawing = false;
|
|
9582
|
+
this.annotations = [...this.annotations, this.currentAnnotation];
|
|
9583
|
+
this.currentAnnotation = null;
|
|
9584
|
+
this.redrawAnnotations();
|
|
9585
|
+
};
|
|
9586
|
+
// Draw resize handles for rectangle annotation
|
|
9587
|
+
this.drawRectangleResizeHandles = (annotation) => {
|
|
9588
|
+
if (!this.canvasContext || annotation.type !== 'rectangle')
|
|
9589
|
+
return;
|
|
9590
|
+
const handleSize = 8;
|
|
9591
|
+
const left = annotation.startX;
|
|
9592
|
+
const top = annotation.startY;
|
|
9593
|
+
const right = annotation.startX + annotation.width;
|
|
9594
|
+
const bottom = annotation.startY + annotation.height;
|
|
9595
|
+
// Define handle positions (4 corners)
|
|
9596
|
+
const handles = [
|
|
9597
|
+
{ x: left, y: top },
|
|
9598
|
+
{ x: right, y: top },
|
|
9599
|
+
{ x: right, y: bottom },
|
|
9600
|
+
{ x: left, y: bottom } // Bottom-left
|
|
9601
|
+
];
|
|
9602
|
+
// Draw each handle
|
|
9603
|
+
this.canvasContext.fillStyle = '#0070F4'; // Primary color
|
|
9604
|
+
this.canvasContext.strokeStyle = '#ffffff';
|
|
9605
|
+
this.canvasContext.lineWidth = 2;
|
|
9606
|
+
handles.forEach(handle => {
|
|
9607
|
+
this.canvasContext.fillRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
|
|
9608
|
+
this.canvasContext.strokeRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
|
|
9609
|
+
});
|
|
9610
|
+
};
|
|
9611
|
+
// Draw resize handles for line/arrow annotation
|
|
9612
|
+
this.drawLineResizeHandles = (annotation) => {
|
|
9613
|
+
if (!this.canvasContext || (annotation.type !== 'line' && annotation.type !== 'arrow'))
|
|
9614
|
+
return;
|
|
9615
|
+
const handleSize = 8;
|
|
9616
|
+
// Define handle positions (2 endpoints)
|
|
9617
|
+
const handles = [
|
|
9618
|
+
{ x: annotation.startX, y: annotation.startY },
|
|
9619
|
+
{ x: annotation.endX, y: annotation.endY } // End point
|
|
9620
|
+
];
|
|
9621
|
+
// Draw each handle
|
|
9622
|
+
this.canvasContext.fillStyle = '#0070F4'; // Primary color
|
|
9623
|
+
this.canvasContext.strokeStyle = '#ffffff';
|
|
9624
|
+
this.canvasContext.lineWidth = 2;
|
|
9625
|
+
handles.forEach(handle => {
|
|
9626
|
+
this.canvasContext.fillRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
|
|
9627
|
+
this.canvasContext.strokeRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
|
|
9628
|
+
});
|
|
9629
|
+
};
|
|
9630
|
+
// Convert screen coordinates to canvas coordinates
|
|
9631
|
+
this.getCanvasCoordinates = (event) => {
|
|
9632
|
+
if (!this.canvasRef)
|
|
9633
|
+
return { x: 0, y: 0 };
|
|
9634
|
+
const rect = this.canvasRef.getBoundingClientRect();
|
|
9635
|
+
// Calculate the scale factor between display size and actual canvas size
|
|
9636
|
+
const scaleX = this.canvasRef.width / rect.width;
|
|
9637
|
+
const scaleY = this.canvasRef.height / rect.height;
|
|
9638
|
+
const x = (event.clientX - rect.left) * scaleX;
|
|
9639
|
+
const y = (event.clientY - rect.top) * scaleY;
|
|
9640
|
+
return { x, y };
|
|
9641
|
+
};
|
|
9642
|
+
// Find annotation under mouse cursor
|
|
9643
|
+
this.findAnnotationAt = (x, y) => {
|
|
9644
|
+
// Check in reverse order (top to bottom)
|
|
9645
|
+
for (let i = this.annotations.length - 1; i >= 0; i--) {
|
|
9646
|
+
const annotation = this.annotations[i];
|
|
9647
|
+
if (this.isPointInAnnotation(x, y, annotation)) {
|
|
9648
|
+
return { annotation, index: i };
|
|
9649
|
+
}
|
|
9650
|
+
}
|
|
9651
|
+
return null;
|
|
9652
|
+
};
|
|
9653
|
+
// Check if point is within annotation bounds
|
|
9654
|
+
this.isPointInAnnotation = (x, y, annotation) => {
|
|
9655
|
+
const tolerance = 10; // Click tolerance
|
|
9656
|
+
switch (annotation.type) {
|
|
9657
|
+
case 'rectangle':
|
|
9658
|
+
const left = Math.min(annotation.startX, annotation.startX + annotation.width);
|
|
9659
|
+
const right = Math.max(annotation.startX, annotation.startX + annotation.width);
|
|
9660
|
+
const top = Math.min(annotation.startY, annotation.startY + annotation.height);
|
|
9661
|
+
const bottom = Math.max(annotation.startY, annotation.startY + annotation.height);
|
|
9662
|
+
return x >= left - tolerance && x <= right + tolerance &&
|
|
9663
|
+
y >= top - tolerance && y <= bottom + tolerance;
|
|
9664
|
+
case 'line':
|
|
9665
|
+
case 'arrow':
|
|
9666
|
+
// Distance from point to line
|
|
9667
|
+
const A = annotation.endY - annotation.startY;
|
|
9668
|
+
const B = annotation.startX - annotation.endX;
|
|
9669
|
+
const C = annotation.endX * annotation.startY - annotation.startX * annotation.endY;
|
|
9670
|
+
const distance = Math.abs(A * x + B * y + C) / Math.sqrt(A * A + B * B);
|
|
9671
|
+
return distance <= tolerance;
|
|
9672
|
+
case 'text':
|
|
9673
|
+
// Simple bounding box for text
|
|
9674
|
+
return x >= annotation.x - tolerance && x <= annotation.x + 100 &&
|
|
9675
|
+
y >= annotation.y - 20 && y <= annotation.y + tolerance;
|
|
9676
|
+
default:
|
|
9677
|
+
return false;
|
|
9678
|
+
}
|
|
9679
|
+
};
|
|
9680
|
+
// Handle resize for different annotation types
|
|
9681
|
+
this.handleResize = (currentPos) => {
|
|
9682
|
+
if (!this.resizingAnnotation || !this.dragStartPos)
|
|
9683
|
+
return;
|
|
9684
|
+
const annotation = this.resizingAnnotation;
|
|
9685
|
+
const index = this.annotations.findIndex(a => a === annotation);
|
|
9686
|
+
if (index === -1)
|
|
9687
|
+
return;
|
|
9688
|
+
let updatedAnnotation = Object.assign({}, annotation);
|
|
9689
|
+
switch (annotation.type) {
|
|
9690
|
+
case 'text':
|
|
9691
|
+
// Text resize logic (existing)
|
|
9692
|
+
const deltaX = currentPos.x - this.dragStartPos.x;
|
|
9693
|
+
const deltaY = currentPos.y - this.dragStartPos.y;
|
|
9694
|
+
const avgDelta = (deltaX + deltaY) / 2;
|
|
9695
|
+
const newSize = Math.max(8, Math.min(72, this.resizeStartSize + avgDelta * 0.5));
|
|
9696
|
+
updatedAnnotation.fontSize = Math.round(newSize);
|
|
9697
|
+
break;
|
|
9698
|
+
case 'rectangle':
|
|
9699
|
+
// Rectangle resizing disabled for now
|
|
9700
|
+
return;
|
|
9701
|
+
case 'line':
|
|
9702
|
+
case 'arrow':
|
|
9703
|
+
// Line/arrow resize logic - move endpoints
|
|
9704
|
+
if (this.resizeHandle === 'start') {
|
|
9705
|
+
updatedAnnotation.startX = currentPos.x;
|
|
9706
|
+
updatedAnnotation.startY = currentPos.y;
|
|
9707
|
+
}
|
|
9708
|
+
else if (this.resizeHandle === 'end') {
|
|
9709
|
+
updatedAnnotation.endX = currentPos.x;
|
|
9710
|
+
updatedAnnotation.endY = currentPos.y;
|
|
9711
|
+
}
|
|
9712
|
+
break;
|
|
9713
|
+
}
|
|
9714
|
+
// Update annotation in array
|
|
9715
|
+
this.annotations[index] = updatedAnnotation;
|
|
9716
|
+
this.resizingAnnotation = updatedAnnotation;
|
|
9717
|
+
this.redrawAnnotations();
|
|
9718
|
+
};
|
|
9177
9719
|
this.sending = false;
|
|
9178
9720
|
this.formMessage = '';
|
|
9179
9721
|
this.formEmail = '';
|
|
@@ -9187,6 +9729,26 @@ const FeedbackModal = class {
|
|
|
9187
9729
|
this.selectedRating = -1;
|
|
9188
9730
|
this.overlayVisible = false;
|
|
9189
9731
|
this.isAnimating = false;
|
|
9732
|
+
this.takingScreenshot = false;
|
|
9733
|
+
this.showPreviewModal = false;
|
|
9734
|
+
this.showCanvasEditor = false;
|
|
9735
|
+
this.canvasDrawingTool = 'rectangle';
|
|
9736
|
+
this.canvasDrawingColor = '#ff0000';
|
|
9737
|
+
this.canvasLineWidth = 3;
|
|
9738
|
+
this.isDrawing = false;
|
|
9739
|
+
this.annotations = [];
|
|
9740
|
+
this.currentAnnotation = null;
|
|
9741
|
+
this.isDragging = false;
|
|
9742
|
+
this.draggedAnnotation = null;
|
|
9743
|
+
this.dragStartPos = null;
|
|
9744
|
+
this.showColorPicker = false;
|
|
9745
|
+
this.editingColorIndex = -1;
|
|
9746
|
+
this.isResizing = false;
|
|
9747
|
+
this.resizingAnnotation = null;
|
|
9748
|
+
this.resizeStartSize = 16;
|
|
9749
|
+
this.hoveredAnnotation = null;
|
|
9750
|
+
this.resizeHandle = false;
|
|
9751
|
+
this.defaultColors = ['#ff0000', '#00ff00', '#0000ff', '#000000'];
|
|
9190
9752
|
this.customFont = false;
|
|
9191
9753
|
this.emailAddress = '';
|
|
9192
9754
|
this.hideEmail = false;
|
|
@@ -9217,10 +9779,14 @@ const FeedbackModal = class {
|
|
|
9217
9779
|
this.ratingPlaceholder = 'Was this page helpful?';
|
|
9218
9780
|
this.ratingStarsPlaceholder = 'How would you rate this page?';
|
|
9219
9781
|
this.sendButtonText = 'Send';
|
|
9220
|
-
this.screenshotButtonText = 'Add a screenshot';
|
|
9221
9782
|
this.screenshotAttachedText = 'Screenshot attached';
|
|
9783
|
+
this.screenshotButtonText = 'Add a screenshot';
|
|
9784
|
+
this.screenshotTakingText = 'Taking screenshot...';
|
|
9222
9785
|
this.screenshotTopbarText = 'Select an element on this page';
|
|
9223
9786
|
this.successMessage = '';
|
|
9787
|
+
this.canvasEditorTitle = 'Edit screenshot';
|
|
9788
|
+
this.canvasEditorCancelText = 'Cancel';
|
|
9789
|
+
this.canvasEditorSaveText = 'Save';
|
|
9224
9790
|
}
|
|
9225
9791
|
componentWillLoad() {
|
|
9226
9792
|
if (this.fetchData)
|
|
@@ -9244,15 +9810,10 @@ const FeedbackModal = class {
|
|
|
9244
9810
|
}
|
|
9245
9811
|
}
|
|
9246
9812
|
resetOverflow() {
|
|
9813
|
+
// Just clean up any stray classes, don't add/remove during screenshot
|
|
9247
9814
|
document.documentElement.classList.remove('feedback-modal-screenshot-open');
|
|
9248
9815
|
document.documentElement.classList.remove('feedback-modal-screenshot-open--scroll');
|
|
9249
|
-
document.documentElement.classList.
|
|
9250
|
-
// Only restore scroll position if we previously modified it
|
|
9251
|
-
if (document.documentElement.style.top) {
|
|
9252
|
-
window.scrollTo(0, parseInt(document.documentElement.style.top || '0') * -1);
|
|
9253
|
-
document.documentElement.style.top = '';
|
|
9254
|
-
}
|
|
9255
|
-
window.addEventListener('scroll', this.onScrollDebounced);
|
|
9816
|
+
document.documentElement.classList.remove('feedback-modal-screenshot-closing');
|
|
9256
9817
|
}
|
|
9257
9818
|
handleMessageInput(event) {
|
|
9258
9819
|
this.formMessage = event.target.value;
|
|
@@ -9260,31 +9821,48 @@ const FeedbackModal = class {
|
|
|
9260
9821
|
handleEmailInput(event) {
|
|
9261
9822
|
this.formEmail = event.target.value;
|
|
9262
9823
|
}
|
|
9263
|
-
|
|
9824
|
+
captureViewportScreenshot() {
|
|
9264
9825
|
return new Promise((resolve, reject) => {
|
|
9265
9826
|
requestAnimationFrame(() => {
|
|
9266
|
-
|
|
9267
|
-
|
|
9268
|
-
|
|
9269
|
-
|
|
9270
|
-
|
|
9271
|
-
|
|
9827
|
+
// Get viewport dimensions and scroll position
|
|
9828
|
+
const viewportWidth = window.innerWidth;
|
|
9829
|
+
const viewportHeight = window.innerHeight;
|
|
9830
|
+
const scrollX = window.scrollX || window.pageXOffset || 0;
|
|
9831
|
+
const scrollY = window.scrollY || window.pageYOffset || 0;
|
|
9832
|
+
// Capture exactly what the user sees in their viewport
|
|
9833
|
+
html2canvasPro(document.documentElement, {
|
|
9834
|
+
x: scrollX,
|
|
9835
|
+
y: scrollY,
|
|
9836
|
+
width: viewportWidth,
|
|
9837
|
+
height: viewportHeight,
|
|
9838
|
+
scrollX: 0,
|
|
9839
|
+
scrollY: 0,
|
|
9840
|
+
allowTaint: false,
|
|
9272
9841
|
useCORS: true,
|
|
9273
9842
|
scale: 1,
|
|
9843
|
+
backgroundColor: '#ffffff',
|
|
9844
|
+
logging: false,
|
|
9845
|
+
foreignObjectRendering: false,
|
|
9846
|
+
imageTimeout: 15000,
|
|
9847
|
+
windowWidth: viewportWidth,
|
|
9848
|
+
windowHeight: viewportHeight,
|
|
9849
|
+
removeContainer: true,
|
|
9850
|
+
ignoreElements: (element) => {
|
|
9851
|
+
// Ignore all feedback modal elements
|
|
9852
|
+
return element.closest('feedback-modal') !== null ||
|
|
9853
|
+
element.classList.contains('feedback-overlay') ||
|
|
9854
|
+
element.classList.contains('feedback-modal-screenshot-header') ||
|
|
9855
|
+
element.tagName === 'FEEDBACK-MODAL' ||
|
|
9856
|
+
element.tagName === 'FEEDBACK-BUTTON';
|
|
9857
|
+
}
|
|
9274
9858
|
})
|
|
9275
9859
|
.then((canvas) => {
|
|
9276
|
-
const
|
|
9277
|
-
|
|
9278
|
-
// Use the same color as HTML highlight
|
|
9279
|
-
context.strokeStyle = 'rgba(0, 123, 255, 0.8)'; // Example color
|
|
9280
|
-
context.lineWidth = 3;
|
|
9281
|
-
context.strokeRect(this.selectedElementBounds.left + window.scrollX, this.selectedElementBounds.top + window.scrollY, this.selectedElementBounds.width, this.selectedElementBounds.height);
|
|
9282
|
-
}
|
|
9283
|
-
const dataUrl = canvas.toDataURL();
|
|
9860
|
+
const dataUrl = canvas.toDataURL('image/png');
|
|
9861
|
+
console.log('Screenshot captured successfully, size:', canvas.width, 'x', canvas.height);
|
|
9284
9862
|
resolve(dataUrl);
|
|
9285
9863
|
})
|
|
9286
9864
|
.catch((error) => {
|
|
9287
|
-
console.error('Failed to capture screenshot:', error);
|
|
9865
|
+
console.error('Failed to capture viewport screenshot:', error);
|
|
9288
9866
|
reject(error);
|
|
9289
9867
|
});
|
|
9290
9868
|
});
|
|
@@ -9299,12 +9877,8 @@ const FeedbackModal = class {
|
|
|
9299
9877
|
handleRatingChange(newRating) {
|
|
9300
9878
|
this.selectedRating = newRating;
|
|
9301
9879
|
}
|
|
9302
|
-
// Remove the preview modal toggle function
|
|
9303
|
-
// togglePreviewModal() {
|
|
9304
|
-
// this.showPreviewModal = !this.showPreviewModal;
|
|
9305
|
-
// }
|
|
9306
9880
|
render() {
|
|
9307
|
-
return (index.h("div", { class: `feedback-modal-wrapper ${this.customFont ? 'feedback-modal-wrapper--custom-font' : ''}` }, this.
|
|
9881
|
+
return (index.h("div", { class: `feedback-modal-wrapper ${this.customFont ? 'feedback-modal-wrapper--custom-font' : ''}` }, this.showModal && (index.h("div", { class: `feedback-overlay ${this.isAnimating ? 'feedback-overlay--visible' : ''}` })), this.showModal && (index.h("div", { class: `feedback-modal-content feedback-modal-content--${this.modalPosition} ${this.isAnimating ? 'feedback-modal-content--open' : ''}`, ref: (el) => (this.modalContent = el) }, index.h("div", { class: "feedback-modal-header" }, !this.formSuccess && !this.formError ? (index.h("span", null, this.modalTitle)) : this.formSuccess ? (index.h("span", null, this.modalTitleSuccess)) : (index.h("span", null, this.modalTitleError)), index.h("button", { class: "feedback-modal-close", onClick: this.close }, index.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" }, index.h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), index.h("line", { x1: "6", y1: "6", x2: "18", y2: "18" })))), index.h("div", { class: "feedback-modal-body" }, !this.formSuccess && !this.formError ? (index.h("form", { onSubmit: this.handleSubmit }, !this.hideRating && (index.h("div", { class: "feedback-modal-rating" }, this.ratingMode === 'thumbs' ? (index.h("div", { class: "feedback-modal-rating-content" }, index.h("span", { class: "feedback-modal-input-heading" }, this.ratingPlaceholder), index.h("div", { class: "feedback-modal-rating-buttons feedback-modal-rating-buttons--thumbs" }, index.h("button", { title: "Yes", class: `feedback-modal-rating-button ${this.selectedRating === 1
|
|
9308
9882
|
? 'feedback-modal-rating-button--selected'
|
|
9309
9883
|
: ''}`, onClick: (event) => {
|
|
9310
9884
|
event.preventDefault();
|
|
@@ -9319,7 +9893,8 @@ const FeedbackModal = class {
|
|
|
9319
9893
|
: ''}`, onClick: (event) => {
|
|
9320
9894
|
event.preventDefault();
|
|
9321
9895
|
this.handleRatingChange(rating);
|
|
9322
|
-
} }, index.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" }, index.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" })))))))))), index.h("div", { class: "feedback-modal-text" }, index.h("textarea", { placeholder: this.messagePlaceholder, value: this.formMessage, onInput: (event) => this.handleMessageInput(event) })), !this.hideEmail && (index.h("div", { class: "feedback-modal-email" }, index.h("input", { placeholder: this.emailPlaceholder, type: "email", onInput: (event) => this.handleEmailInput(event), value: this.formEmail, required: this.isEmailRequired }))), index.h("div", { class: "feedback-verification" }, index.h("input", { type: "text", name: "verification", style: { display: 'none' }, onInput: (event) => this.handleVerification(event), value: this.formVerification })), !this.hidePrivacyPolicy && (index.h("div", { class: "feedback-modal-privacy" }, index.h("input", { type: "checkbox", id: "privacyPolicy", onChange: (ev) => this.handleCheckboxChange(ev), required: true }), index.h("span", { innerHTML: this.privacyPolicyText }))), index.h("div", { class: `feedback-modal-buttons ${this.hideScreenshotButton ? 'single' : ''}` }, !this.hideScreenshotButton && (index.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 && (index.h("div", { class: "screenshot-preview" }, index.h("img", { src: this.encodedScreenshot, alt: "Screenshot Preview" }))), !this.encodedScreenshot && (index.h("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24", viewBox: "0 -960 960 960", width: "24" }, index.h("path", { d: "M680-80v-120H560v-80h120v-120h80v120h120v80H760v120h-80ZM200-200v-200h80v120h120v80H200Zm0-360v-200h200v80H280v120h-80Zm480 0v-120H560v-80h200v200h-80Z" }))), this.
|
|
9896
|
+
} }, index.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" }, index.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" })))))))))), index.h("div", { class: "feedback-modal-text" }, index.h("textarea", { placeholder: this.messagePlaceholder, value: this.formMessage, onInput: (event) => this.handleMessageInput(event) })), !this.hideEmail && (index.h("div", { class: "feedback-modal-email" }, index.h("input", { placeholder: this.emailPlaceholder, type: "email", onInput: (event) => this.handleEmailInput(event), value: this.formEmail, required: this.isEmailRequired }))), index.h("div", { class: "feedback-verification" }, index.h("input", { type: "text", name: "verification", style: { display: 'none' }, onInput: (event) => this.handleVerification(event), value: this.formVerification })), !this.hidePrivacyPolicy && (index.h("div", { class: "feedback-modal-privacy" }, index.h("input", { type: "checkbox", id: "privacyPolicy", onChange: (ev) => this.handleCheckboxChange(ev), required: true }), index.h("span", { innerHTML: this.privacyPolicyText }))), index.h("div", { class: `feedback-modal-buttons ${this.hideScreenshotButton ? 'single' : ''}` }, !this.hideScreenshotButton && (index.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 && (index.h("div", { class: "screenshot-preview", onClick: this.openCanvasEditor }, index.h("img", { src: this.encodedScreenshot, alt: "Screenshot Preview" }))), !this.encodedScreenshot && !this.takingScreenshot && (index.h("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24", viewBox: "0 -960 960 960", width: "24" }, index.h("path", { d: "M680-80v-120H560v-80h120v-120h80v120h120v80H760v120h-80ZM200-200v-200h80v120h120v80H200Zm0-360v-200h200v80H280v120h-80Zm480 0v-120H560v-80h200v200h-80Z" }))), this.takingScreenshot && (index.h("div", { class: "screenshot-loading" }, index.h("svg", { width: "16", height: "16", viewBox: "0 0 16 16" }, index.h("circle", { cx: "8", cy: "8", r: "6", fill: "none", stroke: "#666", "stroke-width": "2", "stroke-dasharray": "6 6", "transform-origin": "8 8" }, index.h("animateTransform", { attributeName: "transform", type: "rotate", values: "0 8 8;360 8 8", dur: "1s", repeatCount: "indefinite" }))))), this.takingScreenshot ? this.screenshotTakingText :
|
|
9897
|
+
this.encodedScreenshot ? this.screenshotAttachedText : this.screenshotButtonText)), index.h("button", { class: "feedback-modal-button feedback-modal-button--submit", type: "submit", disabled: this.sending }, this.sendButtonText)))) : this.formSuccess && !this.formError ? (index.h("div", { class: "feedback-modal-success" }, index.h("p", { class: "feedback-modal-message" }, this.successMessage))) : this.formError && this.formErrorStatus == 404 ? (index.h("p", { class: "feedback-modal-message" }, this.errorMessage404)) : this.formError && this.formErrorStatus == 403 ? (index.h("p", { class: "feedback-modal-message" }, this.errorMessage403)) : this.formError ? (index.h("p", { class: "feedback-modal-message" }, this.errorMessage)) : (index.h("span", null))), index.h("div", { class: "feedback-modal-footer" }, index.h("div", { class: "feedback-logo", style: { display: this.whitelabel ? 'none' : 'block' } }, "Powered by", ' ', index.h("a", { target: "_blank", href: "https://pushfeedback.com" }, "PushFeedback.com")), this.footerText && (index.h("div", { class: "feedback-footer-text" }, index.h("span", { innerHTML: this.footerText })))))), this.showCanvasEditor && (index.h("div", { class: "canvas-editor-overlay" }, index.h("div", { class: "canvas-editor-modal" }, index.h("div", { class: "canvas-editor-header" }, index.h("div", { class: "canvas-editor-title" }, index.h("h3", null, this.canvasEditorTitle)), index.h("div", { class: "canvas-editor-toolbar" }, index.h("div", { class: "toolbar-section" }, index.h("div", { class: "tool-group" }, index.h("button", { class: `tool-btn ${this.canvasDrawingTool === 'rectangle' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'rectangle', title: "Rectangle" }, index.h("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }))), index.h("button", { class: `tool-btn ${this.canvasDrawingTool === 'line' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'line', title: "Line" }, index.h("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("line", { x1: "5", y1: "12", x2: "19", y2: "12" }))), index.h("button", { class: `tool-btn ${this.canvasDrawingTool === 'arrow' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'arrow', title: "Arrow" }, index.h("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("line", { x1: "7", y1: "17", x2: "17", y2: "7" }), index.h("polyline", { points: "7,7 17,7 17,17" }))), index.h("button", { class: `tool-btn ${this.canvasDrawingTool === 'text' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'text', title: "Text" }, index.h("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("polyline", { points: "4,7 4,4 20,4 20,7" }), index.h("line", { x1: "9", y1: "20", x2: "15", y2: "20" }), index.h("line", { x1: "12", y1: "4", x2: "12", y2: "20" }))), index.h("div", { class: "toolbar-divider" }), index.h("button", { class: "tool-btn undo-btn", onClick: this.undoLastAnnotation, disabled: this.annotations.length === 0, title: "Undo" }, index.h("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("polyline", { points: "1,4 1,10 7,10" }), index.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" }))))), index.h("div", { class: "toolbar-section" }, index.h("div", { class: "color-palette" }, this.defaultColors.map((color, index$1) => (index.h("div", { class: "color-slot-wrapper" }, index.h("button", { class: `color-btn ${this.canvasDrawingColor === color ? 'active' : ''} ${this.editingColorIndex === index$1 ? 'editing' : ''}`, style: { backgroundColor: color }, onClick: () => this.handleColorSlotClick(index$1), title: `Color ${index$1 + 1} - Click to customize` }, this.editingColorIndex === index$1 && (index.h("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "white", "stroke-width": "2" }, index.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$1 && this.showColorPicker && (index.h("div", { class: "color-picker-dropdown" }, index.h("input", { type: "color", value: color, onInput: (e) => this.handleColorPickerInput(e), onClick: (e) => this.handleColorPickerClick(e) })))))))), index.h("div", { class: "toolbar-section" }, index.h("div", { class: "size-control" }, index.h("input", { type: "range", min: "1", max: "10", value: this.canvasLineWidth, onInput: (e) => this.canvasLineWidth = parseInt(e.target.value), class: "size-slider" }), index.h("span", { class: "size-value" }, this.canvasLineWidth, "px"))), index.h("div", { class: "toolbar-section" }, index.h("button", { class: "action-btn secondary", onClick: this.closeCanvasEditor }, this.canvasEditorCancelText), index.h("button", { class: "action-btn primary", onClick: this.saveAnnotations }, this.canvasEditorSaveText))), index.h("div", { class: "canvas-editor-content" }, index.h("canvas", { ref: (el) => this.canvasRef = el, class: "annotation-canvas", onMouseDown: this.handleCanvasMouseDown, onMouseMove: this.handleCanvasMouseMove, onMouseUp: this.handleCanvasMouseUp, onMouseLeave: this.handleCanvasMouseUp }))))))));
|
|
9323
9898
|
}
|
|
9324
9899
|
componentDidRender() {
|
|
9325
9900
|
if (this.showModal) {
|