pushfeedback 0.1.83 → 0.1.85
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 +440 -44
- 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 +173 -15
- package/dist/collection/components/feedback-button/feedback-button.css +45 -1
- package/dist/collection/components/feedback-button/feedback-button.js +98 -8
- package/dist/collection/components/feedback-modal/feedback-modal.css +6 -0
- package/dist/collection/components/feedback-modal/feedback-modal.js +351 -20
- package/dist/collection/utils/sanitize-html.js +90 -0
- package/dist/components/canvas-editor2.js +139 -15
- package/dist/components/feedback-button.js +30 -8
- package/dist/components/feedback-modal2.js +286 -21
- package/dist/esm/canvas-editor_3.entry.js +440 -44
- package/dist/esm/loader.js +1 -1
- package/dist/esm/pushfeedback.js +1 -1
- package/dist/pushfeedback/p-17acbd1c.entry.js +1 -0
- package/dist/pushfeedback/pushfeedback.esm.js +1 -1
- package/dist/types/components/canvas-editor/canvas-editor.d.ts +7 -0
- package/dist/types/components/feedback-button/feedback-button.d.ts +16 -0
- package/dist/types/components/feedback-modal/feedback-modal.d.ts +33 -0
- package/dist/types/components.d.ts +48 -0
- package/dist/types/utils/sanitize-html.d.ts +8 -0
- package/package.json +2 -1
- package/dist/pushfeedback/p-1338beed.entry.js +0 -1
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
import { h } from '@stencil/core';
|
|
2
|
+
import { sanitizeHtml } from '../../utils/sanitize-html';
|
|
2
3
|
export class FeedbackModal {
|
|
3
4
|
constructor() {
|
|
5
|
+
// Track the history entry pushed while the modal is open
|
|
6
|
+
this.historyEntryPushed = false;
|
|
7
|
+
// Element that had focus before the modal opened, so it can be restored on close
|
|
8
|
+
this.previouslyFocused = null;
|
|
9
|
+
this.handleKeyDown = (event) => {
|
|
10
|
+
// The canvas editor renders its own overlay and handles its own keys
|
|
11
|
+
if (!this.showModal || this.embedded || this.showCanvasEditor) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (event.key === 'Escape' && this.escapeClose) {
|
|
15
|
+
event.preventDefault();
|
|
16
|
+
// Escape is an accidental-dismissal path like clicking outside, so keep
|
|
17
|
+
// whatever the user already typed
|
|
18
|
+
this.doClose(!this.formSuccess);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (event.key === 'Tab') {
|
|
22
|
+
this.trapFocus(event);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
this.handlePopState = () => {
|
|
26
|
+
// Back button pressed while the modal is open: close it and consume our entry
|
|
27
|
+
if (this.historyEntryPushed) {
|
|
28
|
+
this.historyEntryPushed = false;
|
|
29
|
+
if (this.showModal) {
|
|
30
|
+
this.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
4
34
|
this.onScrollDebounced = () => {
|
|
5
35
|
clearTimeout(this.scrollTimeout);
|
|
6
36
|
this.scrollTimeout = setTimeout(() => {
|
|
@@ -35,12 +65,16 @@ export class FeedbackModal {
|
|
|
35
65
|
}
|
|
36
66
|
}
|
|
37
67
|
const body = Object.assign({ url: window.location.href, message: this.formMessage, email: this.formEmail, project: this.project, screenshot: this.encodedScreenshot, rating: this.selectedRating, ratingMode: this.ratingMode, metadata: this.metadata, verification: this.formVerification, session: localStorage.getItem('pushfeedback_sessionid') || '' }, (recaptchaToken && { recaptchaToken }));
|
|
38
|
-
const
|
|
68
|
+
const headers = {
|
|
69
|
+
'Content-Type': 'application/json',
|
|
70
|
+
};
|
|
71
|
+
if (this.apiKey) {
|
|
72
|
+
headers['Authorization'] = `Api-Key ${this.apiKey}`;
|
|
73
|
+
}
|
|
74
|
+
const res = await fetch('https://app.pushfeedback.com/api/v1/feedback/', {
|
|
39
75
|
method: 'POST',
|
|
40
76
|
body: JSON.stringify(body),
|
|
41
|
-
headers
|
|
42
|
-
'Content-Type': 'application/json',
|
|
43
|
-
},
|
|
77
|
+
headers,
|
|
44
78
|
});
|
|
45
79
|
if (res.status === 201) {
|
|
46
80
|
const feedback_with_id = Object.assign(Object.assign({}, body), { id: await res.json() });
|
|
@@ -85,14 +119,22 @@ export class FeedbackModal {
|
|
|
85
119
|
}
|
|
86
120
|
};
|
|
87
121
|
this.close = () => {
|
|
122
|
+
this.doClose(false);
|
|
123
|
+
};
|
|
124
|
+
// Closing by clicking outside keeps the typed input, so an accidental
|
|
125
|
+
// click does not throw away a half-written message or screenshot
|
|
126
|
+
this.handleOverlayClick = () => {
|
|
127
|
+
this.doClose(!this.formSuccess);
|
|
128
|
+
};
|
|
129
|
+
this.doClose = (preserveInput) => {
|
|
88
130
|
this.isAnimating = false;
|
|
131
|
+
this.popHistoryEntry();
|
|
89
132
|
setTimeout(() => {
|
|
90
133
|
this.sending = false;
|
|
91
134
|
this.showModal = false;
|
|
92
135
|
this.showScreenshotMode = false;
|
|
93
136
|
this.showScreenshotTopBar = false;
|
|
94
137
|
this.hasSelectedElement = false;
|
|
95
|
-
this.encodedScreenshot = null;
|
|
96
138
|
// Remove highlight from ALL selected elements
|
|
97
139
|
document.querySelectorAll('.feedback-modal-element-selected').forEach((el) => {
|
|
98
140
|
el.classList.remove('feedback-modal-element-selected');
|
|
@@ -101,9 +143,19 @@ export class FeedbackModal {
|
|
|
101
143
|
this.formSuccess = false;
|
|
102
144
|
this.formError = false;
|
|
103
145
|
this.formErrorStatus = 500;
|
|
104
|
-
|
|
105
|
-
|
|
146
|
+
if (!preserveInput) {
|
|
147
|
+
this.encodedScreenshot = null;
|
|
148
|
+
this.formMessage = '';
|
|
149
|
+
this.formEmail = '';
|
|
150
|
+
// The rating and the privacy checkbox are part of the same in-progress
|
|
151
|
+
// input. Leaving the rating set meant reopening the modal showed the
|
|
152
|
+
// previous session's choice still highlighted, and submitting then sent
|
|
153
|
+
// that stale rating instead of one chosen for this submission.
|
|
154
|
+
this.selectedRating = this.initialRating();
|
|
155
|
+
this.isPrivacyChecked = false;
|
|
156
|
+
}
|
|
106
157
|
this.resetOverflow();
|
|
158
|
+
this.restoreFocus();
|
|
107
159
|
}, 200);
|
|
108
160
|
};
|
|
109
161
|
// Handle screenshot events from canvas editor
|
|
@@ -113,12 +165,16 @@ export class FeedbackModal {
|
|
|
113
165
|
this.takingScreenshot = false;
|
|
114
166
|
this.showCanvasEditor = false;
|
|
115
167
|
this.autoStartCapture = false;
|
|
168
|
+
this.focusModal();
|
|
116
169
|
};
|
|
117
170
|
this.handleScreenshotCancelled = () => {
|
|
118
171
|
this.showModal = true;
|
|
119
172
|
this.takingScreenshot = false;
|
|
120
173
|
this.showCanvasEditor = false;
|
|
121
174
|
this.autoStartCapture = false;
|
|
175
|
+
// Focus was inside the editor that just went away, so bring it back to the
|
|
176
|
+
// form rather than letting it fall to the top of the page
|
|
177
|
+
this.focusModal();
|
|
122
178
|
};
|
|
123
179
|
this.handleScreenshotError = (event) => {
|
|
124
180
|
console.error('Screenshot error:', event.detail.error);
|
|
@@ -130,6 +186,7 @@ export class FeedbackModal {
|
|
|
130
186
|
this.takingScreenshot = false;
|
|
131
187
|
this.showCanvasEditor = false;
|
|
132
188
|
this.autoStartCapture = false;
|
|
189
|
+
this.focusModal();
|
|
133
190
|
// Auto-hide error after 8 seconds
|
|
134
191
|
setTimeout(() => {
|
|
135
192
|
this.showScreenshotError = false;
|
|
@@ -171,6 +228,7 @@ export class FeedbackModal {
|
|
|
171
228
|
this.screenshotError = '';
|
|
172
229
|
this.showCanvasEditor = false;
|
|
173
230
|
this.autoStartCapture = false;
|
|
231
|
+
this.apiKey = '';
|
|
174
232
|
this.customFont = false;
|
|
175
233
|
this.emailAddress = '';
|
|
176
234
|
this.hideEmail = false;
|
|
@@ -188,8 +246,12 @@ export class FeedbackModal {
|
|
|
188
246
|
this.metadata = undefined;
|
|
189
247
|
this.fetchData = true;
|
|
190
248
|
this.embedded = false;
|
|
249
|
+
this.clickOutsideClose = true;
|
|
250
|
+
this.historyClose = true;
|
|
251
|
+
this.escapeClose = true;
|
|
191
252
|
this.emailPlaceholder = 'Email address (optional)';
|
|
192
253
|
this.errorMessage = 'Please try again later.';
|
|
254
|
+
this.errorMessage401 = 'This project requires a valid API key to submit feedback. Check the api-key attribute.';
|
|
193
255
|
this.errorMessage403 = 'The request URL does not match the one defined in PushFeedback for this project.';
|
|
194
256
|
this.errorMessage404 = 'We could not find the provided project ID in PushFeedback.';
|
|
195
257
|
this.messagePlaceholder = 'Share your thoughts...';
|
|
@@ -202,6 +264,10 @@ export class FeedbackModal {
|
|
|
202
264
|
this.ratingPlaceholder = 'Was this page helpful?';
|
|
203
265
|
this.ratingStarsPlaceholder = 'How would you rate this page?';
|
|
204
266
|
this.sendButtonText = 'Send';
|
|
267
|
+
this.closeButtonLabel = 'Close feedback form';
|
|
268
|
+
this.ratingPositiveLabel = 'Yes';
|
|
269
|
+
this.ratingNegativeLabel = 'No';
|
|
270
|
+
this.ratingStarLabel = 'Rate {rating} out of 5';
|
|
205
271
|
this.successMessage = '';
|
|
206
272
|
this.recaptchaText = 'This form is protected by reCAPTCHA and the Google <a href="https://policies.google.com/privacy" target="_blank" rel="noopener noreferrer">Privacy Policy</a> and <a href="https://policies.google.com/terms" target="_blank" rel="noopener noreferrer">Terms of Service</a> apply.';
|
|
207
273
|
this.screenshotAttachedText = 'Screenshot attached';
|
|
@@ -222,16 +288,98 @@ export class FeedbackModal {
|
|
|
222
288
|
this.screenshotErrorBrowserNotSupported = 'Your browser does not support screen capture. Please use a browser like Chrome, Firefox, or Safari on desktop.';
|
|
223
289
|
this.screenshotErrorUnexpected = 'An unexpected error occurred. Please try again.';
|
|
224
290
|
}
|
|
291
|
+
connectedCallback() {
|
|
292
|
+
window.addEventListener('popstate', this.handlePopState);
|
|
293
|
+
document.addEventListener('keydown', this.handleKeyDown);
|
|
294
|
+
}
|
|
295
|
+
disconnectedCallback() {
|
|
296
|
+
window.removeEventListener('popstate', this.handlePopState);
|
|
297
|
+
document.removeEventListener('keydown', this.handleKeyDown);
|
|
298
|
+
}
|
|
299
|
+
// Keeps Tab cycling inside the dialog while it is open
|
|
300
|
+
trapFocus(event) {
|
|
301
|
+
var _a, _b;
|
|
302
|
+
const focusable = this.getFocusableElements();
|
|
303
|
+
if (focusable.length === 0) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const first = focusable[0];
|
|
307
|
+
const last = focusable[focusable.length - 1];
|
|
308
|
+
const active = (_a = this.modalContent) === null || _a === void 0 ? void 0 : _a.getRootNode();
|
|
309
|
+
const current = active === null || active === void 0 ? void 0 : active.activeElement;
|
|
310
|
+
if (current === this.modalContent) {
|
|
311
|
+
// Focus is on the dialog container itself (where it lands on open).
|
|
312
|
+
// Tab falls through to the first control natively; Shift+Tab would
|
|
313
|
+
// escape the dialog, so wrap it to the last one.
|
|
314
|
+
if (event.shiftKey) {
|
|
315
|
+
event.preventDefault();
|
|
316
|
+
last.focus();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
else if (event.shiftKey && current === first) {
|
|
320
|
+
event.preventDefault();
|
|
321
|
+
last.focus();
|
|
322
|
+
}
|
|
323
|
+
else if (!event.shiftKey && current === last) {
|
|
324
|
+
event.preventDefault();
|
|
325
|
+
first.focus();
|
|
326
|
+
}
|
|
327
|
+
else if (!current || !((_b = this.modalContent) === null || _b === void 0 ? void 0 : _b.contains(current))) {
|
|
328
|
+
// Focus escaped the dialog (or never entered it) - pull it back in
|
|
329
|
+
event.preventDefault();
|
|
330
|
+
first.focus();
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
// offsetParent is not usable here: it is null for `position: fixed` elements
|
|
334
|
+
// even when they are perfectly visible, and it is non-null for
|
|
335
|
+
// `visibility: hidden` ones, which cannot be focused. getClientRects covers
|
|
336
|
+
// display:none and detached nodes, so visibility is the only extra check.
|
|
337
|
+
isFocusable(el) {
|
|
338
|
+
if (el.hidden || el.getClientRects().length === 0) {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
return getComputedStyle(el).visibility !== 'hidden';
|
|
342
|
+
}
|
|
343
|
+
getFocusableElements() {
|
|
344
|
+
if (!this.modalContent) {
|
|
345
|
+
return [];
|
|
346
|
+
}
|
|
347
|
+
const selector = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
348
|
+
return Array.from(this.modalContent.querySelectorAll(selector)).filter((el) => this.isFocusable(el));
|
|
349
|
+
}
|
|
350
|
+
// Moves focus to the dialog container once it has rendered, so screen readers
|
|
351
|
+
// announce the dialog title rather than jumping straight to the first control
|
|
352
|
+
focusModal() {
|
|
353
|
+
requestAnimationFrame(() => {
|
|
354
|
+
if (this.modalContent) {
|
|
355
|
+
this.modalContent.focus();
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
restoreFocus() {
|
|
360
|
+
const target = this.previouslyFocused;
|
|
361
|
+
this.previouslyFocused = null;
|
|
362
|
+
if (target && typeof target.focus === 'function' && target.isConnected) {
|
|
363
|
+
target.focus();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// The rating the widget starts from. Closing restores this rather than
|
|
367
|
+
// blanking to neutral, so a consumer's configured `rating` default survives
|
|
368
|
+
// the modal being closed and reopened.
|
|
369
|
+
initialRating() {
|
|
370
|
+
if (this.ratingMode == 'thumbs' && this.rating == 0) {
|
|
371
|
+
return 5;
|
|
372
|
+
}
|
|
373
|
+
if (this.rating) {
|
|
374
|
+
return this.rating;
|
|
375
|
+
}
|
|
376
|
+
return -1;
|
|
377
|
+
}
|
|
225
378
|
componentWillLoad() {
|
|
226
379
|
if (this.fetchData)
|
|
227
380
|
this.fetchProjectData();
|
|
228
381
|
this.formEmail = this.emailAddress;
|
|
229
|
-
|
|
230
|
-
this.selectedRating = this.rating;
|
|
231
|
-
}
|
|
232
|
-
if (this.ratingMode == 'thumbs' && this.rating == 0) {
|
|
233
|
-
this.selectedRating = 5;
|
|
234
|
-
}
|
|
382
|
+
this.selectedRating = this.initialRating();
|
|
235
383
|
// Automatically show modal when embedded
|
|
236
384
|
if (this.embedded) {
|
|
237
385
|
this.showModal = true;
|
|
@@ -239,7 +387,9 @@ export class FeedbackModal {
|
|
|
239
387
|
}
|
|
240
388
|
async fetchProjectData() {
|
|
241
389
|
try {
|
|
242
|
-
|
|
390
|
+
// Public config endpoint: never send the API key here, it is only
|
|
391
|
+
// needed (and only allowed to travel) on the feedback POST
|
|
392
|
+
const response = await fetch('https://app.pushfeedback.com/api/v1/projects/' + this.project + '/');
|
|
243
393
|
const data = await response.json();
|
|
244
394
|
this.whitelabel = data.whitelabel;
|
|
245
395
|
this.recaptchaEnabled = data.recaptcha_enabled || false;
|
|
@@ -312,6 +462,12 @@ export class FeedbackModal {
|
|
|
312
462
|
handleEmailInput(event) {
|
|
313
463
|
this.formEmail = event.target.value;
|
|
314
464
|
}
|
|
465
|
+
popHistoryEntry() {
|
|
466
|
+
if (this.historyEntryPushed) {
|
|
467
|
+
this.historyEntryPushed = false;
|
|
468
|
+
history.back();
|
|
469
|
+
}
|
|
470
|
+
}
|
|
315
471
|
handleCheckboxChange(event) {
|
|
316
472
|
this.isPrivacyChecked = event.target.checked;
|
|
317
473
|
}
|
|
@@ -322,28 +478,28 @@ export class FeedbackModal {
|
|
|
322
478
|
this.selectedRating = newRating;
|
|
323
479
|
}
|
|
324
480
|
render() {
|
|
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)
|
|
481
|
+
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, "escape-close": this.escapeClose ? 'true' : 'false', "click-outside-close": this.clickOutsideClose ? 'true' : 'false', "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", "aria-hidden": "true", onClick: this.clickOutsideClose ? this.handleOverlayClick : undefined })), 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", role: this.embedded ? 'region' : 'dialog', "aria-modal": this.embedded ? undefined : 'true', "aria-labelledby": "feedback-modal-title", tabindex: "-1", ref: (el) => (this.modalContent = el) }, h("div", { class: `feedback-modal-header ${(this.formSuccess && !this.successMessage) || (this.formError && !this.errorMessage)
|
|
326
482
|
? '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: "
|
|
483
|
+
: ''}`, part: "header" }, h("div", { class: "feedback-modal-header-content" }, !this.formSuccess && !this.formError ? (h("div", { class: "feedback-modal-header-text" }, h("span", { id: "feedback-modal-title", 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", { id: "feedback-modal-title", class: "feedback-modal-title", part: "title" }, this.modalTitleSuccess)) : (h("span", { id: "feedback-modal-title", class: "feedback-modal-title", part: "title" }, this.modalTitleError))), !this.embedded && (h("button", { class: "feedback-modal-close", part: "close-button", type: "button", "aria-label": this.closeButtonLabel, 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", { type: "button", title: this.ratingPositiveLabel, "aria-label": this.ratingPositiveLabel, "aria-pressed": this.selectedRating === 1 ? 'true' : 'false', class: `feedback-modal-rating-button feedback-modal-rating-button--positive ${this.selectedRating === 1
|
|
328
484
|
? 'feedback-modal-rating-button--selected'
|
|
329
485
|
: ''}`, part: "rating-button rating-button-positive", onClick: (event) => {
|
|
330
486
|
event.preventDefault();
|
|
331
487
|
this.handleRatingChange(1);
|
|
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: "
|
|
488
|
+
} }, 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", { type: "button", title: this.ratingNegativeLabel, "aria-label": this.ratingNegativeLabel, "aria-pressed": this.selectedRating === 5 ? 'true' : 'false', class: `feedback-modal-rating-button feedback-modal-rating-button--negative ${this.selectedRating === 5
|
|
333
489
|
? 'feedback-modal-rating-button--selected'
|
|
334
490
|
: ''}`, part: "rating-button rating-button-negative", onClick: (event) => {
|
|
335
491
|
event.preventDefault();
|
|
336
492
|
this.handleRatingChange(5);
|
|
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
|
|
493
|
+
} }, 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, type: "button", "aria-label": this.ratingStarLabel.replace('{rating}', String(rating)), "aria-pressed": this.selectedRating === rating ? 'true' : 'false', class: `feedback-modal-rating-button ${this.selectedRating >= rating
|
|
338
494
|
? 'feedback-modal-rating-button--selected'
|
|
339
495
|
: ''}`, part: "rating-button", onClick: (event) => {
|
|
340
496
|
event.preventDefault();
|
|
341
497
|
this.handleRatingChange(rating);
|
|
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
|
|
498
|
+
} }, 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: sanitizeHtml(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
499
|
? this.screenshotTakingText
|
|
344
500
|
: this.encodedScreenshot
|
|
345
501
|
? 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 }))))))));
|
|
502
|
+
: 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 == 401 ? (h("p", { class: "feedback-modal-message", part: "error-message" }, this.errorMessage401)) : 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: sanitizeHtml(this.recaptchaText) })), this.recaptchaEnabled && this.footerText && ' ', this.footerText && h("span", { innerHTML: sanitizeHtml(this.footerText) }))))))));
|
|
347
503
|
}
|
|
348
504
|
componentDidRender() {
|
|
349
505
|
if (this.showModal) {
|
|
@@ -353,7 +509,17 @@ export class FeedbackModal {
|
|
|
353
509
|
}
|
|
354
510
|
}
|
|
355
511
|
async openModal() {
|
|
512
|
+
// Remember the trigger so focus can return there when the modal closes
|
|
513
|
+
if (!this.embedded) {
|
|
514
|
+
const active = document.activeElement;
|
|
515
|
+
this.previouslyFocused = active && active !== document.body ? active : null;
|
|
516
|
+
}
|
|
356
517
|
this.showModal = true;
|
|
518
|
+
this.focusModal();
|
|
519
|
+
if (this.historyClose && !this.embedded && !this.historyEntryPushed) {
|
|
520
|
+
history.pushState({ feedbackModal: true }, '');
|
|
521
|
+
this.historyEntryPushed = true;
|
|
522
|
+
}
|
|
357
523
|
requestAnimationFrame(() => {
|
|
358
524
|
requestAnimationFrame(() => {
|
|
359
525
|
this.isAnimating = true;
|
|
@@ -374,6 +540,24 @@ export class FeedbackModal {
|
|
|
374
540
|
}
|
|
375
541
|
static get properties() {
|
|
376
542
|
return {
|
|
543
|
+
"apiKey": {
|
|
544
|
+
"type": "string",
|
|
545
|
+
"mutable": false,
|
|
546
|
+
"complexType": {
|
|
547
|
+
"original": "string",
|
|
548
|
+
"resolved": "string",
|
|
549
|
+
"references": {}
|
|
550
|
+
},
|
|
551
|
+
"required": false,
|
|
552
|
+
"optional": false,
|
|
553
|
+
"docs": {
|
|
554
|
+
"tags": [],
|
|
555
|
+
"text": "Optional API key sent with feedback submissions, for projects that\nrequire one. Sent as `Authorization: Api-Key <key>` on the feedback POST\nrequest only, never on the public config request. Only use keys scoped to\n`feedback:submit`: like any credential used by an embedded widget, the\nvalue is part of the page and readable by any script running on it, so it\nprovides server-side scoping and traceability rather than client-side\nsecrecy. Intended for internal or access-controlled pages."
|
|
556
|
+
},
|
|
557
|
+
"attribute": "api-key",
|
|
558
|
+
"reflect": false,
|
|
559
|
+
"defaultValue": "''"
|
|
560
|
+
},
|
|
377
561
|
"customFont": {
|
|
378
562
|
"type": "boolean",
|
|
379
563
|
"mutable": false,
|
|
@@ -678,6 +862,60 @@ export class FeedbackModal {
|
|
|
678
862
|
"reflect": false,
|
|
679
863
|
"defaultValue": "false"
|
|
680
864
|
},
|
|
865
|
+
"clickOutsideClose": {
|
|
866
|
+
"type": "boolean",
|
|
867
|
+
"mutable": false,
|
|
868
|
+
"complexType": {
|
|
869
|
+
"original": "boolean",
|
|
870
|
+
"resolved": "boolean",
|
|
871
|
+
"references": {}
|
|
872
|
+
},
|
|
873
|
+
"required": false,
|
|
874
|
+
"optional": false,
|
|
875
|
+
"docs": {
|
|
876
|
+
"tags": [],
|
|
877
|
+
"text": ""
|
|
878
|
+
},
|
|
879
|
+
"attribute": "click-outside-close",
|
|
880
|
+
"reflect": false,
|
|
881
|
+
"defaultValue": "true"
|
|
882
|
+
},
|
|
883
|
+
"historyClose": {
|
|
884
|
+
"type": "boolean",
|
|
885
|
+
"mutable": false,
|
|
886
|
+
"complexType": {
|
|
887
|
+
"original": "boolean",
|
|
888
|
+
"resolved": "boolean",
|
|
889
|
+
"references": {}
|
|
890
|
+
},
|
|
891
|
+
"required": false,
|
|
892
|
+
"optional": false,
|
|
893
|
+
"docs": {
|
|
894
|
+
"tags": [],
|
|
895
|
+
"text": ""
|
|
896
|
+
},
|
|
897
|
+
"attribute": "history-close",
|
|
898
|
+
"reflect": false,
|
|
899
|
+
"defaultValue": "true"
|
|
900
|
+
},
|
|
901
|
+
"escapeClose": {
|
|
902
|
+
"type": "boolean",
|
|
903
|
+
"mutable": false,
|
|
904
|
+
"complexType": {
|
|
905
|
+
"original": "boolean",
|
|
906
|
+
"resolved": "boolean",
|
|
907
|
+
"references": {}
|
|
908
|
+
},
|
|
909
|
+
"required": false,
|
|
910
|
+
"optional": false,
|
|
911
|
+
"docs": {
|
|
912
|
+
"tags": [],
|
|
913
|
+
"text": ""
|
|
914
|
+
},
|
|
915
|
+
"attribute": "escape-close",
|
|
916
|
+
"reflect": false,
|
|
917
|
+
"defaultValue": "true"
|
|
918
|
+
},
|
|
681
919
|
"emailPlaceholder": {
|
|
682
920
|
"type": "string",
|
|
683
921
|
"mutable": false,
|
|
@@ -714,6 +952,24 @@ export class FeedbackModal {
|
|
|
714
952
|
"reflect": false,
|
|
715
953
|
"defaultValue": "'Please try again later.'"
|
|
716
954
|
},
|
|
955
|
+
"errorMessage401": {
|
|
956
|
+
"type": "string",
|
|
957
|
+
"mutable": false,
|
|
958
|
+
"complexType": {
|
|
959
|
+
"original": "string",
|
|
960
|
+
"resolved": "string",
|
|
961
|
+
"references": {}
|
|
962
|
+
},
|
|
963
|
+
"required": false,
|
|
964
|
+
"optional": false,
|
|
965
|
+
"docs": {
|
|
966
|
+
"tags": [],
|
|
967
|
+
"text": ""
|
|
968
|
+
},
|
|
969
|
+
"attribute": "error-message-4-0-1",
|
|
970
|
+
"reflect": false,
|
|
971
|
+
"defaultValue": "'This project requires a valid API key to submit feedback. Check the api-key attribute.'"
|
|
972
|
+
},
|
|
717
973
|
"errorMessage403": {
|
|
718
974
|
"type": "string",
|
|
719
975
|
"mutable": false,
|
|
@@ -930,6 +1186,78 @@ export class FeedbackModal {
|
|
|
930
1186
|
"reflect": false,
|
|
931
1187
|
"defaultValue": "'Send'"
|
|
932
1188
|
},
|
|
1189
|
+
"closeButtonLabel": {
|
|
1190
|
+
"type": "string",
|
|
1191
|
+
"mutable": false,
|
|
1192
|
+
"complexType": {
|
|
1193
|
+
"original": "string",
|
|
1194
|
+
"resolved": "string",
|
|
1195
|
+
"references": {}
|
|
1196
|
+
},
|
|
1197
|
+
"required": false,
|
|
1198
|
+
"optional": false,
|
|
1199
|
+
"docs": {
|
|
1200
|
+
"tags": [],
|
|
1201
|
+
"text": ""
|
|
1202
|
+
},
|
|
1203
|
+
"attribute": "close-button-label",
|
|
1204
|
+
"reflect": false,
|
|
1205
|
+
"defaultValue": "'Close feedback form'"
|
|
1206
|
+
},
|
|
1207
|
+
"ratingPositiveLabel": {
|
|
1208
|
+
"type": "string",
|
|
1209
|
+
"mutable": false,
|
|
1210
|
+
"complexType": {
|
|
1211
|
+
"original": "string",
|
|
1212
|
+
"resolved": "string",
|
|
1213
|
+
"references": {}
|
|
1214
|
+
},
|
|
1215
|
+
"required": false,
|
|
1216
|
+
"optional": false,
|
|
1217
|
+
"docs": {
|
|
1218
|
+
"tags": [],
|
|
1219
|
+
"text": ""
|
|
1220
|
+
},
|
|
1221
|
+
"attribute": "rating-positive-label",
|
|
1222
|
+
"reflect": false,
|
|
1223
|
+
"defaultValue": "'Yes'"
|
|
1224
|
+
},
|
|
1225
|
+
"ratingNegativeLabel": {
|
|
1226
|
+
"type": "string",
|
|
1227
|
+
"mutable": false,
|
|
1228
|
+
"complexType": {
|
|
1229
|
+
"original": "string",
|
|
1230
|
+
"resolved": "string",
|
|
1231
|
+
"references": {}
|
|
1232
|
+
},
|
|
1233
|
+
"required": false,
|
|
1234
|
+
"optional": false,
|
|
1235
|
+
"docs": {
|
|
1236
|
+
"tags": [],
|
|
1237
|
+
"text": ""
|
|
1238
|
+
},
|
|
1239
|
+
"attribute": "rating-negative-label",
|
|
1240
|
+
"reflect": false,
|
|
1241
|
+
"defaultValue": "'No'"
|
|
1242
|
+
},
|
|
1243
|
+
"ratingStarLabel": {
|
|
1244
|
+
"type": "string",
|
|
1245
|
+
"mutable": false,
|
|
1246
|
+
"complexType": {
|
|
1247
|
+
"original": "string",
|
|
1248
|
+
"resolved": "string",
|
|
1249
|
+
"references": {}
|
|
1250
|
+
},
|
|
1251
|
+
"required": false,
|
|
1252
|
+
"optional": false,
|
|
1253
|
+
"docs": {
|
|
1254
|
+
"tags": [],
|
|
1255
|
+
"text": ""
|
|
1256
|
+
},
|
|
1257
|
+
"attribute": "rating-star-label",
|
|
1258
|
+
"reflect": false,
|
|
1259
|
+
"defaultValue": "'Rate {rating} out of 5'"
|
|
1260
|
+
},
|
|
933
1261
|
"successMessage": {
|
|
934
1262
|
"type": "string",
|
|
935
1263
|
"mutable": false,
|
|
@@ -1340,6 +1668,9 @@ export class FeedbackModal {
|
|
|
1340
1668
|
"references": {
|
|
1341
1669
|
"Promise": {
|
|
1342
1670
|
"location": "global"
|
|
1671
|
+
},
|
|
1672
|
+
"HTMLElement": {
|
|
1673
|
+
"location": "global"
|
|
1343
1674
|
}
|
|
1344
1675
|
},
|
|
1345
1676
|
"return": "Promise<void>"
|