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