pushfeedback 0.1.81 → 0.1.83
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/canvas-editor_3.cjs.entry.js +82 -57
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/pushfeedback.cjs.js +1 -1
- package/dist/collection/components/canvas-editor/canvas-editor.js +57 -42
- package/dist/collection/components/feedback-button/feedback-button.js +2 -2
- package/dist/collection/components/feedback-modal/feedback-modal.css +80 -0
- package/dist/collection/components/feedback-modal/feedback-modal.js +40 -12
- package/dist/components/canvas-editor2.js +57 -42
- package/dist/components/feedback-button.js +2 -2
- package/dist/components/feedback-modal2.js +24 -13
- package/dist/esm/canvas-editor_3.entry.js +82 -57
- package/dist/esm/loader.js +1 -1
- package/dist/esm/pushfeedback.js +1 -1
- package/dist/pushfeedback/p-1338beed.entry.js +1 -0
- package/dist/pushfeedback/pushfeedback.css +1 -1
- package/dist/pushfeedback/pushfeedback.esm.js +1 -1
- package/dist/types/components/feedback-modal/feedback-modal.d.ts +1 -0
- package/dist/types/components.d.ts +2 -0
- package/package.json +1 -1
- package/dist/pushfeedback/p-4836008c.entry.js +0 -1
|
@@ -51,7 +51,7 @@ export class FeedbackModal {
|
|
|
51
51
|
else if (res.status === 202) {
|
|
52
52
|
const limitExceededBody = {
|
|
53
53
|
message: "You received a new feedback entry. You've reached the 25 message limit for your current plan. Upgrade to continue receiving feedback.",
|
|
54
|
-
id: await res.json()
|
|
54
|
+
id: await res.json(),
|
|
55
55
|
};
|
|
56
56
|
this.feedbackSent.emit({ feedback: limitExceededBody });
|
|
57
57
|
this.formSuccess = true;
|
|
@@ -94,7 +94,7 @@ export class FeedbackModal {
|
|
|
94
94
|
this.hasSelectedElement = false;
|
|
95
95
|
this.encodedScreenshot = null;
|
|
96
96
|
// Remove highlight from ALL selected elements
|
|
97
|
-
document.querySelectorAll('.feedback-modal-element-selected').forEach(el => {
|
|
97
|
+
document.querySelectorAll('.feedback-modal-element-selected').forEach((el) => {
|
|
98
98
|
el.classList.remove('feedback-modal-element-selected');
|
|
99
99
|
});
|
|
100
100
|
// Reset form states
|
|
@@ -187,6 +187,7 @@ export class FeedbackModal {
|
|
|
187
187
|
this.rating = undefined;
|
|
188
188
|
this.metadata = undefined;
|
|
189
189
|
this.fetchData = true;
|
|
190
|
+
this.embedded = false;
|
|
190
191
|
this.emailPlaceholder = 'Email address (optional)';
|
|
191
192
|
this.errorMessage = 'Please try again later.';
|
|
192
193
|
this.errorMessage403 = 'The request URL does not match the one defined in PushFeedback for this project.';
|
|
@@ -231,6 +232,10 @@ export class FeedbackModal {
|
|
|
231
232
|
if (this.ratingMode == 'thumbs' && this.rating == 0) {
|
|
232
233
|
this.selectedRating = 5;
|
|
233
234
|
}
|
|
235
|
+
// Automatically show modal when embedded
|
|
236
|
+
if (this.embedded) {
|
|
237
|
+
this.showModal = true;
|
|
238
|
+
}
|
|
234
239
|
}
|
|
235
240
|
async fetchProjectData() {
|
|
236
241
|
try {
|
|
@@ -267,7 +272,7 @@ export class FeedbackModal {
|
|
|
267
272
|
// Wait for grecaptcha to be available
|
|
268
273
|
let attempts = 0;
|
|
269
274
|
while (!window['grecaptcha'] && attempts < 50) {
|
|
270
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
275
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
271
276
|
attempts++;
|
|
272
277
|
}
|
|
273
278
|
if (!window['grecaptcha']) {
|
|
@@ -279,7 +284,7 @@ export class FeedbackModal {
|
|
|
279
284
|
window['grecaptcha'].ready(async () => {
|
|
280
285
|
try {
|
|
281
286
|
const token = await window['grecaptcha'].execute(this.recaptchaSiteKey, {
|
|
282
|
-
action: 'submit_feedback'
|
|
287
|
+
action: 'submit_feedback',
|
|
283
288
|
});
|
|
284
289
|
resolve(token);
|
|
285
290
|
}
|
|
@@ -317,23 +322,28 @@ export class FeedbackModal {
|
|
|
317
322
|
this.selectedRating = newRating;
|
|
318
323
|
}
|
|
319
324
|
render() {
|
|
320
|
-
return (h("div", { class: `feedback-modal-wrapper ${this.customFont ? 'feedback-modal-wrapper--custom-font' : ''}
|
|
325
|
+
return (h("div", { class: `feedback-modal-wrapper ${this.customFont ? 'feedback-modal-wrapper--custom-font' : ''} ${this.embedded ? 'feedback-modal-wrapper--embedded' : ''}`, part: "wrapper" }, this.showCanvasEditor && (h("canvas-editor", { ref: (el) => (this.canvasEditorRef = el), exportparts: "overlay: canvas-editor-overlay, modal: canvas-editor-modal, header: canvas-editor-header, title: canvas-editor-title, toolbar: canvas-editor-toolbar, tool-button: canvas-editor-tool-button, cancel-button: canvas-editor-cancel-button, save-button: canvas-editor-save-button, content: canvas-editor-content, canvas: canvas-editor-canvas", "canvas-editor-title": this.screenshotEditorTitle, "canvas-editor-cancel-text": this.screenshotEditorCancelText, "canvas-editor-save-text": this.screenshotEditorSaveText, "screenshot-taking-text": this.screenshotTakingText, "screenshot-attached-text": this.screenshotAttachedText, "screenshot-button-text": this.screenshotButtonText, "auto-start-screenshot": this.autoStartCapture, "existing-screenshot": this.encodedScreenshot || '', "edit-text-button-text": this.screenshotEditTextButtonText, "size-label-text": this.screenshotSizeLabelText, "border-label-text": this.screenshotBorderLabelText, "edit-text-prompt-text": this.screenshotEditTextPromptText, "screenshot-error-general": this.screenshotErrorGeneral, "screenshot-error-permission": this.screenshotErrorPermission, "screenshot-error-not-supported": this.screenshotErrorNotSupported, "screenshot-error-not-found": this.screenshotErrorNotFound, "screenshot-error-cancelled": this.screenshotErrorCancelled, "screenshot-error-browser-not-supported": this.screenshotErrorBrowserNotSupported, "screenshot-error-unexpected": this.screenshotErrorUnexpected, onScreenshotReady: this.handleScreenshotReady, onScreenshotCancelled: this.handleScreenshotCancelled, onScreenshotFailed: this.handleScreenshotError })), this.showScreenshotError && (h("div", { class: "screenshot-error-notification" }, h("div", { class: "screenshot-error-content" }, h("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("circle", { cx: "12", cy: "12", r: "10" }), h("line", { x1: "15", y1: "9", x2: "9", y2: "15" }), h("line", { x1: "9", y1: "9", x2: "15", y2: "15" })), h("span", null, this.screenshotError), h("button", { class: "error-close-btn", onClick: () => (this.showScreenshotError = false), title: "Close" }, h("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), h("line", { x1: "6", y1: "6", x2: "18", y2: "18" })))))), this.showModal && !this.embedded && (h("div", { class: `feedback-overlay ${this.isAnimating ? 'feedback-overlay--visible' : ''}`, part: "overlay" })), this.showModal && (h("div", { class: `feedback-modal-content feedback-modal-content--${this.modalPosition} ${this.isAnimating ? 'feedback-modal-content--open' : ''} ${this.embedded ? 'feedback-modal-content--embedded' : ''}`, part: "modal", ref: (el) => (this.modalContent = el) }, h("div", { class: `feedback-modal-header ${(this.formSuccess && !this.successMessage) || (this.formError && !this.errorMessage)
|
|
326
|
+
? 'feedback-modal-header--no-content'
|
|
327
|
+
: ''}`, part: "header" }, h("div", { class: "feedback-modal-header-content" }, !this.formSuccess && !this.formError ? (h("div", { class: "feedback-modal-header-text" }, h("span", { class: "feedback-modal-title", part: "title" }, this.modalTitle), !this.whitelabel && (h("span", { class: "feedback-modal-powered-by", part: "powered-by" }, "Powered by", ' ', h("a", { target: "_blank", href: "https://pushfeedback.com" }, "PushFeedback"))))) : this.formSuccess ? (h("span", { class: "feedback-modal-title", part: "title" }, this.modalTitleSuccess)) : (h("span", { class: "feedback-modal-title", part: "title" }, this.modalTitleError))), !this.embedded && (h("button", { class: "feedback-modal-close", part: "close-button", 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", part: "body" }, !this.formSuccess && !this.formError ? (h("form", { part: "form", onSubmit: this.handleSubmit }, !this.hideRating && (h("div", { class: "feedback-modal-rating", part: "rating" }, this.ratingMode === 'thumbs' ? (h("div", { class: "feedback-modal-rating-content" }, h("span", { class: "feedback-modal-input-heading", part: "rating-title" }, this.ratingPlaceholder), h("div", { class: "feedback-modal-rating-buttons feedback-modal-rating-buttons--thumbs", part: "rating-buttons" }, h("button", { title: "Yes", class: `feedback-modal-rating-button feedback-modal-rating-button--positive ${this.selectedRating === 1
|
|
321
328
|
? 'feedback-modal-rating-button--selected'
|
|
322
|
-
: ''}`, onClick: (event) => {
|
|
329
|
+
: ''}`, part: "rating-button rating-button-positive", onClick: (event) => {
|
|
323
330
|
event.preventDefault();
|
|
324
331
|
this.handleRatingChange(1);
|
|
325
|
-
} }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#5F6368", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3" }))), h("button", { title: "No", class: `feedback-modal-rating-button ${this.selectedRating === 5
|
|
332
|
+
} }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#5F6368", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3" }))), h("button", { title: "No", class: `feedback-modal-rating-button feedback-modal-rating-button--negative ${this.selectedRating === 5
|
|
326
333
|
? 'feedback-modal-rating-button--selected'
|
|
327
|
-
: ''}`, onClick: (event) => {
|
|
334
|
+
: ''}`, part: "rating-button rating-button-negative", onClick: (event) => {
|
|
328
335
|
event.preventDefault();
|
|
329
336
|
this.handleRatingChange(5);
|
|
330
|
-
} }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#5F6368", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17" })))))) : (h("div", { class: "feedback-modal-rating-content" }, h("span", { class: "feedback-modal-input-heading" }, this.ratingStarsPlaceholder), h("div", { class: "feedback-modal-rating-buttons feedback-modal-rating-buttons--stars" }, [1, 2, 3, 4, 5].map((rating) => (h("button", { key: rating, class: `feedback-modal-rating-button ${this.selectedRating >= rating
|
|
337
|
+
} }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#5F6368", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17" })))))) : (h("div", { class: "feedback-modal-rating-content" }, h("span", { class: "feedback-modal-input-heading", part: "rating-title" }, this.ratingStarsPlaceholder), h("div", { class: "feedback-modal-rating-buttons feedback-modal-rating-buttons--stars", part: "rating-buttons" }, [1, 2, 3, 4, 5].map((rating) => (h("button", { key: rating, class: `feedback-modal-rating-button ${this.selectedRating >= rating
|
|
331
338
|
? 'feedback-modal-rating-button--selected'
|
|
332
|
-
: ''}`, onClick: (event) => {
|
|
339
|
+
: ''}`, part: "rating-button", onClick: (event) => {
|
|
333
340
|
event.preventDefault();
|
|
334
341
|
this.handleRatingChange(rating);
|
|
335
|
-
} }, 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' : ''}
|
|
336
|
-
|
|
342
|
+
} }, 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", { part: "message-input", placeholder: this.messagePlaceholder, value: this.formMessage, onInput: (event) => this.handleMessageInput(event) })), !this.hideEmail && (h("div", { class: "feedback-modal-email" }, h("input", { part: "email-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", part: "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' : ''}`, part: "buttons" }, !this.hideScreenshotButton && (h("button", { type: "button", class: `feedback-modal-button feedback-modal-button--screenshot ${this.encodedScreenshot ? 'feedback-modal-button--active' : ''}`, part: "screenshot-button", 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 24 24", fill: "none", stroke: "#666", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "feather-loader" }, h("line", { x1: "12", y1: "2", x2: "12", y2: "6" }), h("line", { x1: "12", y1: "18", x2: "12", y2: "22" }), h("line", { x1: "4.93", y1: "4.93", x2: "7.76", y2: "7.76" }), h("line", { x1: "16.24", y1: "16.24", x2: "19.07", y2: "19.07" }), h("line", { x1: "2", y1: "12", x2: "6", y2: "12" }), h("line", { x1: "18", y1: "12", x2: "22", y2: "12" }), h("line", { x1: "4.93", y1: "19.07", x2: "7.76", y2: "16.24" }), h("line", { x1: "16.24", y1: "7.76", x2: "19.07", y2: "4.93" })))), this.takingScreenshot
|
|
343
|
+
? this.screenshotTakingText
|
|
344
|
+
: this.encodedScreenshot
|
|
345
|
+
? this.screenshotAttachedText
|
|
346
|
+
: this.screenshotButtonText)), h("button", { class: "feedback-modal-button feedback-modal-button--submit", part: "submit-button", type: "submit", disabled: this.sending }, this.sendButtonText)))) : this.formSuccess && !this.formError ? (h("div", { class: "feedback-modal-success" }, h("p", { class: "feedback-modal-message", part: "success-message" }, this.successMessage))) : this.formError && this.formErrorStatus == 404 ? (h("p", { class: "feedback-modal-message", part: "error-message" }, this.errorMessage404)) : this.formError && this.formErrorStatus == 403 ? (h("p", { class: "feedback-modal-message", part: "error-message" }, this.errorMessage403)) : this.formError ? (h("p", { class: "feedback-modal-message", part: "error-message" }, this.errorMessage)) : (h("span", null))), !this.formSuccess && !this.formError && (this.recaptchaEnabled || this.footerText) && (h("div", { class: "feedback-modal-footer", part: "footer" }, h("div", { class: "feedback-footer-combined" }, this.recaptchaEnabled && h("span", { innerHTML: this.recaptchaText }), this.recaptchaEnabled && this.footerText && ' ', this.footerText && h("span", { innerHTML: this.footerText }))))))));
|
|
337
347
|
}
|
|
338
348
|
componentDidRender() {
|
|
339
349
|
if (this.showModal) {
|
|
@@ -650,6 +660,24 @@ export class FeedbackModal {
|
|
|
650
660
|
"reflect": false,
|
|
651
661
|
"defaultValue": "true"
|
|
652
662
|
},
|
|
663
|
+
"embedded": {
|
|
664
|
+
"type": "boolean",
|
|
665
|
+
"mutable": false,
|
|
666
|
+
"complexType": {
|
|
667
|
+
"original": "boolean",
|
|
668
|
+
"resolved": "boolean",
|
|
669
|
+
"references": {}
|
|
670
|
+
},
|
|
671
|
+
"required": false,
|
|
672
|
+
"optional": false,
|
|
673
|
+
"docs": {
|
|
674
|
+
"tags": [],
|
|
675
|
+
"text": ""
|
|
676
|
+
},
|
|
677
|
+
"attribute": "embedded",
|
|
678
|
+
"reflect": false,
|
|
679
|
+
"defaultValue": "false"
|
|
680
|
+
},
|
|
653
681
|
"emailPlaceholder": {
|
|
654
682
|
"type": "string",
|
|
655
683
|
"mutable": false,
|
|
@@ -33,7 +33,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
33
33
|
this.hideAllFeedbackElements();
|
|
34
34
|
try {
|
|
35
35
|
// Wait a moment for UI to update before capturing
|
|
36
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
36
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
37
37
|
// Capture viewport screenshot using browser API
|
|
38
38
|
const dataUrl = await this.captureViewportScreenshot();
|
|
39
39
|
this.originalImageData = dataUrl;
|
|
@@ -61,14 +61,14 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
61
61
|
this.hideAllFeedbackElements = () => {
|
|
62
62
|
// Hide all feedback buttons and modals on the page
|
|
63
63
|
const feedbackElements = document.querySelectorAll('feedback-button, feedback-modal');
|
|
64
|
-
feedbackElements.forEach(element => {
|
|
64
|
+
feedbackElements.forEach((element) => {
|
|
65
65
|
element.style.visibility = 'hidden';
|
|
66
66
|
});
|
|
67
67
|
};
|
|
68
68
|
this.showAllFeedbackElements = () => {
|
|
69
69
|
// Show all feedback buttons and modals on the page
|
|
70
70
|
const feedbackElements = document.querySelectorAll('feedback-button, feedback-modal');
|
|
71
|
-
feedbackElements.forEach(element => {
|
|
71
|
+
feedbackElements.forEach((element) => {
|
|
72
72
|
element.style.visibility = 'visible';
|
|
73
73
|
});
|
|
74
74
|
};
|
|
@@ -124,7 +124,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
124
124
|
const scaleY = containerHeight / img.height;
|
|
125
125
|
// Use a more aggressive scaling approach for large screens
|
|
126
126
|
// Allow scaling up to 1.5x on very large screens, but still maintain aspect ratio
|
|
127
|
-
const maxScale = window.innerWidth > 1920 ? 1.5 :
|
|
127
|
+
const maxScale = window.innerWidth > 1920 ? 1.5 : window.innerWidth > 1200 ? 1.2 : 1;
|
|
128
128
|
const scale = Math.min(scaleX, scaleY, maxScale);
|
|
129
129
|
// Calculate final display dimensions
|
|
130
130
|
const displayWidth = img.width * scale;
|
|
@@ -148,7 +148,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
148
148
|
this.canvasContext.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height);
|
|
149
149
|
this.canvasContext.drawImage(img, 0, 0);
|
|
150
150
|
// Draw all annotations
|
|
151
|
-
this.annotations.forEach(annotation => {
|
|
151
|
+
this.annotations.forEach((annotation) => {
|
|
152
152
|
this.drawAnnotation(annotation);
|
|
153
153
|
});
|
|
154
154
|
};
|
|
@@ -198,7 +198,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
198
198
|
this.drawLineResizeHandles(annotation);
|
|
199
199
|
}
|
|
200
200
|
break;
|
|
201
|
-
case 'text':
|
|
201
|
+
case 'text': {
|
|
202
202
|
const fontSize = annotation.fontSize || 24;
|
|
203
203
|
this.canvasContext.fillStyle = annotation.color;
|
|
204
204
|
this.canvasContext.font = `${fontSize}px Arial`;
|
|
@@ -208,6 +208,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
208
208
|
this.drawTextSelectionIndicator(annotation);
|
|
209
209
|
}
|
|
210
210
|
break;
|
|
211
|
+
}
|
|
211
212
|
}
|
|
212
213
|
};
|
|
213
214
|
// Draw selection indicator for shapes
|
|
@@ -279,7 +280,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
279
280
|
};
|
|
280
281
|
this.deleteSelectedAnnotation = () => {
|
|
281
282
|
if (this.selectedAnnotation) {
|
|
282
|
-
const index = this.annotations.findIndex(a => a === this.selectedAnnotation);
|
|
283
|
+
const index = this.annotations.findIndex((a) => a === this.selectedAnnotation);
|
|
283
284
|
if (index !== -1) {
|
|
284
285
|
this.annotations = this.annotations.filter((_, i) => i !== index);
|
|
285
286
|
this.selectedAnnotation = null;
|
|
@@ -350,26 +351,32 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
350
351
|
this.isPointInResizeHandle = (x, y, annotation) => {
|
|
351
352
|
const handleSize = 8;
|
|
352
353
|
switch (annotation.type) {
|
|
353
|
-
case 'rectangle':
|
|
354
|
+
case 'rectangle': {
|
|
354
355
|
const right = annotation.startX + annotation.width;
|
|
355
356
|
const bottom = annotation.startY + annotation.height;
|
|
356
357
|
// Only check bottom-right corner handle
|
|
357
|
-
return x >= right - handleSize / 2 &&
|
|
358
|
-
|
|
358
|
+
return (x >= right - handleSize / 2 &&
|
|
359
|
+
x <= right + handleSize / 2 &&
|
|
360
|
+
y >= bottom - handleSize / 2 &&
|
|
361
|
+
y <= bottom + handleSize / 2);
|
|
362
|
+
}
|
|
359
363
|
case 'line':
|
|
360
|
-
case 'arrow':
|
|
364
|
+
case 'arrow': {
|
|
361
365
|
// Check both endpoint handles
|
|
362
366
|
const lineHandles = [
|
|
363
367
|
{ x: annotation.startX, y: annotation.startY, point: 'start' },
|
|
364
|
-
{ x: annotation.endX, y: annotation.endY, point: 'end' }
|
|
368
|
+
{ x: annotation.endX, y: annotation.endY, point: 'end' },
|
|
365
369
|
];
|
|
366
370
|
for (const handle of lineHandles) {
|
|
367
|
-
if (x >= handle.x - handleSize / 2 &&
|
|
368
|
-
|
|
371
|
+
if (x >= handle.x - handleSize / 2 &&
|
|
372
|
+
x <= handle.x + handleSize / 2 &&
|
|
373
|
+
y >= handle.y - handleSize / 2 &&
|
|
374
|
+
y <= handle.y + handleSize / 2) {
|
|
369
375
|
return handle.point; // Return which endpoint was clicked
|
|
370
376
|
}
|
|
371
377
|
}
|
|
372
378
|
return false;
|
|
379
|
+
}
|
|
373
380
|
default:
|
|
374
381
|
return false;
|
|
375
382
|
}
|
|
@@ -398,13 +405,13 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
398
405
|
// Define handle positions (2 endpoints)
|
|
399
406
|
const handles = [
|
|
400
407
|
{ x: annotation.startX, y: annotation.startY },
|
|
401
|
-
{ x: annotation.endX, y: annotation.endY } // End point
|
|
408
|
+
{ x: annotation.endX, y: annotation.endY }, // End point
|
|
402
409
|
];
|
|
403
410
|
// Draw each handle
|
|
404
411
|
this.canvasContext.fillStyle = '#0070F4'; // Primary color
|
|
405
412
|
this.canvasContext.strokeStyle = '#ffffff';
|
|
406
413
|
this.canvasContext.lineWidth = 2;
|
|
407
|
-
handles.forEach(handle => {
|
|
414
|
+
handles.forEach((handle) => {
|
|
408
415
|
this.canvasContext.fillRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
|
|
409
416
|
this.canvasContext.strokeRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
|
|
410
417
|
});
|
|
@@ -425,12 +432,12 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
425
432
|
if (!this.resizingAnnotation || !this.dragStartPos)
|
|
426
433
|
return;
|
|
427
434
|
const annotation = this.resizingAnnotation;
|
|
428
|
-
const index = this.annotations.findIndex(a => a === annotation);
|
|
435
|
+
const index = this.annotations.findIndex((a) => a === annotation);
|
|
429
436
|
if (index === -1)
|
|
430
437
|
return;
|
|
431
|
-
|
|
438
|
+
const updatedAnnotation = Object.assign({}, annotation);
|
|
432
439
|
switch (annotation.type) {
|
|
433
|
-
case 'rectangle':
|
|
440
|
+
case 'rectangle': {
|
|
434
441
|
// Rectangle resize logic - only bottom-right corner
|
|
435
442
|
const rectDeltaX = currentPos.x - this.dragStartPos.x;
|
|
436
443
|
const rectDeltaY = currentPos.y - this.dragStartPos.y;
|
|
@@ -438,6 +445,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
438
445
|
updatedAnnotation.width = Math.max(10, this.resizeStartDimensions.width + rectDeltaX);
|
|
439
446
|
updatedAnnotation.height = Math.max(10, this.resizeStartDimensions.height + rectDeltaY);
|
|
440
447
|
break;
|
|
448
|
+
}
|
|
441
449
|
case 'line':
|
|
442
450
|
case 'arrow':
|
|
443
451
|
// Line/arrow resize logic - move endpoints
|
|
@@ -460,7 +468,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
460
468
|
this.startTextEditing = (annotation) => {
|
|
461
469
|
const newText = prompt(this.editTextPromptText, annotation.text);
|
|
462
470
|
if (newText !== null && newText.trim()) {
|
|
463
|
-
const index = this.annotations.findIndex(a => a === annotation);
|
|
471
|
+
const index = this.annotations.findIndex((a) => a === annotation);
|
|
464
472
|
if (index !== -1) {
|
|
465
473
|
this.annotations[index] = Object.assign(Object.assign({}, annotation), { text: newText.trim() });
|
|
466
474
|
this.selectedAnnotation = this.annotations[index];
|
|
@@ -471,7 +479,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
471
479
|
// Update selected annotation font size
|
|
472
480
|
this.updateSelectedTextSize = (newSize) => {
|
|
473
481
|
if (this.selectedAnnotation && this.selectedAnnotation.type === 'text') {
|
|
474
|
-
const index = this.annotations.findIndex(a => a === this.selectedAnnotation);
|
|
482
|
+
const index = this.annotations.findIndex((a) => a === this.selectedAnnotation);
|
|
475
483
|
if (index !== -1) {
|
|
476
484
|
this.annotations[index] = Object.assign(Object.assign({}, this.selectedAnnotation), { fontSize: Math.max(8, Math.min(72, newSize)) });
|
|
477
485
|
this.selectedAnnotation = this.annotations[index];
|
|
@@ -481,8 +489,9 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
481
489
|
};
|
|
482
490
|
// Update selected annotation border width
|
|
483
491
|
this.updateSelectedBorderWidth = (newWidth) => {
|
|
484
|
-
if (this.selectedAnnotation &&
|
|
485
|
-
|
|
492
|
+
if (this.selectedAnnotation &&
|
|
493
|
+
['rectangle', 'line', 'arrow'].includes(this.selectedAnnotation.type)) {
|
|
494
|
+
const index = this.annotations.findIndex((a) => a === this.selectedAnnotation);
|
|
486
495
|
if (index !== -1) {
|
|
487
496
|
this.annotations[index] = Object.assign(Object.assign({}, this.selectedAnnotation), { lineWidth: Math.max(1, Math.min(20, newWidth)) });
|
|
488
497
|
this.selectedAnnotation = this.annotations[index];
|
|
@@ -545,7 +554,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
545
554
|
y: coords.y,
|
|
546
555
|
text,
|
|
547
556
|
color: this.canvasDrawingColor,
|
|
548
|
-
fontSize: this.canvasTextSize
|
|
557
|
+
fontSize: this.canvasTextSize,
|
|
549
558
|
};
|
|
550
559
|
this.annotations = [...this.annotations, annotation];
|
|
551
560
|
this.redrawAnnotations();
|
|
@@ -558,7 +567,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
558
567
|
startX: coords.x,
|
|
559
568
|
startY: coords.y,
|
|
560
569
|
color: this.canvasDrawingColor,
|
|
561
|
-
lineWidth: this.canvasLineWidth
|
|
570
|
+
lineWidth: this.canvasLineWidth,
|
|
562
571
|
};
|
|
563
572
|
}
|
|
564
573
|
};
|
|
@@ -598,7 +607,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
598
607
|
break;
|
|
599
608
|
}
|
|
600
609
|
// Update annotation in array
|
|
601
|
-
const index = this.annotations.findIndex(a => a === this.draggedAnnotation);
|
|
610
|
+
const index = this.annotations.findIndex((a) => a === this.draggedAnnotation);
|
|
602
611
|
if (index !== -1) {
|
|
603
612
|
this.annotations[index] = updatedAnnotation;
|
|
604
613
|
this.draggedAnnotation = updatedAnnotation;
|
|
@@ -711,22 +720,26 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
711
720
|
this.isPointInAnnotation = (x, y, annotation) => {
|
|
712
721
|
const tolerance = 10; // Click tolerance
|
|
713
722
|
switch (annotation.type) {
|
|
714
|
-
case 'rectangle':
|
|
723
|
+
case 'rectangle': {
|
|
715
724
|
const left = Math.min(annotation.startX, annotation.startX + annotation.width);
|
|
716
725
|
const right = Math.max(annotation.startX, annotation.startX + annotation.width);
|
|
717
726
|
const top = Math.min(annotation.startY, annotation.startY + annotation.height);
|
|
718
727
|
const bottom = Math.max(annotation.startY, annotation.startY + annotation.height);
|
|
719
|
-
return x >= left - tolerance &&
|
|
720
|
-
|
|
728
|
+
return (x >= left - tolerance &&
|
|
729
|
+
x <= right + tolerance &&
|
|
730
|
+
y >= top - tolerance &&
|
|
731
|
+
y <= bottom + tolerance);
|
|
732
|
+
}
|
|
721
733
|
case 'line':
|
|
722
|
-
case 'arrow':
|
|
734
|
+
case 'arrow': {
|
|
723
735
|
// Distance from point to line
|
|
724
736
|
const A = annotation.endY - annotation.startY;
|
|
725
737
|
const B = annotation.startX - annotation.endX;
|
|
726
738
|
const C = annotation.endX * annotation.startY - annotation.startX * annotation.endY;
|
|
727
739
|
const distance = Math.abs(A * x + B * y + C) / Math.sqrt(A * A + B * B);
|
|
728
740
|
return distance <= tolerance;
|
|
729
|
-
|
|
741
|
+
}
|
|
742
|
+
case 'text': {
|
|
730
743
|
// Use actual text dimensions for better dragging
|
|
731
744
|
const fontSize = annotation.fontSize || 24;
|
|
732
745
|
const textWidth = this.getTextWidth(annotation.text, fontSize);
|
|
@@ -736,8 +749,8 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
736
749
|
const textRight = annotation.x + textWidth + tolerance;
|
|
737
750
|
const textTop = annotation.y - textHeight - tolerance;
|
|
738
751
|
const textBottom = annotation.y + tolerance;
|
|
739
|
-
return x >= textLeft && x <= textRight &&
|
|
740
|
-
|
|
752
|
+
return x >= textLeft && x <= textRight && y >= textTop && y <= textBottom;
|
|
753
|
+
}
|
|
741
754
|
default:
|
|
742
755
|
return false;
|
|
743
756
|
}
|
|
@@ -819,10 +832,10 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
819
832
|
video: {
|
|
820
833
|
mediaSource: 'screen',
|
|
821
834
|
width: { ideal: window.innerWidth },
|
|
822
|
-
height: { ideal: window.innerHeight }
|
|
835
|
+
height: { ideal: window.innerHeight },
|
|
823
836
|
},
|
|
824
837
|
audio: false,
|
|
825
|
-
preferCurrentTab: true
|
|
838
|
+
preferCurrentTab: true,
|
|
826
839
|
});
|
|
827
840
|
// Create video element to capture frame
|
|
828
841
|
const video = document.createElement('video');
|
|
@@ -842,20 +855,20 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
842
855
|
const ctx = canvas.getContext('2d');
|
|
843
856
|
ctx.drawImage(video, 0, 0);
|
|
844
857
|
// Stop the stream
|
|
845
|
-
stream.getTracks().forEach(track => track.stop());
|
|
858
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
846
859
|
// Convert to data URL
|
|
847
860
|
const dataUrl = canvas.toDataURL('image/png');
|
|
848
861
|
console.log('Screenshot captured successfully using Screen Capture API');
|
|
849
862
|
resolve(dataUrl);
|
|
850
863
|
}
|
|
851
864
|
catch (error) {
|
|
852
|
-
stream.getTracks().forEach(track => track.stop());
|
|
865
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
853
866
|
reject(error);
|
|
854
867
|
}
|
|
855
868
|
}, 100);
|
|
856
869
|
};
|
|
857
870
|
video.onerror = () => {
|
|
858
|
-
stream.getTracks().forEach(track => track.stop());
|
|
871
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
859
872
|
reject(new Error('Failed to load video for screenshot capture'));
|
|
860
873
|
};
|
|
861
874
|
});
|
|
@@ -867,7 +880,8 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
867
880
|
}
|
|
868
881
|
render() {
|
|
869
882
|
var _a, _b, _c, _d, _e, _f;
|
|
870
|
-
return (h("div", { class: "canvas-editor-wrapper" }, this.showCanvasEditor && (h("div", { class: "canvas-editor-overlay" }, h("div", { class: "canvas-editor-modal" }, h("div", { class: "canvas-editor-header" }, h("div", { class: "canvas-editor-title" }, h("h3", null, this.canvasEditorTitle)), h("div", { class: "canvas-editor-toolbar" }, h("div", { class: "toolbar-section" }, h("div", { class: "tool-group" }, h("button", { class: `tool-btn ${this.canvasDrawingTool === 'rectangle' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'rectangle', title: "Rectangle" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-square" }, h("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }))), h("button", { class: `tool-btn ${this.canvasDrawingTool === 'line' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'line', title: "Line" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-minus" }, h("path", { d: "M5 12h14" }))), h("button", { class: `tool-btn ${this.canvasDrawingTool === 'arrow' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'arrow', title: "Arrow" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-move-up-right" }, h("path", { d: "M13 5H19V11" }), h("path", { d: "M19 5L5 19" }))), h("button", { class: `tool-btn ${this.canvasDrawingTool === 'text' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'text', title: "Text" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-type" }, h("path", { d: "M12 4v16" }), h("path", { d: "M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2" }), h("path", { d: "M9 20h6" }))), h("div", { class: "toolbar-divider" }), h("button", { class: "tool-btn undo-btn", onClick: this.undoLastAnnotation, disabled: this.annotations.length === 0, title: "Undo" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-undo" }, h("path", { d: "M3 7v6h6" }), h("path", { d: "M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13" }))), this.selectedAnnotation && (h("button", { class: "tool-btn delete-btn", onClick: this.deleteSelectedAnnotation, title: "Delete" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-trash-2" }, h("path", { d: "M3 6h18" }), h("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }), h("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" }), h("line", { x1: "10", x2: "10", y1: "11", y2: "17" }), h("line", { x1: "14", x2: "14", y1: "11", y2: "17" })))))), h("div", { class: "toolbar-section" }, h("div", { class: "color-palette" }, this.defaultColors.map((color, index) => (h("div", { class: "color-slot-wrapper" }, h("button", { class: `color-btn ${this.canvasDrawingColor === color ? 'active' : ''} ${this.editingColorIndex === index ? 'editing' : ''}`, style: { backgroundColor: color }, onClick: () => this.handleColorSlotClick(index), title: `Color ${index + 1} - Click to customize` }, this.editingColorIndex === index && (h("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "white", "stroke-width": "2" }, h("path", { d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" })))), this.editingColorIndex === index && this.showColorPicker && (h("div", { class: "color-picker-dropdown" }, h("input", { type: "color", value: color, onInput: (e) => this.handleColorPickerInput(e), onClick: (e) => this.handleColorPickerClick(e) })))))))), (this.selectedAnnotation || this.canvasDrawingTool) && (h("div", { class: "toolbar-section selected-annotation-controls" }, (((_a = this.selectedAnnotation) === null || _a === void 0 ? void 0 : _a.type) === 'text' ||
|
|
883
|
+
return (h("div", { class: "canvas-editor-wrapper" }, this.showCanvasEditor && (h("div", { class: "canvas-editor-overlay", part: "overlay" }, h("div", { class: "canvas-editor-modal", part: "modal" }, h("div", { class: "canvas-editor-header", part: "header" }, h("div", { class: "canvas-editor-title", part: "title" }, h("h3", null, this.canvasEditorTitle)), h("div", { class: "canvas-editor-toolbar", part: "toolbar" }, h("div", { class: "toolbar-section" }, h("div", { class: "tool-group" }, h("button", { class: `tool-btn ${this.canvasDrawingTool === 'rectangle' ? 'active' : ''}`, part: "tool-button", onClick: () => (this.canvasDrawingTool = 'rectangle'), title: "Rectangle" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-square" }, h("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }))), h("button", { class: `tool-btn ${this.canvasDrawingTool === 'line' ? 'active' : ''}`, part: "tool-button", onClick: () => (this.canvasDrawingTool = 'line'), title: "Line" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-minus" }, h("path", { d: "M5 12h14" }))), h("button", { class: `tool-btn ${this.canvasDrawingTool === 'arrow' ? 'active' : ''}`, part: "tool-button", onClick: () => (this.canvasDrawingTool = 'arrow'), title: "Arrow" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-move-up-right" }, h("path", { d: "M13 5H19V11" }), h("path", { d: "M19 5L5 19" }))), h("button", { class: `tool-btn ${this.canvasDrawingTool === 'text' ? 'active' : ''}`, part: "tool-button", onClick: () => (this.canvasDrawingTool = 'text'), title: "Text" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-type" }, h("path", { d: "M12 4v16" }), h("path", { d: "M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2" }), h("path", { d: "M9 20h6" }))), h("div", { class: "toolbar-divider" }), h("button", { class: "tool-btn undo-btn", part: "tool-button", onClick: this.undoLastAnnotation, disabled: this.annotations.length === 0, title: "Undo" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-undo" }, h("path", { d: "M3 7v6h6" }), h("path", { d: "M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13" }))), this.selectedAnnotation && (h("button", { class: "tool-btn delete-btn", part: "tool-button", onClick: this.deleteSelectedAnnotation, title: "Delete" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "lucide lucide-trash-2" }, h("path", { d: "M3 6h18" }), h("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }), h("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" }), h("line", { x1: "10", x2: "10", y1: "11", y2: "17" }), h("line", { x1: "14", x2: "14", y1: "11", y2: "17" })))))), h("div", { class: "toolbar-section" }, h("div", { class: "color-palette" }, this.defaultColors.map((color, index) => (h("div", { class: "color-slot-wrapper" }, h("button", { class: `color-btn ${this.canvasDrawingColor === color ? 'active' : ''} ${this.editingColorIndex === index ? 'editing' : ''}`, style: { backgroundColor: color }, onClick: () => this.handleColorSlotClick(index), title: `Color ${index + 1} - Click to customize` }, this.editingColorIndex === index && (h("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "white", "stroke-width": "2" }, h("path", { d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" })))), this.editingColorIndex === index && this.showColorPicker && (h("div", { class: "color-picker-dropdown" }, h("input", { type: "color", value: color, onInput: (e) => this.handleColorPickerInput(e), onClick: (e) => this.handleColorPickerClick(e) })))))))), (this.selectedAnnotation || this.canvasDrawingTool) && (h("div", { class: "toolbar-section selected-annotation-controls" }, (((_a = this.selectedAnnotation) === null || _a === void 0 ? void 0 : _a.type) === 'text' ||
|
|
884
|
+
(!this.selectedAnnotation && this.canvasDrawingTool === 'text')) && (h("div", { class: "text-controls" }, h("div", { class: "font-size-control" }, h("label", null, this.sizeLabelText), h("input", { type: "range", min: "8", max: "72", value: ((_b = this.selectedAnnotation) === null || _b === void 0 ? void 0 : _b.fontSize) || this.canvasTextSize, onInput: (e) => {
|
|
871
885
|
const newSize = parseInt(e.target.value);
|
|
872
886
|
if (this.selectedAnnotation) {
|
|
873
887
|
this.updateSelectedTextSize(newSize);
|
|
@@ -875,8 +889,9 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
875
889
|
else {
|
|
876
890
|
this.canvasTextSize = newSize;
|
|
877
891
|
}
|
|
878
|
-
}, class: "size-slider" }), h("span", { class: "size-value" }, ((_c = this.selectedAnnotation) === null || _c === void 0 ? void 0 : _c.fontSize) || this.canvasTextSize, "px")), this.selectedAnnotation && (h("button", { class: "action-btn small", onClick: () => this.startTextEditing(this.selectedAnnotation) }, this.editTextButtonText)))), (
|
|
879
|
-
(!this.selectedAnnotation &&
|
|
892
|
+
}, class: "size-slider" }), h("span", { class: "size-value" }, ((_c = this.selectedAnnotation) === null || _c === void 0 ? void 0 : _c.fontSize) || this.canvasTextSize, "px")), this.selectedAnnotation && (h("button", { class: "action-btn small", onClick: () => this.startTextEditing(this.selectedAnnotation) }, this.editTextButtonText)))), (['rectangle', 'line', 'arrow'].includes((_d = this.selectedAnnotation) === null || _d === void 0 ? void 0 : _d.type) ||
|
|
893
|
+
(!this.selectedAnnotation &&
|
|
894
|
+
['rectangle', 'line', 'arrow'].includes(this.canvasDrawingTool))) && (h("div", { class: "shape-controls" }, h("div", { class: "border-width-control" }, h("label", null, this.borderLabelText), h("input", { type: "range", min: "1", max: "20", value: ((_e = this.selectedAnnotation) === null || _e === void 0 ? void 0 : _e.lineWidth) || this.canvasLineWidth, onInput: (e) => {
|
|
880
895
|
const newWidth = parseInt(e.target.value);
|
|
881
896
|
if (this.selectedAnnotation) {
|
|
882
897
|
this.updateSelectedBorderWidth(newWidth);
|
|
@@ -884,7 +899,7 @@ const CanvasEditor = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
|
|
|
884
899
|
else {
|
|
885
900
|
this.canvasLineWidth = newWidth;
|
|
886
901
|
}
|
|
887
|
-
}, class: "size-slider" }), h("span", { class: "size-value" }, ((_f = this.selectedAnnotation) === null || _f === void 0 ? void 0 : _f.lineWidth) || this.canvasLineWidth, "px")))))), h("div", { class: "toolbar-section" }, h("button", { class: "action-btn secondary", onClick: this.closeCanvasEditor }, this.canvasEditorCancelText), h("button", { class: "action-btn primary", onClick: this.saveAnnotations }, this.canvasEditorSaveText))), h("div", { class: "canvas-editor-content" }, h("canvas", { ref: (el) => this.canvasRef = el, class: "annotation-canvas", onMouseDown: this.handleCanvasMouseDown, onMouseMove: this.handleCanvasMouseMove, onMouseUp: this.handleCanvasMouseUp, onMouseLeave: this.handleCanvasMouseUp }))))))));
|
|
902
|
+
}, class: "size-slider" }), h("span", { class: "size-value" }, ((_f = this.selectedAnnotation) === null || _f === void 0 ? void 0 : _f.lineWidth) || this.canvasLineWidth, "px")))))), h("div", { class: "toolbar-section" }, h("button", { class: "action-btn secondary", part: "cancel-button", onClick: this.closeCanvasEditor }, this.canvasEditorCancelText), h("button", { class: "action-btn primary", part: "save-button", onClick: this.saveAnnotations }, this.canvasEditorSaveText))), h("div", { class: "canvas-editor-content", part: "content" }, h("canvas", { ref: (el) => (this.canvasRef = el), class: "annotation-canvas", part: "canvas", onMouseDown: this.handleCanvasMouseDown, onMouseMove: this.handleCanvasMouseMove, onMouseUp: this.handleCanvasMouseUp, onMouseLeave: this.handleCanvasMouseUp }))))))));
|
|
888
903
|
}
|
|
889
904
|
static get style() { return canvasEditorCss; }
|
|
890
905
|
}, [1, "canvas-editor", {
|
|
@@ -198,7 +198,7 @@ const FeedbackButton$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElem
|
|
|
198
198
|
else if (res.status === 202) {
|
|
199
199
|
const limitExceededBody = {
|
|
200
200
|
message: "You received a new feedback entry. You've reached the 25 message limit for your current plan. Upgrade to continue receiving feedback.",
|
|
201
|
-
id: await res.json()
|
|
201
|
+
id: await res.json(),
|
|
202
202
|
};
|
|
203
203
|
this.feedbackSent.emit({ feedback: limitExceededBody });
|
|
204
204
|
}
|
|
@@ -220,7 +220,7 @@ const FeedbackButton$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElem
|
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
render() {
|
|
223
|
-
return (h(Host, null, h("a", { class: `feedback-button-content feedback-button-content--${this.buttonStyle} feedback-button-content--${this.buttonPosition} ${this.customFont ? 'feedback-button-content--custom-font' : ''} ${this.hideMobile ? 'feedback-button-content--hide-mobile' : ''}`, onClick: () => this.showModal() }, !this.hideIcon && this.buttonStyle != 'default' && (h("span", { class: "feedback-button-content-icon" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#fff", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "icon-edit" }, h("path", { d: "M12 20h9" }), h("path", { d: "M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z" })))), h("slot", null))));
|
|
223
|
+
return (h(Host, null, h("a", { class: `feedback-button-content feedback-button-content--${this.buttonStyle} feedback-button-content--${this.buttonPosition} ${this.customFont ? 'feedback-button-content--custom-font' : ''} ${this.hideMobile ? 'feedback-button-content--hide-mobile' : ''}`, part: "button", onClick: () => this.showModal() }, !this.hideIcon && this.buttonStyle != 'default' && (h("span", { class: "feedback-button-content-icon", part: "icon" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#fff", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "icon-edit" }, h("path", { d: "M12 20h9" }), h("path", { d: "M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z" })))), h("slot", null))));
|
|
224
224
|
}
|
|
225
225
|
get el() { return this; }
|
|
226
226
|
static get style() { return feedbackButtonCss; }
|