@product7/feedback-sdk 1.1.4 → 1.1.6
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/README.md +20 -16
- package/dist/README.md +20 -16
- package/dist/feedback-sdk.js +392 -410
- package/dist/feedback-sdk.js.map +1 -1
- package/dist/feedback-sdk.min.js +1 -1
- package/dist/feedback-sdk.min.js.map +1 -1
- package/package.json +1 -1
- package/src/core/APIService.js +14 -11
- package/src/core/FeedbackSDK.js +28 -11
- package/src/docs/api.md +46 -12
- package/src/docs/example.md +33 -31
- package/src/docs/installation.md +50 -41
- package/src/index.js +5 -2
- package/src/styles/styles.js +82 -226
- package/src/widgets/BaseWidget.js +37 -31
- package/src/widgets/ButtonWidget.js +10 -8
- package/src/widgets/SurveyWidget.js +221 -126
- package/types/index.d.ts +67 -62
package/dist/feedback-sdk.js
CHANGED
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
const MOCK_CONFIG = {
|
|
83
|
-
primaryColor: '#
|
|
83
|
+
primaryColor: '#21244A',
|
|
84
84
|
backgroundColor: '#ffffff',
|
|
85
85
|
textColor: '#1F2937',
|
|
86
86
|
boardId: 'feature-requests',
|
|
@@ -88,7 +88,6 @@
|
|
|
88
88
|
displayMode: 'modal',
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
-
// Environment URLs
|
|
92
91
|
const ENV_URLS = {
|
|
93
92
|
production: {
|
|
94
93
|
base: 'https://api.product7.io/api/v1',
|
|
@@ -96,7 +95,8 @@
|
|
|
96
95
|
},
|
|
97
96
|
staging: {
|
|
98
97
|
base: 'https://staging.api.product7.io/api/v1',
|
|
99
|
-
withWorkspace: (workspace) =>
|
|
98
|
+
withWorkspace: (workspace) =>
|
|
99
|
+
`https://${workspace}.staging.api.product7.io/api/v1`,
|
|
100
100
|
},
|
|
101
101
|
};
|
|
102
102
|
|
|
@@ -107,13 +107,11 @@
|
|
|
107
107
|
this.sessionExpiry = null;
|
|
108
108
|
this.userContext = config.userContext || null;
|
|
109
109
|
this.mock = config.mock || false;
|
|
110
|
-
this.env = config.env || 'production';
|
|
110
|
+
this.env = config.env || 'production';
|
|
111
111
|
|
|
112
112
|
if (config.apiUrl) {
|
|
113
|
-
// Custom API URL takes precedence
|
|
114
113
|
this.baseURL = config.apiUrl;
|
|
115
114
|
} else {
|
|
116
|
-
// Use environment-based URL
|
|
117
115
|
const envConfig = ENV_URLS[this.env] || ENV_URLS.production;
|
|
118
116
|
this.baseURL = this.workspace
|
|
119
117
|
? envConfig.withWorkspace(this.workspace)
|
|
@@ -192,7 +190,7 @@
|
|
|
192
190
|
|
|
193
191
|
// Mock mode - simulate success
|
|
194
192
|
if (this.mock) {
|
|
195
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
193
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
196
194
|
return {
|
|
197
195
|
success: true,
|
|
198
196
|
data: {
|
|
@@ -205,7 +203,8 @@
|
|
|
205
203
|
}
|
|
206
204
|
|
|
207
205
|
const payload = {
|
|
208
|
-
board:
|
|
206
|
+
board:
|
|
207
|
+
feedbackData.board_id || feedbackData.board || feedbackData.boardId,
|
|
209
208
|
title: feedbackData.title,
|
|
210
209
|
content: feedbackData.content,
|
|
211
210
|
attachments: feedbackData.attachments || [],
|
|
@@ -247,7 +246,10 @@
|
|
|
247
246
|
setUserContext(userContext) {
|
|
248
247
|
this.userContext = userContext;
|
|
249
248
|
if (typeof localStorage !== 'undefined') {
|
|
250
|
-
localStorage.setItem(
|
|
249
|
+
localStorage.setItem(
|
|
250
|
+
'feedbackSDK_userContext',
|
|
251
|
+
JSON.stringify(userContext)
|
|
252
|
+
);
|
|
251
253
|
}
|
|
252
254
|
}
|
|
253
255
|
|
|
@@ -308,7 +310,8 @@
|
|
|
308
310
|
|
|
309
311
|
try {
|
|
310
312
|
responseData = await response.json();
|
|
311
|
-
errorMessage =
|
|
313
|
+
errorMessage =
|
|
314
|
+
responseData.message || responseData.error || errorMessage;
|
|
312
315
|
} catch (e) {
|
|
313
316
|
errorMessage = (await response.text()) || errorMessage;
|
|
314
317
|
}
|
|
@@ -641,9 +644,9 @@
|
|
|
641
644
|
container: null,
|
|
642
645
|
position: this.sdk.config.position,
|
|
643
646
|
boardId: this.sdk.config.boardId,
|
|
644
|
-
displayMode: options.displayMode || 'panel',
|
|
645
|
-
size: options.size || 'medium',
|
|
646
|
-
primaryColor: options.primaryColor || '#
|
|
647
|
+
displayMode: options.displayMode || 'panel',
|
|
648
|
+
size: options.size || 'medium',
|
|
649
|
+
primaryColor: options.primaryColor || '#21244A',
|
|
647
650
|
backgroundColor: options.backgroundColor || '#ffffff',
|
|
648
651
|
textColor: options.textColor || '#1F2937',
|
|
649
652
|
autoShow: false,
|
|
@@ -886,12 +889,21 @@
|
|
|
886
889
|
this.backdropElement.addEventListener('click', this.closePanel);
|
|
887
890
|
}
|
|
888
891
|
|
|
889
|
-
const modeClass =
|
|
892
|
+
const modeClass =
|
|
893
|
+
this.options.displayMode === 'modal'
|
|
894
|
+
? 'feedback-modal'
|
|
895
|
+
: 'feedback-panel';
|
|
890
896
|
const sizeClass = `size-${this.options.size}`;
|
|
891
897
|
this.panelElement = document.createElement('div');
|
|
892
898
|
this.panelElement.className = `${modeClass} ${sizeClass}`;
|
|
893
|
-
this.panelElement.style.setProperty(
|
|
894
|
-
|
|
899
|
+
this.panelElement.style.setProperty(
|
|
900
|
+
'--primary-color',
|
|
901
|
+
this.options.primaryColor
|
|
902
|
+
);
|
|
903
|
+
this.panelElement.style.setProperty(
|
|
904
|
+
'--bg-color',
|
|
905
|
+
this.options.backgroundColor
|
|
906
|
+
);
|
|
895
907
|
this.panelElement.style.setProperty('--text-color', this.options.textColor);
|
|
896
908
|
this.panelElement.innerHTML = this._getPanelHTML();
|
|
897
909
|
|
|
@@ -906,44 +918,41 @@
|
|
|
906
918
|
|
|
907
919
|
_getPanelHTML() {
|
|
908
920
|
return `
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
921
|
+
<div class="feedback-panel-content">
|
|
922
|
+
<div class="feedback-panel-header">
|
|
923
|
+
<h3>Share Your Thoughts</h3>
|
|
924
|
+
<button class="feedback-panel-close" type="button" aria-label="Close">×</button>
|
|
925
|
+
</div>
|
|
926
|
+
<div class="feedback-panel-body">
|
|
927
|
+
<form class="feedback-form">
|
|
928
|
+
<div class="feedback-form-group">
|
|
929
|
+
<div class="feedback-input-container">
|
|
918
930
|
<input
|
|
919
931
|
type="text"
|
|
920
932
|
id="feedback-title-${this.id}"
|
|
921
933
|
name="title"
|
|
922
|
-
placeholder="
|
|
934
|
+
placeholder="Title"
|
|
923
935
|
value="${this.state.title}"
|
|
924
936
|
/>
|
|
925
|
-
</div>
|
|
926
|
-
<div class="feedback-form-group">
|
|
927
|
-
<label for="feedback-content-${this.id}">Message *</label>
|
|
928
937
|
<textarea
|
|
929
938
|
id="feedback-content-${this.id}"
|
|
930
939
|
name="content"
|
|
931
|
-
placeholder="Tell us what
|
|
940
|
+
placeholder="Tell us what's on your mind..."
|
|
932
941
|
required
|
|
933
942
|
>${this.state.content}</textarea>
|
|
934
943
|
</div>
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
</
|
|
941
|
-
</
|
|
942
|
-
</
|
|
944
|
+
</div>
|
|
945
|
+
<div class="feedback-error" role="alert"></div>
|
|
946
|
+
<div class="feedback-form-group">
|
|
947
|
+
<button type="submit" class="feedback-btn feedback-btn-submit">
|
|
948
|
+
${this.state.isSubmitting ? 'Sending...' : 'Submit Feedback'}
|
|
949
|
+
</button>
|
|
950
|
+
</div>
|
|
951
|
+
</form>
|
|
943
952
|
</div>
|
|
944
|
-
|
|
953
|
+
</div>
|
|
954
|
+
`;
|
|
945
955
|
}
|
|
946
|
-
|
|
947
956
|
_attachPanelEvents() {
|
|
948
957
|
const panel = this.panelElement;
|
|
949
958
|
|
|
@@ -1079,12 +1088,15 @@
|
|
|
1079
1088
|
const button = document.createElement('div');
|
|
1080
1089
|
button.className = `feedback-widget feedback-widget-button theme-${this.options.theme} position-${this.options.position}`;
|
|
1081
1090
|
button.innerHTML = `
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1091
|
+
<button class="feedback-trigger-btn" type="button" aria-label="Send feedback">
|
|
1092
|
+
<svg width="28" height="32" viewBox="0 0 28 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1093
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.0615 5.28044C8.5161 4.42949 3.30825 11.1456 5.89967 17.6588C6.9321 20.2538 9.06268 22.2644 11.8777 23.1968C16.2682 24.6507 18.4038 22.3222 19.0483 23.9691C19.4055 24.8894 18.7282 25.3209 17.988 25.4938C10.9146 27.15 5.15304 22.7566 3.5869 17.5531C1.52205 10.6941 5.98684 4.6667 11.3483 3.41065C17.8801 1.88094 24.0325 6.19355 24.3926 12.7175C24.7448 19.0921 18.6217 24.5978 11.927 22.2036C10.8789 21.8285 8.8419 20.6682 8.46823 19.858C8.06026 18.9727 8.80261 18.1725 9.68285 18.3576C10.2223 18.4726 10.3116 18.8706 11.3161 19.5372C14.4549 21.6213 19.1276 20.6132 21.2046 17.0972C23.991 12.3817 21.0481 6.05351 15.06 5.27758L15.0615 5.28044Z" fill="#21244A"/>
|
|
1094
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.2492 2.19833C11.944 1.71463 8.88819 3.07214 6.91479 4.49682C2.27067 7.85488 0.76169 14.5038 3.49672 19.8731C4.08535 21.0096 4.84379 22.0497 5.7459 22.9576L7.16343 24.2515C7.67214 24.9131 7.27203 25.7176 6.64115 25.9269C5.13502 26.4271 2.0499 21.8172 1.42044 20.5383C0.0872204 17.8297 -0.312889 14.9047 0.242977 11.503C1.66908 2.77063 11.221 -2.51652 19.7197 1.21021C27.7548 4.73331 30.2733 15.4555 23.9351 22.0773C23.3107 22.7296 21.6352 24.4823 20.6278 23.8907C20.0076 23.5263 19.8933 22.6446 20.5192 22.1238C21.0301 21.6986 21.4759 21.435 21.9896 20.9734C23.6665 19.4688 25.2562 16.8752 25.3477 13.5636C25.4427 10.2055 24.1266 7.5848 22.3904 5.74859C20.6392 3.89665 18.6751 2.69919 15.2456 2.19691L15.2492 2.19833Z" fill="#F69F06"/>
|
|
1095
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.48332 27.2217C7.93817 26.265 8.89987 25.3776 10.1352 25.8641C15.5653 27.9926 18.3081 25.5269 19.0255 27.0823C19.2655 27.6039 19.0448 28.1619 18.7354 28.3863C17.9895 28.9257 14.82 28.9343 13.9262 28.8714C12.9071 28.8053 11.897 28.6377 10.9111 28.3713C10.0888 28.1348 8.88057 27.9247 8.48189 27.2281L8.48332 27.2217Z" fill="#21244A"/>
|
|
1096
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.8722 31.0607C15.7765 32.1381 14.579 32.0331 13.5766 31.9545C12.5742 31.8759 11.5203 31.8502 11.601 30.7013C11.6789 29.5882 12.8035 29.7532 13.8274 29.8332C14.4425 29.8811 15.9951 29.681 15.8722 31.0607Z" fill="#21244A"/>
|
|
1097
|
+
</svg>
|
|
1098
|
+
</button>
|
|
1099
|
+
`;
|
|
1088
1100
|
|
|
1089
1101
|
if (this.options.customStyles) {
|
|
1090
1102
|
Object.assign(button.style, this.options.customStyles);
|
|
@@ -1092,7 +1104,6 @@
|
|
|
1092
1104
|
|
|
1093
1105
|
return button;
|
|
1094
1106
|
}
|
|
1095
|
-
|
|
1096
1107
|
_attachEvents() {
|
|
1097
1108
|
const button = this.element.querySelector('.feedback-trigger-btn');
|
|
1098
1109
|
button.addEventListener('click', this.openPanel);
|
|
@@ -1307,7 +1318,10 @@
|
|
|
1307
1318
|
show() {
|
|
1308
1319
|
this._renderSurvey();
|
|
1309
1320
|
this.surveyState.isVisible = true;
|
|
1310
|
-
this.sdk.eventBus.emit('survey:shown', {
|
|
1321
|
+
this.sdk.eventBus.emit('survey:shown', {
|
|
1322
|
+
widget: this,
|
|
1323
|
+
type: this.surveyOptions.surveyType,
|
|
1324
|
+
});
|
|
1311
1325
|
return this;
|
|
1312
1326
|
}
|
|
1313
1327
|
|
|
@@ -1322,16 +1336,19 @@
|
|
|
1322
1336
|
|
|
1323
1337
|
const config = this._getSurveyConfig();
|
|
1324
1338
|
const positionStyles = this._getPositionStyles();
|
|
1325
|
-
const themeStyles =
|
|
1326
|
-
|
|
1327
|
-
|
|
1339
|
+
const themeStyles =
|
|
1340
|
+
this.surveyOptions.theme === 'dark'
|
|
1341
|
+
? 'background: #1a1a1a; color: #fff;'
|
|
1342
|
+
: 'background: #fff; color: #1d1d1f;';
|
|
1328
1343
|
|
|
1329
1344
|
// Create backdrop for center position
|
|
1330
1345
|
if (this.surveyOptions.position === 'center') {
|
|
1331
1346
|
this.backdropElement = document.createElement('div');
|
|
1332
1347
|
this.backdropElement.className = 'feedback-survey-backdrop';
|
|
1333
1348
|
document.body.appendChild(this.backdropElement);
|
|
1334
|
-
this.backdropElement.addEventListener('click', () =>
|
|
1349
|
+
this.backdropElement.addEventListener('click', () =>
|
|
1350
|
+
this._handleDismiss()
|
|
1351
|
+
);
|
|
1335
1352
|
}
|
|
1336
1353
|
|
|
1337
1354
|
this.surveyElement = document.createElement('div');
|
|
@@ -1355,67 +1372,92 @@
|
|
|
1355
1372
|
// Animate in
|
|
1356
1373
|
requestAnimationFrame(() => {
|
|
1357
1374
|
this.surveyElement.style.opacity = '1';
|
|
1358
|
-
this.surveyElement.style.transform =
|
|
1359
|
-
|
|
1360
|
-
|
|
1375
|
+
this.surveyElement.style.transform =
|
|
1376
|
+
this.surveyOptions.position === 'center'
|
|
1377
|
+
? 'translate(-50%, -50%) scale(1)'
|
|
1378
|
+
: 'translateY(0)';
|
|
1361
1379
|
});
|
|
1362
1380
|
}
|
|
1363
1381
|
|
|
1364
1382
|
_getSurveyConfig() {
|
|
1365
1383
|
const configs = {
|
|
1366
1384
|
nps: {
|
|
1367
|
-
title:
|
|
1368
|
-
|
|
1385
|
+
title:
|
|
1386
|
+
this.surveyOptions.title || 'How likely are you to recommend us?',
|
|
1387
|
+
description:
|
|
1388
|
+
this.surveyOptions.description ||
|
|
1389
|
+
'On a scale of 0-10, how likely are you to recommend our product to a friend or colleague?',
|
|
1369
1390
|
html: `
|
|
1370
1391
|
<div class="feedback-survey-nps" style="display: flex; justify-content: space-between; gap: 4px;">
|
|
1371
|
-
${[...Array(11).keys()]
|
|
1392
|
+
${[...Array(11).keys()]
|
|
1393
|
+
.map(
|
|
1394
|
+
(n) => `
|
|
1372
1395
|
<button class="feedback-survey-nps-btn" data-score="${n}" style="width: 28px; height: 36px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 6px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa'}; cursor: pointer; font-size: 12px; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; transition: all 0.15s;">${n}</button>
|
|
1373
|
-
`
|
|
1396
|
+
`
|
|
1397
|
+
)
|
|
1398
|
+
.join('')}
|
|
1374
1399
|
</div>
|
|
1375
1400
|
<div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'};">
|
|
1376
1401
|
<span>${this.surveyOptions.lowLabel || 'Not likely'}</span>
|
|
1377
1402
|
<span>${this.surveyOptions.highLabel || 'Very likely'}</span>
|
|
1378
1403
|
</div>
|
|
1379
|
-
|
|
1404
|
+
`,
|
|
1380
1405
|
},
|
|
1381
1406
|
csat: {
|
|
1382
1407
|
title: this.surveyOptions.title || 'How satisfied are you?',
|
|
1383
|
-
description:
|
|
1408
|
+
description:
|
|
1409
|
+
this.surveyOptions.description ||
|
|
1410
|
+
'How would you rate your overall satisfaction with our product?',
|
|
1384
1411
|
html: `
|
|
1385
1412
|
<div class="feedback-survey-csat" style="display: flex; justify-content: center; gap: 16px;">
|
|
1386
|
-
${['😞', '😕', '😐', '🙂', '😄']
|
|
1413
|
+
${['😞', '😕', '😐', '🙂', '😄']
|
|
1414
|
+
.map(
|
|
1415
|
+
(emoji, i) => `
|
|
1387
1416
|
<button class="feedback-survey-csat-btn" data-score="${i + 1}" style="background: none; border: none; cursor: pointer; font-size: 36px; transition: transform 0.15s; padding: 8px;">${emoji}</button>
|
|
1388
|
-
`
|
|
1417
|
+
`
|
|
1418
|
+
)
|
|
1419
|
+
.join('')}
|
|
1389
1420
|
</div>
|
|
1390
1421
|
<div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'};">
|
|
1391
1422
|
<span>${this.surveyOptions.lowLabel || 'Very dissatisfied'}</span>
|
|
1392
1423
|
<span>${this.surveyOptions.highLabel || 'Very satisfied'}</span>
|
|
1393
1424
|
</div>
|
|
1394
|
-
|
|
1425
|
+
`,
|
|
1395
1426
|
},
|
|
1396
1427
|
ces: {
|
|
1397
1428
|
title: this.surveyOptions.title || 'How easy was it?',
|
|
1398
|
-
description:
|
|
1429
|
+
description:
|
|
1430
|
+
this.surveyOptions.description ||
|
|
1431
|
+
'How easy was it to accomplish your task today?',
|
|
1399
1432
|
html: `
|
|
1400
1433
|
<div class="feedback-survey-ces" style="display: flex; justify-content: space-between; gap: 8px;">
|
|
1401
|
-
${['Very Difficult', 'Difficult', 'Neutral', 'Easy', 'Very Easy']
|
|
1434
|
+
${['Very Difficult', 'Difficult', 'Neutral', 'Easy', 'Very Easy']
|
|
1435
|
+
.map(
|
|
1436
|
+
(label, i) => `
|
|
1402
1437
|
<button class="feedback-survey-ces-btn" data-score="${i + 1}" style="flex: 1; padding: 12px 8px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa'}; cursor: pointer; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; transition: all 0.15s;">${label}</button>
|
|
1403
|
-
`
|
|
1438
|
+
`
|
|
1439
|
+
)
|
|
1440
|
+
.join('')}
|
|
1404
1441
|
</div>
|
|
1405
|
-
|
|
1442
|
+
`,
|
|
1406
1443
|
},
|
|
1407
1444
|
custom: {
|
|
1408
1445
|
title: this.surveyOptions.title || 'Quick Feedback',
|
|
1409
|
-
description:
|
|
1410
|
-
|
|
1411
|
-
|
|
1446
|
+
description:
|
|
1447
|
+
this.surveyOptions.description ||
|
|
1448
|
+
'Help us improve by answering a few questions.',
|
|
1449
|
+
html: this._renderCustomQuestions(),
|
|
1450
|
+
},
|
|
1412
1451
|
};
|
|
1413
1452
|
|
|
1414
1453
|
return configs[this.surveyOptions.surveyType] || configs.nps;
|
|
1415
1454
|
}
|
|
1416
1455
|
|
|
1417
1456
|
_renderCustomQuestions() {
|
|
1418
|
-
if (
|
|
1457
|
+
if (
|
|
1458
|
+
!this.surveyOptions.customQuestions ||
|
|
1459
|
+
this.surveyOptions.customQuestions.length === 0
|
|
1460
|
+
) {
|
|
1419
1461
|
// Default custom questions
|
|
1420
1462
|
return `
|
|
1421
1463
|
<div style="margin-bottom: 16px;">
|
|
@@ -1431,20 +1473,28 @@
|
|
|
1431
1473
|
<div>
|
|
1432
1474
|
<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">How often do you use it?</label>
|
|
1433
1475
|
<div class="feedback-survey-frequency" style="display: flex; gap: 8px;">
|
|
1434
|
-
${['Daily', 'Weekly', 'Monthly', 'Rarely']
|
|
1476
|
+
${['Daily', 'Weekly', 'Monthly', 'Rarely']
|
|
1477
|
+
.map(
|
|
1478
|
+
(freq) => `
|
|
1435
1479
|
<button class="feedback-survey-freq-btn" data-freq="${freq}" style="flex: 1; padding: 10px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa'}; cursor: pointer; font-size: 12px; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; transition: all 0.15s;">${freq}</button>
|
|
1436
|
-
`
|
|
1480
|
+
`
|
|
1481
|
+
)
|
|
1482
|
+
.join('')}
|
|
1437
1483
|
</div>
|
|
1438
1484
|
</div>
|
|
1439
1485
|
`;
|
|
1440
1486
|
}
|
|
1441
1487
|
|
|
1442
|
-
return this.surveyOptions.customQuestions
|
|
1488
|
+
return this.surveyOptions.customQuestions
|
|
1489
|
+
.map(
|
|
1490
|
+
(q, index) => `
|
|
1443
1491
|
<div style="margin-bottom: 16px;">
|
|
1444
1492
|
<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">${q.label}</label>
|
|
1445
1493
|
${this._renderQuestionInput(q, index)}
|
|
1446
1494
|
</div>
|
|
1447
|
-
`
|
|
1495
|
+
`
|
|
1496
|
+
)
|
|
1497
|
+
.join('');
|
|
1448
1498
|
}
|
|
1449
1499
|
|
|
1450
1500
|
_renderQuestionInput(question, index) {
|
|
@@ -1453,7 +1503,7 @@
|
|
|
1453
1503
|
return `
|
|
1454
1504
|
<select class="feedback-survey-select" data-question="${question.id || index}" style="width: 100%; padding: 10px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; font-size: 14px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#fff'}; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'};">
|
|
1455
1505
|
<option value="">${question.placeholder || 'Select an option'}</option>
|
|
1456
|
-
${question.options.map(opt => `<option value="${opt.value}">${opt.label}</option>`).join('')}
|
|
1506
|
+
${question.options.map((opt) => `<option value="${opt.value}">${opt.label}</option>`).join('')}
|
|
1457
1507
|
</select>
|
|
1458
1508
|
`;
|
|
1459
1509
|
case 'text':
|
|
@@ -1467,10 +1517,14 @@
|
|
|
1467
1517
|
|
|
1468
1518
|
_getPositionStyles() {
|
|
1469
1519
|
const positions = {
|
|
1470
|
-
'bottom-right':
|
|
1471
|
-
|
|
1472
|
-
'
|
|
1473
|
-
|
|
1520
|
+
'bottom-right':
|
|
1521
|
+
'bottom: 24px; right: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',
|
|
1522
|
+
'bottom-left':
|
|
1523
|
+
'bottom: 24px; left: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',
|
|
1524
|
+
center:
|
|
1525
|
+
'top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.95); opacity: 0; transition: all 0.3s ease;',
|
|
1526
|
+
bottom:
|
|
1527
|
+
'bottom: 0; left: 0; right: 0; border-radius: 16px 16px 0 0; max-width: none; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',
|
|
1474
1528
|
};
|
|
1475
1529
|
return positions[this.surveyOptions.position] || positions['bottom-right'];
|
|
1476
1530
|
}
|
|
@@ -1483,11 +1537,15 @@
|
|
|
1483
1537
|
closeBtn.addEventListener('click', () => this._handleDismiss());
|
|
1484
1538
|
|
|
1485
1539
|
// Submit button
|
|
1486
|
-
const submitBtn = this.surveyElement.querySelector(
|
|
1540
|
+
const submitBtn = this.surveyElement.querySelector(
|
|
1541
|
+
'.feedback-survey-submit'
|
|
1542
|
+
);
|
|
1487
1543
|
submitBtn.addEventListener('click', () => this._handleSubmit());
|
|
1488
1544
|
|
|
1489
1545
|
// Feedback textarea
|
|
1490
|
-
const textarea = this.surveyElement.querySelector(
|
|
1546
|
+
const textarea = this.surveyElement.querySelector(
|
|
1547
|
+
'.feedback-survey-textarea'
|
|
1548
|
+
);
|
|
1491
1549
|
textarea.addEventListener('input', (e) => {
|
|
1492
1550
|
this.surveyState.feedback = e.target.value;
|
|
1493
1551
|
});
|
|
@@ -1508,133 +1566,177 @@
|
|
|
1508
1566
|
const type = this.surveyOptions.surveyType;
|
|
1509
1567
|
|
|
1510
1568
|
if (type === 'nps') {
|
|
1511
|
-
this.surveyElement
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
btn.
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
}
|
|
1569
|
+
this.surveyElement
|
|
1570
|
+
.querySelectorAll('.feedback-survey-nps-btn')
|
|
1571
|
+
.forEach((btn) => {
|
|
1572
|
+
btn.addEventListener('click', () =>
|
|
1573
|
+
this._selectNPS(parseInt(btn.dataset.score))
|
|
1574
|
+
);
|
|
1575
|
+
btn.addEventListener('mouseenter', () => {
|
|
1576
|
+
if (this.surveyState.score !== parseInt(btn.dataset.score)) {
|
|
1577
|
+
btn.style.borderColor = '#007aff';
|
|
1578
|
+
}
|
|
1579
|
+
});
|
|
1580
|
+
btn.addEventListener('mouseleave', () => {
|
|
1581
|
+
if (this.surveyState.score !== parseInt(btn.dataset.score)) {
|
|
1582
|
+
btn.style.borderColor =
|
|
1583
|
+
this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
|
|
1584
|
+
}
|
|
1585
|
+
});
|
|
1522
1586
|
});
|
|
1523
|
-
});
|
|
1524
1587
|
}
|
|
1525
1588
|
|
|
1526
1589
|
if (type === 'csat') {
|
|
1527
|
-
this.surveyElement
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
btn.
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
btn.style.transform = 'scale(1)';
|
|
1535
|
-
}
|
|
1590
|
+
this.surveyElement
|
|
1591
|
+
.querySelectorAll('.feedback-survey-csat-btn')
|
|
1592
|
+
.forEach((btn) => {
|
|
1593
|
+
btn.addEventListener('click', () =>
|
|
1594
|
+
this._selectCSAT(parseInt(btn.dataset.score))
|
|
1595
|
+
);
|
|
1596
|
+
btn.addEventListener('mouseenter', () => {
|
|
1597
|
+
btn.style.transform = 'scale(1.1)';
|
|
1598
|
+
});
|
|
1599
|
+
btn.addEventListener('mouseleave', () => {
|
|
1600
|
+
if (this.surveyState.score !== parseInt(btn.dataset.score)) {
|
|
1601
|
+
btn.style.transform = 'scale(1)';
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1536
1604
|
});
|
|
1537
|
-
});
|
|
1538
1605
|
}
|
|
1539
1606
|
|
|
1540
1607
|
if (type === 'ces') {
|
|
1541
|
-
this.surveyElement
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
btn.
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
}
|
|
1608
|
+
this.surveyElement
|
|
1609
|
+
.querySelectorAll('.feedback-survey-ces-btn')
|
|
1610
|
+
.forEach((btn) => {
|
|
1611
|
+
btn.addEventListener('click', () =>
|
|
1612
|
+
this._selectCES(parseInt(btn.dataset.score))
|
|
1613
|
+
);
|
|
1614
|
+
btn.addEventListener('mouseenter', () => {
|
|
1615
|
+
if (this.surveyState.score !== parseInt(btn.dataset.score)) {
|
|
1616
|
+
btn.style.borderColor = '#007aff';
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
btn.addEventListener('mouseleave', () => {
|
|
1620
|
+
if (this.surveyState.score !== parseInt(btn.dataset.score)) {
|
|
1621
|
+
btn.style.borderColor =
|
|
1622
|
+
this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
1552
1625
|
});
|
|
1553
|
-
});
|
|
1554
1626
|
}
|
|
1555
1627
|
|
|
1556
1628
|
if (type === 'custom') {
|
|
1557
1629
|
// Frequency buttons
|
|
1558
|
-
this.surveyElement
|
|
1559
|
-
|
|
1560
|
-
|
|
1630
|
+
this.surveyElement
|
|
1631
|
+
.querySelectorAll('.feedback-survey-freq-btn')
|
|
1632
|
+
.forEach((btn) => {
|
|
1633
|
+
btn.addEventListener('click', () =>
|
|
1634
|
+
this._selectFrequency(btn.dataset.freq)
|
|
1635
|
+
);
|
|
1636
|
+
});
|
|
1561
1637
|
|
|
1562
1638
|
// Select inputs
|
|
1563
|
-
this.surveyElement
|
|
1564
|
-
|
|
1565
|
-
|
|
1639
|
+
this.surveyElement
|
|
1640
|
+
.querySelectorAll('.feedback-survey-select')
|
|
1641
|
+
.forEach((select) => {
|
|
1642
|
+
select.addEventListener('change', (e) => {
|
|
1643
|
+
this.surveyState.customAnswers[select.dataset.question] =
|
|
1644
|
+
e.target.value;
|
|
1645
|
+
});
|
|
1566
1646
|
});
|
|
1567
|
-
});
|
|
1568
1647
|
|
|
1569
1648
|
// Text inputs
|
|
1570
|
-
this.surveyElement
|
|
1571
|
-
|
|
1572
|
-
|
|
1649
|
+
this.surveyElement
|
|
1650
|
+
.querySelectorAll('.feedback-survey-input')
|
|
1651
|
+
.forEach((input) => {
|
|
1652
|
+
input.addEventListener('input', (e) => {
|
|
1653
|
+
this.surveyState.customAnswers[input.dataset.question] =
|
|
1654
|
+
e.target.value;
|
|
1655
|
+
});
|
|
1573
1656
|
});
|
|
1574
|
-
});
|
|
1575
1657
|
}
|
|
1576
1658
|
}
|
|
1577
1659
|
|
|
1578
1660
|
_selectNPS(score) {
|
|
1579
1661
|
this.surveyState.score = score;
|
|
1580
|
-
this.surveyElement
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
btn.
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1662
|
+
this.surveyElement
|
|
1663
|
+
.querySelectorAll('.feedback-survey-nps-btn')
|
|
1664
|
+
.forEach((btn) => {
|
|
1665
|
+
const btnScore = parseInt(btn.dataset.score);
|
|
1666
|
+
if (btnScore === score) {
|
|
1667
|
+
btn.style.background = '#007aff';
|
|
1668
|
+
btn.style.borderColor = '#007aff';
|
|
1669
|
+
btn.style.color = '#fff';
|
|
1670
|
+
} else {
|
|
1671
|
+
btn.style.background =
|
|
1672
|
+
this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
|
|
1673
|
+
btn.style.borderColor =
|
|
1674
|
+
this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
|
|
1675
|
+
btn.style.color =
|
|
1676
|
+
this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
|
|
1677
|
+
}
|
|
1678
|
+
});
|
|
1592
1679
|
}
|
|
1593
1680
|
|
|
1594
1681
|
_selectCSAT(score) {
|
|
1595
1682
|
this.surveyState.score = score;
|
|
1596
|
-
this.surveyElement
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1683
|
+
this.surveyElement
|
|
1684
|
+
.querySelectorAll('.feedback-survey-csat-btn')
|
|
1685
|
+
.forEach((btn) => {
|
|
1686
|
+
const btnScore = parseInt(btn.dataset.score);
|
|
1687
|
+
btn.style.transform = btnScore === score ? 'scale(1.2)' : 'scale(1)';
|
|
1688
|
+
});
|
|
1600
1689
|
}
|
|
1601
1690
|
|
|
1602
1691
|
_selectCES(score) {
|
|
1603
1692
|
this.surveyState.score = score;
|
|
1604
|
-
this.surveyElement
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
btn.
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1693
|
+
this.surveyElement
|
|
1694
|
+
.querySelectorAll('.feedback-survey-ces-btn')
|
|
1695
|
+
.forEach((btn) => {
|
|
1696
|
+
const btnScore = parseInt(btn.dataset.score);
|
|
1697
|
+
if (btnScore === score) {
|
|
1698
|
+
btn.style.background = '#007aff';
|
|
1699
|
+
btn.style.borderColor = '#007aff';
|
|
1700
|
+
btn.style.color = '#fff';
|
|
1701
|
+
} else {
|
|
1702
|
+
btn.style.background =
|
|
1703
|
+
this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
|
|
1704
|
+
btn.style.borderColor =
|
|
1705
|
+
this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
|
|
1706
|
+
btn.style.color =
|
|
1707
|
+
this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1616
1710
|
}
|
|
1617
1711
|
|
|
1618
1712
|
_selectFrequency(freq) {
|
|
1619
1713
|
this.surveyState.customAnswers.frequency = freq;
|
|
1620
|
-
this.surveyElement
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
btn.
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1714
|
+
this.surveyElement
|
|
1715
|
+
.querySelectorAll('.feedback-survey-freq-btn')
|
|
1716
|
+
.forEach((btn) => {
|
|
1717
|
+
if (btn.dataset.freq === freq) {
|
|
1718
|
+
btn.style.background = '#007aff';
|
|
1719
|
+
btn.style.borderColor = '#007aff';
|
|
1720
|
+
btn.style.color = '#fff';
|
|
1721
|
+
} else {
|
|
1722
|
+
btn.style.background =
|
|
1723
|
+
this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
|
|
1724
|
+
btn.style.borderColor =
|
|
1725
|
+
this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
|
|
1726
|
+
btn.style.color =
|
|
1727
|
+
this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
|
|
1728
|
+
}
|
|
1729
|
+
});
|
|
1631
1730
|
}
|
|
1632
1731
|
|
|
1633
1732
|
async _handleSubmit() {
|
|
1634
1733
|
const type = this.surveyOptions.surveyType;
|
|
1635
1734
|
|
|
1636
1735
|
// Validate
|
|
1637
|
-
if (
|
|
1736
|
+
if (
|
|
1737
|
+
(type === 'nps' || type === 'csat' || type === 'ces') &&
|
|
1738
|
+
this.surveyState.score === null
|
|
1739
|
+
) {
|
|
1638
1740
|
this._showError('Please select a rating');
|
|
1639
1741
|
return;
|
|
1640
1742
|
}
|
|
@@ -1682,10 +1784,13 @@
|
|
|
1682
1784
|
|
|
1683
1785
|
const error = document.createElement('div');
|
|
1684
1786
|
error.className = 'feedback-survey-error';
|
|
1685
|
-
error.style.cssText =
|
|
1787
|
+
error.style.cssText =
|
|
1788
|
+
'color: #ef4444; font-size: 13px; margin-top: 8px; text-align: center;';
|
|
1686
1789
|
error.textContent = message;
|
|
1687
1790
|
|
|
1688
|
-
const submitBtn = this.surveyElement.querySelector(
|
|
1791
|
+
const submitBtn = this.surveyElement.querySelector(
|
|
1792
|
+
'.feedback-survey-submit'
|
|
1793
|
+
);
|
|
1689
1794
|
submitBtn.parentNode.insertBefore(error, submitBtn);
|
|
1690
1795
|
|
|
1691
1796
|
setTimeout(() => error.remove(), 3000);
|
|
@@ -1735,9 +1840,10 @@
|
|
|
1735
1840
|
|
|
1736
1841
|
if (surveyEl) {
|
|
1737
1842
|
surveyEl.style.opacity = '0';
|
|
1738
|
-
surveyEl.style.transform =
|
|
1739
|
-
|
|
1740
|
-
|
|
1843
|
+
surveyEl.style.transform =
|
|
1844
|
+
this.surveyOptions.position === 'center'
|
|
1845
|
+
? 'translate(-50%, -50%) scale(0.95)'
|
|
1846
|
+
: 'translateY(20px)';
|
|
1741
1847
|
setTimeout(() => {
|
|
1742
1848
|
if (surveyEl && surveyEl.parentNode) {
|
|
1743
1849
|
surveyEl.parentNode.removeChild(surveyEl);
|
|
@@ -1946,7 +2052,9 @@
|
|
|
1946
2052
|
|
|
1947
2053
|
createWidget(type = 'button', options = {}) {
|
|
1948
2054
|
if (!this.initialized) {
|
|
1949
|
-
throw new SDKError(
|
|
2055
|
+
throw new SDKError(
|
|
2056
|
+
'SDK must be initialized before creating widgets. Call init() first.'
|
|
2057
|
+
);
|
|
1950
2058
|
}
|
|
1951
2059
|
|
|
1952
2060
|
const widgetId = generateId('widget');
|
|
@@ -1988,7 +2096,9 @@
|
|
|
1988
2096
|
*/
|
|
1989
2097
|
showSurvey(options = {}) {
|
|
1990
2098
|
if (!this.initialized) {
|
|
1991
|
-
throw new SDKError(
|
|
2099
|
+
throw new SDKError(
|
|
2100
|
+
'SDK must be initialized before showing surveys. Call init() first.'
|
|
2101
|
+
);
|
|
1992
2102
|
}
|
|
1993
2103
|
|
|
1994
2104
|
const surveyWidget = this.createWidget('survey', {
|
|
@@ -2056,7 +2166,10 @@
|
|
|
2056
2166
|
}
|
|
2057
2167
|
|
|
2058
2168
|
getUserContext() {
|
|
2059
|
-
return
|
|
2169
|
+
return (
|
|
2170
|
+
this.config.userContext ||
|
|
2171
|
+
(this.apiService ? this.apiService.getUserContext() : null)
|
|
2172
|
+
);
|
|
2060
2173
|
}
|
|
2061
2174
|
|
|
2062
2175
|
async reinitialize(newUserContext = null) {
|
|
@@ -2112,7 +2225,10 @@
|
|
|
2112
2225
|
env: 'production', // 'production' or 'staging'
|
|
2113
2226
|
};
|
|
2114
2227
|
|
|
2115
|
-
const mergedConfig = deepMerge(
|
|
2228
|
+
const mergedConfig = deepMerge(
|
|
2229
|
+
deepMerge(defaultConfig, existingConfig),
|
|
2230
|
+
newConfig
|
|
2231
|
+
);
|
|
2116
2232
|
|
|
2117
2233
|
if (!mergedConfig.workspace) {
|
|
2118
2234
|
throw new ConfigError('Missing required configuration: workspace');
|
|
@@ -2127,7 +2243,9 @@
|
|
|
2127
2243
|
|
|
2128
2244
|
_validateUserContext(userContext) {
|
|
2129
2245
|
if (!userContext.user_id && !userContext.email) {
|
|
2130
|
-
throw new ConfigError(
|
|
2246
|
+
throw new ConfigError(
|
|
2247
|
+
'User context must include at least user_id or email'
|
|
2248
|
+
);
|
|
2131
2249
|
}
|
|
2132
2250
|
|
|
2133
2251
|
const validStructure = {
|
|
@@ -2140,7 +2258,9 @@
|
|
|
2140
2258
|
|
|
2141
2259
|
for (const [key, expectedType] of Object.entries(validStructure)) {
|
|
2142
2260
|
if (userContext[key] && typeof userContext[key] !== expectedType) {
|
|
2143
|
-
throw new ConfigError(
|
|
2261
|
+
throw new ConfigError(
|
|
2262
|
+
`User context field '${key}' must be of type '${expectedType}'`
|
|
2263
|
+
);
|
|
2144
2264
|
}
|
|
2145
2265
|
}
|
|
2146
2266
|
}
|
|
@@ -2173,18 +2293,21 @@
|
|
|
2173
2293
|
plan: authData.plan || authData.subscription?.plan,
|
|
2174
2294
|
...(authData.custom_fields || {}),
|
|
2175
2295
|
},
|
|
2176
|
-
company:
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2296
|
+
company:
|
|
2297
|
+
authData.company || authData.organization
|
|
2298
|
+
? {
|
|
2299
|
+
id: authData.company?.id || authData.organization?.id,
|
|
2300
|
+
name: authData.company?.name || authData.organization?.name,
|
|
2301
|
+
monthly_spend: authData.company?.monthly_spend,
|
|
2302
|
+
}
|
|
2303
|
+
: undefined,
|
|
2181
2304
|
};
|
|
2182
2305
|
}
|
|
2183
2306
|
}
|
|
2184
2307
|
|
|
2185
2308
|
const CSS_STYLES = `
|
|
2186
2309
|
.feedback-widget {
|
|
2187
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
|
2310
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
2188
2311
|
font-size: 14px;
|
|
2189
2312
|
line-height: 1.4;
|
|
2190
2313
|
z-index: 999999;
|
|
@@ -2240,47 +2363,45 @@
|
|
|
2240
2363
|
transform: translate(-50%, -50%);
|
|
2241
2364
|
}
|
|
2242
2365
|
|
|
2243
|
-
/*
|
|
2366
|
+
/* New button design - white with elevation */
|
|
2244
2367
|
.feedback-trigger-btn {
|
|
2245
|
-
width:
|
|
2246
|
-
height:
|
|
2368
|
+
width: 52px;
|
|
2369
|
+
height: 52px;
|
|
2247
2370
|
border-radius: 50%;
|
|
2248
|
-
border:
|
|
2249
|
-
background
|
|
2371
|
+
border: none;
|
|
2372
|
+
background: #ffffff;
|
|
2250
2373
|
cursor: pointer;
|
|
2251
2374
|
display: flex;
|
|
2252
2375
|
align-items: center;
|
|
2253
2376
|
justify-content: center;
|
|
2254
|
-
box-shadow:
|
|
2255
|
-
|
|
2377
|
+
box-shadow:
|
|
2378
|
+
0 2px 8px rgba(0, 0, 0, 0.08),
|
|
2379
|
+
0 4px 16px rgba(0, 0, 0, 0.06);
|
|
2380
|
+
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
|
2256
2381
|
padding: 0;
|
|
2257
|
-
color: #155eff; /* Icon color matches border */
|
|
2258
2382
|
}
|
|
2259
2383
|
|
|
2260
2384
|
.feedback-trigger-btn:hover {
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2385
|
+
box-shadow:
|
|
2386
|
+
0 4px 12px rgba(0, 0, 0, 0.1),
|
|
2387
|
+
0 8px 24px rgba(0, 0, 0, 0.08);
|
|
2388
|
+
transform: translateY(-2px);
|
|
2264
2389
|
}
|
|
2265
2390
|
|
|
2266
2391
|
.feedback-trigger-btn:active {
|
|
2267
|
-
transform:
|
|
2392
|
+
transform: translateY(0px);
|
|
2393
|
+
box-shadow:
|
|
2394
|
+
0 2px 6px rgba(0, 0, 0, 0.08),
|
|
2395
|
+
0 1px 4px rgba(0, 0, 0, 0.06);
|
|
2268
2396
|
}
|
|
2269
|
-
|
|
2270
2397
|
.feedback-trigger-btn svg {
|
|
2271
2398
|
flex-shrink: 0;
|
|
2399
|
+
width: 22px;
|
|
2400
|
+
height: 25px;
|
|
2272
2401
|
}
|
|
2273
2402
|
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
background-color: #1a1a1a;
|
|
2277
|
-
border-color: #155eff;
|
|
2278
|
-
color: #155eff;
|
|
2279
|
-
}
|
|
2280
|
-
|
|
2281
|
-
.theme-dark .feedback-trigger-btn:hover {
|
|
2282
|
-
background-color: #155eff;
|
|
2283
|
-
color: #ffffff;
|
|
2403
|
+
.feedback-trigger-btn svg path {
|
|
2404
|
+
fill: #21244A;
|
|
2284
2405
|
}
|
|
2285
2406
|
|
|
2286
2407
|
/* Loading Modal */
|
|
@@ -2302,17 +2423,12 @@
|
|
|
2302
2423
|
.feedback-loading-spinner {
|
|
2303
2424
|
width: 48px;
|
|
2304
2425
|
height: 48px;
|
|
2305
|
-
border: 4px solid rgba(
|
|
2306
|
-
border-top-color: #
|
|
2426
|
+
border: 4px solid rgba(0, 0, 0, 0.1);
|
|
2427
|
+
border-top-color: #21244A;
|
|
2307
2428
|
border-radius: 50%;
|
|
2308
2429
|
animation: spin 0.8s linear infinite;
|
|
2309
2430
|
}
|
|
2310
2431
|
|
|
2311
|
-
.theme-dark .feedback-loading-spinner {
|
|
2312
|
-
border-color: rgba(255, 255, 255, 0.2);
|
|
2313
|
-
border-top-color: #155EEF;
|
|
2314
|
-
}
|
|
2315
|
-
|
|
2316
2432
|
@keyframes spin {
|
|
2317
2433
|
to { transform: rotate(360deg); }
|
|
2318
2434
|
}
|
|
@@ -2367,15 +2483,6 @@
|
|
|
2367
2483
|
width: 520px;
|
|
2368
2484
|
}
|
|
2369
2485
|
|
|
2370
|
-
/* Adjust textarea height for sizes */
|
|
2371
|
-
.size-small .feedback-form-group textarea {
|
|
2372
|
-
min-height: 120px;
|
|
2373
|
-
}
|
|
2374
|
-
|
|
2375
|
-
.size-large .feedback-form-group textarea {
|
|
2376
|
-
min-height: 280px;
|
|
2377
|
-
}
|
|
2378
|
-
|
|
2379
2486
|
/* Side Panel Styles */
|
|
2380
2487
|
.feedback-panel {
|
|
2381
2488
|
position: fixed;
|
|
@@ -2399,7 +2506,8 @@
|
|
|
2399
2506
|
left: 0;
|
|
2400
2507
|
right: 0;
|
|
2401
2508
|
bottom: 0;
|
|
2402
|
-
background: rgba(0, 0, 0, 0.
|
|
2509
|
+
background: rgba(0, 0, 0, 0.4);
|
|
2510
|
+
backdrop-filter: blur(4px);
|
|
2403
2511
|
opacity: 0;
|
|
2404
2512
|
transition: opacity 0.3s ease;
|
|
2405
2513
|
pointer-events: none;
|
|
@@ -2413,22 +2521,19 @@
|
|
|
2413
2521
|
|
|
2414
2522
|
.feedback-panel-content {
|
|
2415
2523
|
background: var(--bg-color, #ffffff);
|
|
2416
|
-
color: var(--text-color, #
|
|
2524
|
+
color: var(--text-color, #171717);
|
|
2417
2525
|
height: 100%;
|
|
2418
2526
|
display: flex;
|
|
2419
2527
|
flex-direction: column;
|
|
2420
|
-
border-radius:
|
|
2421
|
-
|
|
2422
|
-
0 10px 10px -5px rgba(0, 0, 0, 0.04),
|
|
2423
|
-
0 0 0 1px rgba(0, 0, 0, 0.05);
|
|
2528
|
+
border-radius: 12px;
|
|
2529
|
+
border: 1px solid #e5e5e5;
|
|
2424
2530
|
}
|
|
2425
2531
|
|
|
2426
2532
|
.feedback-panel-header {
|
|
2427
2533
|
display: flex;
|
|
2428
2534
|
align-items: center;
|
|
2429
2535
|
justify-content: space-between;
|
|
2430
|
-
padding:
|
|
2431
|
-
border-bottom: 1px solid rgba(128, 128, 128, 0.2);
|
|
2536
|
+
padding: 24px 24px 20px 24px;
|
|
2432
2537
|
flex-shrink: 0;
|
|
2433
2538
|
}
|
|
2434
2539
|
|
|
@@ -2436,40 +2541,39 @@
|
|
|
2436
2541
|
margin: 0;
|
|
2437
2542
|
font-size: 18px;
|
|
2438
2543
|
font-weight: 600;
|
|
2439
|
-
color: var(--text-color, #
|
|
2544
|
+
color: var(--text-color, #171717);
|
|
2440
2545
|
}
|
|
2441
2546
|
|
|
2442
2547
|
.feedback-panel-close {
|
|
2443
2548
|
background: none;
|
|
2444
2549
|
border: none;
|
|
2445
|
-
font-size:
|
|
2550
|
+
font-size: 20px;
|
|
2446
2551
|
cursor: pointer;
|
|
2447
|
-
color:
|
|
2448
|
-
|
|
2449
|
-
padding: 4px;
|
|
2552
|
+
color: #737373;
|
|
2553
|
+
padding: 0;
|
|
2450
2554
|
width: 32px;
|
|
2451
2555
|
height: 32px;
|
|
2452
2556
|
display: flex;
|
|
2453
2557
|
align-items: center;
|
|
2454
2558
|
justify-content: center;
|
|
2455
|
-
border-radius:
|
|
2456
|
-
transition: all 0.
|
|
2559
|
+
border-radius: 8px;
|
|
2560
|
+
transition: all 0.15s ease;
|
|
2457
2561
|
}
|
|
2458
2562
|
|
|
2459
2563
|
.feedback-panel-close:hover {
|
|
2460
|
-
|
|
2461
|
-
|
|
2564
|
+
background: #f5f5f5;
|
|
2565
|
+
color: #171717;
|
|
2462
2566
|
}
|
|
2463
2567
|
|
|
2464
2568
|
.feedback-panel-close:focus-visible {
|
|
2465
|
-
outline: 2px solid var(--primary-color, #
|
|
2569
|
+
outline: 2px solid var(--primary-color, #21244A);
|
|
2466
2570
|
outline-offset: 2px;
|
|
2467
2571
|
}
|
|
2468
2572
|
|
|
2469
2573
|
.feedback-panel-body {
|
|
2470
2574
|
flex: 1;
|
|
2471
2575
|
overflow-y: auto;
|
|
2472
|
-
padding:
|
|
2576
|
+
padding: 0 24px 24px 24px;
|
|
2473
2577
|
}
|
|
2474
2578
|
|
|
2475
2579
|
.feedback-form {
|
|
@@ -2479,85 +2583,59 @@
|
|
|
2479
2583
|
}
|
|
2480
2584
|
|
|
2481
2585
|
.feedback-form-group {
|
|
2482
|
-
|
|
2483
|
-
flex-direction: column;
|
|
2484
|
-
gap: 8px;
|
|
2485
|
-
margin-bottom: 20px;
|
|
2586
|
+
margin-bottom: 16px;
|
|
2486
2587
|
}
|
|
2487
2588
|
|
|
2488
2589
|
.feedback-form-group:last-child {
|
|
2489
2590
|
margin-bottom: 0;
|
|
2490
2591
|
}
|
|
2491
2592
|
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2593
|
+
/* Unified input container */
|
|
2594
|
+
.feedback-input-container {
|
|
2595
|
+
border: 1px solid #e5e5e5;
|
|
2596
|
+
border-radius: 8px;
|
|
2597
|
+
padding: 16px;
|
|
2598
|
+
background: #ffffff;
|
|
2599
|
+
transition: all 0.15s ease;
|
|
2498
2600
|
}
|
|
2499
2601
|
|
|
2500
|
-
.feedback-
|
|
2501
|
-
|
|
2602
|
+
.feedback-input-container:focus-within {
|
|
2603
|
+
border-color: var(--primary-color, #21244A);
|
|
2604
|
+
box-shadow: 0 0 0 3px rgba(33, 36, 74, 0.08);
|
|
2605
|
+
}
|
|
2606
|
+
|
|
2607
|
+
.feedback-form-group input,
|
|
2608
|
+
.feedback-form-group textarea {
|
|
2502
2609
|
width: 100%;
|
|
2503
|
-
border
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
padding: 10px 14px;
|
|
2507
|
-
font-size: 15px;
|
|
2508
|
-
font-weight: 400;
|
|
2509
|
-
line-height: 1.5;
|
|
2510
|
-
color: var(--text-color, #1F2937);
|
|
2610
|
+
border: none;
|
|
2611
|
+
padding: 0;
|
|
2612
|
+
font-size: 14px;
|
|
2511
2613
|
font-family: inherit;
|
|
2614
|
+
color: var(--text-color, #171717);
|
|
2615
|
+
background: transparent;
|
|
2512
2616
|
outline: none;
|
|
2513
|
-
|
|
2617
|
+
resize: none;
|
|
2514
2618
|
}
|
|
2515
2619
|
|
|
2516
|
-
.feedback-form-group input
|
|
2620
|
+
.feedback-form-group input {
|
|
2621
|
+
font-weight: 600;
|
|
2517
2622
|
font-size: 15px;
|
|
2518
|
-
|
|
2519
|
-
opacity: 0.5;
|
|
2623
|
+
margin-bottom: 12px;
|
|
2520
2624
|
}
|
|
2521
2625
|
|
|
2522
|
-
.feedback-form-group input
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
}
|
|
2526
|
-
|
|
2527
|
-
.feedback-form-group input:focus-visible {
|
|
2528
|
-
outline: none;
|
|
2626
|
+
.feedback-form-group input::placeholder {
|
|
2627
|
+
color: #737373;
|
|
2628
|
+
font-weight: 600;
|
|
2529
2629
|
}
|
|
2530
2630
|
|
|
2531
2631
|
.feedback-form-group textarea {
|
|
2532
|
-
min-height:
|
|
2533
|
-
width: 100%;
|
|
2534
|
-
resize: vertical;
|
|
2535
|
-
border-radius: 8px;
|
|
2536
|
-
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
2537
|
-
background: rgba(128, 128, 128, 0.05);
|
|
2538
|
-
padding: 10px 14px;
|
|
2539
|
-
font-size: 15px;
|
|
2632
|
+
min-height: 120px;
|
|
2540
2633
|
font-weight: 400;
|
|
2541
|
-
line-height: 1.5;
|
|
2542
|
-
color: var(--text-color, #1F2937);
|
|
2543
|
-
font-family: inherit;
|
|
2544
|
-
outline: none;
|
|
2545
|
-
transition: all 0.2s ease;
|
|
2546
2634
|
}
|
|
2547
2635
|
|
|
2548
2636
|
.feedback-form-group textarea::placeholder {
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
opacity: 0.5;
|
|
2552
|
-
}
|
|
2553
|
-
|
|
2554
|
-
.feedback-form-group textarea:focus {
|
|
2555
|
-
border-color: var(--primary-color, #155EEF);
|
|
2556
|
-
box-shadow: 0 0 0 3px rgba(21, 94, 239, 0.1);
|
|
2557
|
-
}
|
|
2558
|
-
|
|
2559
|
-
.feedback-form-group textarea:focus-visible {
|
|
2560
|
-
outline: none;
|
|
2637
|
+
color: #a3a3a3;
|
|
2638
|
+
font-weight: 400;
|
|
2561
2639
|
}
|
|
2562
2640
|
|
|
2563
2641
|
.feedback-btn {
|
|
@@ -2574,7 +2652,7 @@
|
|
|
2574
2652
|
font-weight: 500;
|
|
2575
2653
|
font-family: inherit;
|
|
2576
2654
|
cursor: pointer;
|
|
2577
|
-
transition: all 0.
|
|
2655
|
+
transition: all 0.15s ease;
|
|
2578
2656
|
}
|
|
2579
2657
|
|
|
2580
2658
|
.feedback-btn:disabled {
|
|
@@ -2583,53 +2661,32 @@
|
|
|
2583
2661
|
}
|
|
2584
2662
|
|
|
2585
2663
|
.feedback-btn:focus-visible {
|
|
2586
|
-
outline: 2px solid #
|
|
2664
|
+
outline: 2px solid #21244A;
|
|
2587
2665
|
outline-offset: 2px;
|
|
2588
2666
|
}
|
|
2589
2667
|
|
|
2590
2668
|
.feedback-btn-submit {
|
|
2591
|
-
background: var(--primary-color, #
|
|
2669
|
+
background: var(--primary-color, #21244A);
|
|
2592
2670
|
color: white;
|
|
2593
2671
|
width: 100%;
|
|
2594
2672
|
}
|
|
2595
2673
|
|
|
2596
2674
|
.feedback-btn-submit:hover:not(:disabled) {
|
|
2597
|
-
background:
|
|
2598
|
-
filter: brightness(0.9);
|
|
2675
|
+
background: #2d3159;
|
|
2599
2676
|
}
|
|
2600
2677
|
|
|
2601
2678
|
.feedback-btn-submit:active:not(:disabled) {
|
|
2602
|
-
|
|
2603
|
-
filter: brightness(0.8);
|
|
2604
|
-
}
|
|
2605
|
-
|
|
2606
|
-
.feedback-btn-cancel {
|
|
2607
|
-
background: transparent;
|
|
2608
|
-
color: var(--text-color, #6B7280);
|
|
2609
|
-
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
2610
|
-
}
|
|
2611
|
-
|
|
2612
|
-
.feedback-btn-cancel:hover:not(:disabled) {
|
|
2613
|
-
background: rgba(128, 128, 128, 0.1);
|
|
2614
|
-
}
|
|
2615
|
-
|
|
2616
|
-
.feedback-form-actions {
|
|
2617
|
-
display: flex;
|
|
2618
|
-
flex-direction: column;
|
|
2619
|
-
gap: 12px;
|
|
2620
|
-
margin-top: auto;
|
|
2621
|
-
padding-top: 24px;
|
|
2679
|
+
transform: scale(0.98);
|
|
2622
2680
|
}
|
|
2623
2681
|
|
|
2624
2682
|
.feedback-error {
|
|
2683
|
+
background: #FEF2F2;
|
|
2684
|
+
border: 1px solid #FEE2E2;
|
|
2625
2685
|
color: #DC2626;
|
|
2626
|
-
|
|
2627
|
-
font-weight: 400;
|
|
2628
|
-
margin-top: 8px;
|
|
2629
|
-
padding: 12px;
|
|
2630
|
-
background: #FEE2E2;
|
|
2631
|
-
border: 1px solid #FECACA;
|
|
2686
|
+
padding: 12px 14px;
|
|
2632
2687
|
border-radius: 8px;
|
|
2688
|
+
font-size: 13px;
|
|
2689
|
+
margin-top: 12px;
|
|
2633
2690
|
display: none;
|
|
2634
2691
|
}
|
|
2635
2692
|
|
|
@@ -2637,12 +2694,6 @@
|
|
|
2637
2694
|
display: block;
|
|
2638
2695
|
}
|
|
2639
2696
|
|
|
2640
|
-
.feedback-panel.theme-dark .feedback-error {
|
|
2641
|
-
background: #7F1D1D;
|
|
2642
|
-
border-color: #991B1B;
|
|
2643
|
-
color: #FCA5A5;
|
|
2644
|
-
}
|
|
2645
|
-
|
|
2646
2697
|
.feedback-success-notification {
|
|
2647
2698
|
position: fixed;
|
|
2648
2699
|
top: 24px;
|
|
@@ -2707,7 +2758,7 @@
|
|
|
2707
2758
|
}
|
|
2708
2759
|
|
|
2709
2760
|
.feedback-success-close:focus-visible {
|
|
2710
|
-
outline: 2px solid #
|
|
2761
|
+
outline: 2px solid #21244A;
|
|
2711
2762
|
outline-offset: 2px;
|
|
2712
2763
|
}
|
|
2713
2764
|
|
|
@@ -2769,18 +2820,10 @@
|
|
|
2769
2820
|
border-radius: 2px;
|
|
2770
2821
|
}
|
|
2771
2822
|
|
|
2772
|
-
.feedback-panel.theme-dark .feedback-panel-header::before {
|
|
2773
|
-
background: #4B5563;
|
|
2774
|
-
}
|
|
2775
|
-
|
|
2776
2823
|
.feedback-panel-body {
|
|
2777
2824
|
padding: 20px;
|
|
2778
2825
|
}
|
|
2779
2826
|
|
|
2780
|
-
.feedback-form-group textarea {
|
|
2781
|
-
min-height: 150px;
|
|
2782
|
-
}
|
|
2783
|
-
|
|
2784
2827
|
.feedback-widget-button {
|
|
2785
2828
|
bottom: 16px;
|
|
2786
2829
|
right: 16px;
|
|
@@ -2817,74 +2860,13 @@
|
|
|
2817
2860
|
display: none !important;
|
|
2818
2861
|
}
|
|
2819
2862
|
}
|
|
2820
|
-
|
|
2821
|
-
/* Survey Widget Styles */
|
|
2822
|
-
.feedback-survey-backdrop {
|
|
2823
|
-
position: fixed;
|
|
2824
|
-
top: 0;
|
|
2825
|
-
left: 0;
|
|
2826
|
-
right: 0;
|
|
2827
|
-
bottom: 0;
|
|
2828
|
-
background: rgba(0, 0, 0, 0.5);
|
|
2829
|
-
z-index: 9999;
|
|
2830
|
-
opacity: 0;
|
|
2831
|
-
transition: opacity 0.3s ease;
|
|
2832
|
-
}
|
|
2833
|
-
|
|
2834
|
-
.feedback-survey-backdrop.show {
|
|
2835
|
-
opacity: 1;
|
|
2836
|
-
}
|
|
2837
|
-
|
|
2838
|
-
.feedback-survey {
|
|
2839
|
-
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
2840
|
-
}
|
|
2841
|
-
|
|
2842
|
-
.feedback-survey-csat-btn:hover {
|
|
2843
|
-
transform: scale(1.1) !important;
|
|
2844
|
-
}
|
|
2845
|
-
|
|
2846
|
-
.feedback-survey-nps-btn:hover,
|
|
2847
|
-
.feedback-survey-ces-btn:hover,
|
|
2848
|
-
.feedback-survey-freq-btn:hover {
|
|
2849
|
-
border-color: #007aff !important;
|
|
2850
|
-
}
|
|
2851
|
-
|
|
2852
|
-
@media (max-width: 768px) {
|
|
2853
|
-
.feedback-survey {
|
|
2854
|
-
left: 16px !important;
|
|
2855
|
-
right: 16px !important;
|
|
2856
|
-
max-width: none !important;
|
|
2857
|
-
min-width: auto !important;
|
|
2858
|
-
}
|
|
2859
|
-
|
|
2860
|
-
.feedback-survey.feedback-survey-center {
|
|
2861
|
-
width: calc(100% - 32px) !important;
|
|
2862
|
-
}
|
|
2863
|
-
|
|
2864
|
-
.feedback-survey-nps {
|
|
2865
|
-
flex-wrap: wrap;
|
|
2866
|
-
justify-content: center !important;
|
|
2867
|
-
}
|
|
2868
|
-
|
|
2869
|
-
.feedback-survey-nps-btn {
|
|
2870
|
-
width: 32px !important;
|
|
2871
|
-
height: 32px !important;
|
|
2872
|
-
font-size: 11px !important;
|
|
2873
|
-
}
|
|
2874
|
-
|
|
2875
|
-
.feedback-survey-ces {
|
|
2876
|
-
flex-direction: column !important;
|
|
2877
|
-
}
|
|
2878
|
-
|
|
2879
|
-
.feedback-survey-ces-btn {
|
|
2880
|
-
flex: none !important;
|
|
2881
|
-
width: 100% !important;
|
|
2882
|
-
}
|
|
2883
|
-
}
|
|
2884
2863
|
`;
|
|
2885
2864
|
|
|
2886
2865
|
function injectStyles() {
|
|
2887
|
-
if (
|
|
2866
|
+
if (
|
|
2867
|
+
typeof document !== 'undefined' &&
|
|
2868
|
+
!document.querySelector('#feedback-sdk-styles')
|
|
2869
|
+
) {
|
|
2888
2870
|
const style = document.createElement('style');
|
|
2889
2871
|
style.id = 'feedback-sdk-styles';
|
|
2890
2872
|
style.textContent = CSS_STYLES;
|