@product7/feedback-sdk 1.0.9 → 1.1.4
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 +181 -33
- package/dist/README.md +181 -33
- package/dist/feedback-sdk.js +904 -95
- 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 +55 -3
- package/src/core/FeedbackSDK.js +44 -1
- package/src/index.js +3 -0
- package/src/styles/styles.js +231 -80
- package/src/widgets/BaseWidget.js +68 -11
- package/src/widgets/SurveyWidget.js +504 -0
- package/src/widgets/WidgetFactory.js +2 -0
package/dist/feedback-sdk.js
CHANGED
|
@@ -79,19 +79,45 @@
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
const MOCK_CONFIG = {
|
|
83
|
+
primaryColor: '#155EEF',
|
|
84
|
+
backgroundColor: '#ffffff',
|
|
85
|
+
textColor: '#1F2937',
|
|
86
|
+
boardId: 'feature-requests',
|
|
87
|
+
size: 'medium',
|
|
88
|
+
displayMode: 'modal',
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Environment URLs
|
|
92
|
+
const ENV_URLS = {
|
|
93
|
+
production: {
|
|
94
|
+
base: 'https://api.product7.io/api/v1',
|
|
95
|
+
withWorkspace: (workspace) => `https://${workspace}.api.product7.io/api/v1`,
|
|
96
|
+
},
|
|
97
|
+
staging: {
|
|
98
|
+
base: 'https://staging.api.product7.io/api/v1',
|
|
99
|
+
withWorkspace: (workspace) => `https://${workspace}.staging.api.product7.io/api/v1`,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
82
103
|
class APIService {
|
|
83
104
|
constructor(config = {}) {
|
|
84
105
|
this.workspace = config.workspace;
|
|
85
106
|
this.sessionToken = null;
|
|
86
107
|
this.sessionExpiry = null;
|
|
87
108
|
this.userContext = config.userContext || null;
|
|
109
|
+
this.mock = config.mock || false;
|
|
110
|
+
this.env = config.env || 'production'; // 'production' or 'staging'
|
|
88
111
|
|
|
89
112
|
if (config.apiUrl) {
|
|
113
|
+
// Custom API URL takes precedence
|
|
90
114
|
this.baseURL = config.apiUrl;
|
|
91
|
-
} else if (this.workspace) {
|
|
92
|
-
this.baseURL = `https://${this.workspace}.staging.api.product7.io/api/v1`;
|
|
93
115
|
} else {
|
|
94
|
-
|
|
116
|
+
// Use environment-based URL
|
|
117
|
+
const envConfig = ENV_URLS[this.env] || ENV_URLS.production;
|
|
118
|
+
this.baseURL = this.workspace
|
|
119
|
+
? envConfig.withWorkspace(this.workspace)
|
|
120
|
+
: envConfig.base;
|
|
95
121
|
}
|
|
96
122
|
|
|
97
123
|
this._loadStoredSession();
|
|
@@ -111,6 +137,18 @@
|
|
|
111
137
|
throw new APIError(400, error);
|
|
112
138
|
}
|
|
113
139
|
|
|
140
|
+
// Mock mode - return fake session
|
|
141
|
+
if (this.mock) {
|
|
142
|
+
this.sessionToken = 'mock_session_' + Date.now();
|
|
143
|
+
this.sessionExpiry = new Date(Date.now() + 3600 * 1000);
|
|
144
|
+
this._storeSession();
|
|
145
|
+
return {
|
|
146
|
+
sessionToken: this.sessionToken,
|
|
147
|
+
config: MOCK_CONFIG,
|
|
148
|
+
expiresIn: 3600,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
114
152
|
const payload = {
|
|
115
153
|
workspace: this.workspace,
|
|
116
154
|
user: this.userContext,
|
|
@@ -152,6 +190,20 @@
|
|
|
152
190
|
throw new APIError(401, 'No valid session token available');
|
|
153
191
|
}
|
|
154
192
|
|
|
193
|
+
// Mock mode - simulate success
|
|
194
|
+
if (this.mock) {
|
|
195
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
196
|
+
return {
|
|
197
|
+
success: true,
|
|
198
|
+
data: {
|
|
199
|
+
id: 'mock_post_' + Date.now(),
|
|
200
|
+
title: feedbackData.title,
|
|
201
|
+
content: feedbackData.content,
|
|
202
|
+
},
|
|
203
|
+
message: 'Feedback submitted successfully!',
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
155
207
|
const payload = {
|
|
156
208
|
board: feedbackData.board_id || feedbackData.board || feedbackData.boardId,
|
|
157
209
|
title: feedbackData.title,
|
|
@@ -588,8 +640,12 @@
|
|
|
588
640
|
this.options = {
|
|
589
641
|
container: null,
|
|
590
642
|
position: this.sdk.config.position,
|
|
591
|
-
theme: this.sdk.config.theme,
|
|
592
643
|
boardId: this.sdk.config.boardId,
|
|
644
|
+
displayMode: options.displayMode || 'panel', // 'panel' or 'modal'
|
|
645
|
+
size: options.size || 'medium', // 'small', 'medium', 'large'
|
|
646
|
+
primaryColor: options.primaryColor || '#155EEF',
|
|
647
|
+
backgroundColor: options.backgroundColor || '#ffffff',
|
|
648
|
+
textColor: options.textColor || '#1F2937',
|
|
593
649
|
autoShow: false,
|
|
594
650
|
showBackdrop: true,
|
|
595
651
|
customStyles: {},
|
|
@@ -604,6 +660,7 @@
|
|
|
604
660
|
|
|
605
661
|
this.state = {
|
|
606
662
|
isOpen: false,
|
|
663
|
+
isLoading: false,
|
|
607
664
|
isSubmitting: false,
|
|
608
665
|
title: '',
|
|
609
666
|
content: '',
|
|
@@ -658,18 +715,65 @@
|
|
|
658
715
|
|
|
659
716
|
openPanel() {
|
|
660
717
|
this.state.isOpen = true;
|
|
661
|
-
|
|
662
|
-
|
|
718
|
+
|
|
719
|
+
if (this.options.displayMode === 'modal') {
|
|
720
|
+
this._showLoadingModal();
|
|
721
|
+
// Simulate loading delay then show form
|
|
722
|
+
setTimeout(() => {
|
|
723
|
+
this._hideLoadingModal();
|
|
724
|
+
this._renderPanel();
|
|
725
|
+
requestAnimationFrame(() => {
|
|
726
|
+
if (this.panelElement) {
|
|
727
|
+
this.panelElement.classList.add('open');
|
|
728
|
+
}
|
|
729
|
+
if (this.backdropElement) {
|
|
730
|
+
this.backdropElement.classList.add('show');
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
}, 600);
|
|
734
|
+
} else {
|
|
735
|
+
this._renderPanel();
|
|
736
|
+
requestAnimationFrame(() => {
|
|
737
|
+
if (this.panelElement) {
|
|
738
|
+
this.panelElement.classList.add('open');
|
|
739
|
+
}
|
|
740
|
+
if (this.backdropElement) {
|
|
741
|
+
this.backdropElement.classList.add('show');
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
_showLoadingModal() {
|
|
748
|
+
this.state.isLoading = true;
|
|
749
|
+
|
|
750
|
+
// Create backdrop
|
|
751
|
+
this.backdropElement = document.createElement('div');
|
|
752
|
+
this.backdropElement.className = 'feedback-panel-backdrop';
|
|
753
|
+
document.body.appendChild(this.backdropElement);
|
|
754
|
+
|
|
755
|
+
// Create loading modal
|
|
756
|
+
this.loadingElement = document.createElement('div');
|
|
757
|
+
this.loadingElement.className = `feedback-loading-modal theme-${this.options.theme}`;
|
|
758
|
+
this.loadingElement.innerHTML = `
|
|
759
|
+
<div class="feedback-loading-spinner"></div>
|
|
760
|
+
`;
|
|
761
|
+
document.body.appendChild(this.loadingElement);
|
|
762
|
+
|
|
663
763
|
requestAnimationFrame(() => {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
}
|
|
667
|
-
if (this.backdropElement) {
|
|
668
|
-
this.backdropElement.classList.add('show');
|
|
669
|
-
}
|
|
764
|
+
this.backdropElement.classList.add('show');
|
|
765
|
+
this.loadingElement.classList.add('show');
|
|
670
766
|
});
|
|
671
767
|
}
|
|
672
768
|
|
|
769
|
+
_hideLoadingModal() {
|
|
770
|
+
this.state.isLoading = false;
|
|
771
|
+
if (this.loadingElement) {
|
|
772
|
+
this.loadingElement.remove();
|
|
773
|
+
this.loadingElement = null;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
673
777
|
closePanel() {
|
|
674
778
|
if (this.panelElement) {
|
|
675
779
|
this.panelElement.classList.remove('open');
|
|
@@ -774,7 +878,7 @@
|
|
|
774
878
|
_renderPanel() {
|
|
775
879
|
if (this.panelElement) return;
|
|
776
880
|
|
|
777
|
-
if (this.options.showBackdrop) {
|
|
881
|
+
if (this.options.showBackdrop && !this.backdropElement) {
|
|
778
882
|
this.backdropElement = document.createElement('div');
|
|
779
883
|
this.backdropElement.className = 'feedback-panel-backdrop';
|
|
780
884
|
document.body.appendChild(this.backdropElement);
|
|
@@ -782,8 +886,13 @@
|
|
|
782
886
|
this.backdropElement.addEventListener('click', this.closePanel);
|
|
783
887
|
}
|
|
784
888
|
|
|
889
|
+
const modeClass = this.options.displayMode === 'modal' ? 'feedback-modal' : 'feedback-panel';
|
|
890
|
+
const sizeClass = `size-${this.options.size}`;
|
|
785
891
|
this.panelElement = document.createElement('div');
|
|
786
|
-
this.panelElement.className =
|
|
892
|
+
this.panelElement.className = `${modeClass} ${sizeClass}`;
|
|
893
|
+
this.panelElement.style.setProperty('--primary-color', this.options.primaryColor);
|
|
894
|
+
this.panelElement.style.setProperty('--bg-color', this.options.backgroundColor);
|
|
895
|
+
this.panelElement.style.setProperty('--text-color', this.options.textColor);
|
|
787
896
|
this.panelElement.innerHTML = this._getPanelHTML();
|
|
788
897
|
|
|
789
898
|
document.body.appendChild(this.panelElement);
|
|
@@ -1158,6 +1267,509 @@
|
|
|
1158
1267
|
}
|
|
1159
1268
|
}
|
|
1160
1269
|
|
|
1270
|
+
class SurveyWidget extends BaseWidget {
|
|
1271
|
+
constructor(options) {
|
|
1272
|
+
super({ ...options, type: 'survey' });
|
|
1273
|
+
|
|
1274
|
+
this.surveyOptions = {
|
|
1275
|
+
surveyType: options.surveyType || 'nps', // 'nps', 'csat', 'ces', 'custom'
|
|
1276
|
+
position: options.position || 'bottom-right', // 'bottom-right', 'bottom-left', 'center', 'bottom'
|
|
1277
|
+
title: options.title || null,
|
|
1278
|
+
description: options.description || null,
|
|
1279
|
+
lowLabel: options.lowLabel || null,
|
|
1280
|
+
highLabel: options.highLabel || null,
|
|
1281
|
+
customQuestions: options.customQuestions || [],
|
|
1282
|
+
theme: options.theme || 'light',
|
|
1283
|
+
onSubmit: options.onSubmit || null,
|
|
1284
|
+
onDismiss: options.onDismiss || null,
|
|
1285
|
+
};
|
|
1286
|
+
|
|
1287
|
+
this.surveyState = {
|
|
1288
|
+
score: null,
|
|
1289
|
+
feedback: '',
|
|
1290
|
+
customAnswers: {},
|
|
1291
|
+
isVisible: false,
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
_render() {
|
|
1296
|
+
// Survey widget doesn't render a trigger button, it's shown programmatically
|
|
1297
|
+
const container = document.createElement('div');
|
|
1298
|
+
container.className = 'feedback-survey-container';
|
|
1299
|
+
container.style.display = 'none';
|
|
1300
|
+
return container;
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
_attachEvents() {
|
|
1304
|
+
// Events are attached when survey is shown
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
show() {
|
|
1308
|
+
this._renderSurvey();
|
|
1309
|
+
this.surveyState.isVisible = true;
|
|
1310
|
+
this.sdk.eventBus.emit('survey:shown', { widget: this, type: this.surveyOptions.surveyType });
|
|
1311
|
+
return this;
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
hide() {
|
|
1315
|
+
this._closeSurvey();
|
|
1316
|
+
return this;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
_renderSurvey() {
|
|
1320
|
+
// Remove any existing survey
|
|
1321
|
+
this._closeSurvey();
|
|
1322
|
+
|
|
1323
|
+
const config = this._getSurveyConfig();
|
|
1324
|
+
const positionStyles = this._getPositionStyles();
|
|
1325
|
+
const themeStyles = this.surveyOptions.theme === 'dark'
|
|
1326
|
+
? 'background: #1a1a1a; color: #fff;'
|
|
1327
|
+
: 'background: #fff; color: #1d1d1f;';
|
|
1328
|
+
|
|
1329
|
+
// Create backdrop for center position
|
|
1330
|
+
if (this.surveyOptions.position === 'center') {
|
|
1331
|
+
this.backdropElement = document.createElement('div');
|
|
1332
|
+
this.backdropElement.className = 'feedback-survey-backdrop';
|
|
1333
|
+
document.body.appendChild(this.backdropElement);
|
|
1334
|
+
this.backdropElement.addEventListener('click', () => this._handleDismiss());
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
this.surveyElement = document.createElement('div');
|
|
1338
|
+
this.surveyElement.className = `feedback-survey feedback-survey-${this.surveyOptions.position} theme-${this.surveyOptions.theme}`;
|
|
1339
|
+
this.surveyElement.style.cssText = `position: fixed; ${positionStyles} z-index: 10000; ${themeStyles} border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); padding: 24px; min-width: 320px; max-width: 400px; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;`;
|
|
1340
|
+
|
|
1341
|
+
this.surveyElement.innerHTML = `
|
|
1342
|
+
<button class="feedback-survey-close" style="position: absolute; top: 12px; right: 12px; background: none; border: none; font-size: 20px; cursor: pointer; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'}; line-height: 1;">×</button>
|
|
1343
|
+
<h3 class="feedback-survey-title" style="margin: 0 0 8px 0; font-size: 18px; font-weight: 600; padding-right: 24px;">${config.title}</h3>
|
|
1344
|
+
<p class="feedback-survey-description" style="color: ${this.surveyOptions.theme === 'dark' ? '#aaa' : '#86868b'}; margin: 0 0 20px 0; font-size: 14px;">${config.description}</p>
|
|
1345
|
+
<div class="feedback-survey-content">${config.html}</div>
|
|
1346
|
+
<div class="feedback-survey-feedback" style="margin-top: 16px;">
|
|
1347
|
+
<textarea class="feedback-survey-textarea" placeholder="Any additional feedback? (optional)" style="width: 100%; padding: 12px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#333' : '#d2d2d7'}; border-radius: 8px; font-size: 14px; resize: none; height: 80px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#fff'}; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; font-family: inherit; box-sizing: border-box;"></textarea>
|
|
1348
|
+
</div>
|
|
1349
|
+
<button class="feedback-survey-submit" style="width: 100%; margin-top: 12px; padding: 12px; background: #007aff; color: white; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; font-family: inherit;">Submit</button>
|
|
1350
|
+
`;
|
|
1351
|
+
|
|
1352
|
+
document.body.appendChild(this.surveyElement);
|
|
1353
|
+
this._attachSurveyEvents();
|
|
1354
|
+
|
|
1355
|
+
// Animate in
|
|
1356
|
+
requestAnimationFrame(() => {
|
|
1357
|
+
this.surveyElement.style.opacity = '1';
|
|
1358
|
+
this.surveyElement.style.transform = this.surveyOptions.position === 'center'
|
|
1359
|
+
? 'translate(-50%, -50%) scale(1)'
|
|
1360
|
+
: 'translateY(0)';
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
_getSurveyConfig() {
|
|
1365
|
+
const configs = {
|
|
1366
|
+
nps: {
|
|
1367
|
+
title: this.surveyOptions.title || 'How likely are you to recommend us?',
|
|
1368
|
+
description: this.surveyOptions.description || 'On a scale of 0-10, how likely are you to recommend our product to a friend or colleague?',
|
|
1369
|
+
html: `
|
|
1370
|
+
<div class="feedback-survey-nps" style="display: flex; justify-content: space-between; gap: 4px;">
|
|
1371
|
+
${[...Array(11).keys()].map(n => `
|
|
1372
|
+
<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
|
+
`).join('')}
|
|
1374
|
+
</div>
|
|
1375
|
+
<div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'};">
|
|
1376
|
+
<span>${this.surveyOptions.lowLabel || 'Not likely'}</span>
|
|
1377
|
+
<span>${this.surveyOptions.highLabel || 'Very likely'}</span>
|
|
1378
|
+
</div>
|
|
1379
|
+
`
|
|
1380
|
+
},
|
|
1381
|
+
csat: {
|
|
1382
|
+
title: this.surveyOptions.title || 'How satisfied are you?',
|
|
1383
|
+
description: this.surveyOptions.description || 'How would you rate your overall satisfaction with our product?',
|
|
1384
|
+
html: `
|
|
1385
|
+
<div class="feedback-survey-csat" style="display: flex; justify-content: center; gap: 16px;">
|
|
1386
|
+
${['😞', '😕', '😐', '🙂', '😄'].map((emoji, i) => `
|
|
1387
|
+
<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
|
+
`).join('')}
|
|
1389
|
+
</div>
|
|
1390
|
+
<div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'};">
|
|
1391
|
+
<span>${this.surveyOptions.lowLabel || 'Very dissatisfied'}</span>
|
|
1392
|
+
<span>${this.surveyOptions.highLabel || 'Very satisfied'}</span>
|
|
1393
|
+
</div>
|
|
1394
|
+
`
|
|
1395
|
+
},
|
|
1396
|
+
ces: {
|
|
1397
|
+
title: this.surveyOptions.title || 'How easy was it?',
|
|
1398
|
+
description: this.surveyOptions.description || 'How easy was it to accomplish your task today?',
|
|
1399
|
+
html: `
|
|
1400
|
+
<div class="feedback-survey-ces" style="display: flex; justify-content: space-between; gap: 8px;">
|
|
1401
|
+
${['Very Difficult', 'Difficult', 'Neutral', 'Easy', 'Very Easy'].map((label, i) => `
|
|
1402
|
+
<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
|
+
`).join('')}
|
|
1404
|
+
</div>
|
|
1405
|
+
`
|
|
1406
|
+
},
|
|
1407
|
+
custom: {
|
|
1408
|
+
title: this.surveyOptions.title || 'Quick Feedback',
|
|
1409
|
+
description: this.surveyOptions.description || 'Help us improve by answering a few questions.',
|
|
1410
|
+
html: this._renderCustomQuestions()
|
|
1411
|
+
}
|
|
1412
|
+
};
|
|
1413
|
+
|
|
1414
|
+
return configs[this.surveyOptions.surveyType] || configs.nps;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
_renderCustomQuestions() {
|
|
1418
|
+
if (!this.surveyOptions.customQuestions || this.surveyOptions.customQuestions.length === 0) {
|
|
1419
|
+
// Default custom questions
|
|
1420
|
+
return `
|
|
1421
|
+
<div style="margin-bottom: 16px;">
|
|
1422
|
+
<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">What feature do you use most?</label>
|
|
1423
|
+
<select class="feedback-survey-select" data-question="feature" 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'};">
|
|
1424
|
+
<option value="">Select a feature</option>
|
|
1425
|
+
<option value="feedback">Feedback Collection</option>
|
|
1426
|
+
<option value="surveys">Surveys</option>
|
|
1427
|
+
<option value="analytics">Analytics</option>
|
|
1428
|
+
<option value="integrations">Integrations</option>
|
|
1429
|
+
</select>
|
|
1430
|
+
</div>
|
|
1431
|
+
<div>
|
|
1432
|
+
<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">How often do you use it?</label>
|
|
1433
|
+
<div class="feedback-survey-frequency" style="display: flex; gap: 8px;">
|
|
1434
|
+
${['Daily', 'Weekly', 'Monthly', 'Rarely'].map(freq => `
|
|
1435
|
+
<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
|
+
`).join('')}
|
|
1437
|
+
</div>
|
|
1438
|
+
</div>
|
|
1439
|
+
`;
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
return this.surveyOptions.customQuestions.map((q, index) => `
|
|
1443
|
+
<div style="margin-bottom: 16px;">
|
|
1444
|
+
<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">${q.label}</label>
|
|
1445
|
+
${this._renderQuestionInput(q, index)}
|
|
1446
|
+
</div>
|
|
1447
|
+
`).join('');
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
_renderQuestionInput(question, index) {
|
|
1451
|
+
switch (question.type) {
|
|
1452
|
+
case 'select':
|
|
1453
|
+
return `
|
|
1454
|
+
<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
|
+
<option value="">${question.placeholder || 'Select an option'}</option>
|
|
1456
|
+
${question.options.map(opt => `<option value="${opt.value}">${opt.label}</option>`).join('')}
|
|
1457
|
+
</select>
|
|
1458
|
+
`;
|
|
1459
|
+
case 'text':
|
|
1460
|
+
return `
|
|
1461
|
+
<input type="text" class="feedback-survey-input" data-question="${question.id || index}" placeholder="${question.placeholder || ''}" 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'}; box-sizing: border-box;">
|
|
1462
|
+
`;
|
|
1463
|
+
default:
|
|
1464
|
+
return '';
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
_getPositionStyles() {
|
|
1469
|
+
const positions = {
|
|
1470
|
+
'bottom-right': 'bottom: 24px; right: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',
|
|
1471
|
+
'bottom-left': 'bottom: 24px; left: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',
|
|
1472
|
+
'center': 'top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.95); opacity: 0; transition: all 0.3s ease;',
|
|
1473
|
+
'bottom': '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
|
+
};
|
|
1475
|
+
return positions[this.surveyOptions.position] || positions['bottom-right'];
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
_attachSurveyEvents() {
|
|
1479
|
+
if (!this.surveyElement) return;
|
|
1480
|
+
|
|
1481
|
+
// Close button
|
|
1482
|
+
const closeBtn = this.surveyElement.querySelector('.feedback-survey-close');
|
|
1483
|
+
closeBtn.addEventListener('click', () => this._handleDismiss());
|
|
1484
|
+
|
|
1485
|
+
// Submit button
|
|
1486
|
+
const submitBtn = this.surveyElement.querySelector('.feedback-survey-submit');
|
|
1487
|
+
submitBtn.addEventListener('click', () => this._handleSubmit());
|
|
1488
|
+
|
|
1489
|
+
// Feedback textarea
|
|
1490
|
+
const textarea = this.surveyElement.querySelector('.feedback-survey-textarea');
|
|
1491
|
+
textarea.addEventListener('input', (e) => {
|
|
1492
|
+
this.surveyState.feedback = e.target.value;
|
|
1493
|
+
});
|
|
1494
|
+
|
|
1495
|
+
// Survey type specific events
|
|
1496
|
+
this._attachTypeSpecificEvents();
|
|
1497
|
+
|
|
1498
|
+
// Escape key
|
|
1499
|
+
this._escapeHandler = (e) => {
|
|
1500
|
+
if (e.key === 'Escape') {
|
|
1501
|
+
this._handleDismiss();
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1504
|
+
document.addEventListener('keydown', this._escapeHandler);
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
_attachTypeSpecificEvents() {
|
|
1508
|
+
const type = this.surveyOptions.surveyType;
|
|
1509
|
+
|
|
1510
|
+
if (type === 'nps') {
|
|
1511
|
+
this.surveyElement.querySelectorAll('.feedback-survey-nps-btn').forEach(btn => {
|
|
1512
|
+
btn.addEventListener('click', () => this._selectNPS(parseInt(btn.dataset.score)));
|
|
1513
|
+
btn.addEventListener('mouseenter', () => {
|
|
1514
|
+
if (this.surveyState.score !== parseInt(btn.dataset.score)) {
|
|
1515
|
+
btn.style.borderColor = '#007aff';
|
|
1516
|
+
}
|
|
1517
|
+
});
|
|
1518
|
+
btn.addEventListener('mouseleave', () => {
|
|
1519
|
+
if (this.surveyState.score !== parseInt(btn.dataset.score)) {
|
|
1520
|
+
btn.style.borderColor = this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
|
|
1521
|
+
}
|
|
1522
|
+
});
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
if (type === 'csat') {
|
|
1527
|
+
this.surveyElement.querySelectorAll('.feedback-survey-csat-btn').forEach(btn => {
|
|
1528
|
+
btn.addEventListener('click', () => this._selectCSAT(parseInt(btn.dataset.score)));
|
|
1529
|
+
btn.addEventListener('mouseenter', () => {
|
|
1530
|
+
btn.style.transform = 'scale(1.1)';
|
|
1531
|
+
});
|
|
1532
|
+
btn.addEventListener('mouseleave', () => {
|
|
1533
|
+
if (this.surveyState.score !== parseInt(btn.dataset.score)) {
|
|
1534
|
+
btn.style.transform = 'scale(1)';
|
|
1535
|
+
}
|
|
1536
|
+
});
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
if (type === 'ces') {
|
|
1541
|
+
this.surveyElement.querySelectorAll('.feedback-survey-ces-btn').forEach(btn => {
|
|
1542
|
+
btn.addEventListener('click', () => this._selectCES(parseInt(btn.dataset.score)));
|
|
1543
|
+
btn.addEventListener('mouseenter', () => {
|
|
1544
|
+
if (this.surveyState.score !== parseInt(btn.dataset.score)) {
|
|
1545
|
+
btn.style.borderColor = '#007aff';
|
|
1546
|
+
}
|
|
1547
|
+
});
|
|
1548
|
+
btn.addEventListener('mouseleave', () => {
|
|
1549
|
+
if (this.surveyState.score !== parseInt(btn.dataset.score)) {
|
|
1550
|
+
btn.style.borderColor = this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
|
|
1551
|
+
}
|
|
1552
|
+
});
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
if (type === 'custom') {
|
|
1557
|
+
// Frequency buttons
|
|
1558
|
+
this.surveyElement.querySelectorAll('.feedback-survey-freq-btn').forEach(btn => {
|
|
1559
|
+
btn.addEventListener('click', () => this._selectFrequency(btn.dataset.freq));
|
|
1560
|
+
});
|
|
1561
|
+
|
|
1562
|
+
// Select inputs
|
|
1563
|
+
this.surveyElement.querySelectorAll('.feedback-survey-select').forEach(select => {
|
|
1564
|
+
select.addEventListener('change', (e) => {
|
|
1565
|
+
this.surveyState.customAnswers[select.dataset.question] = e.target.value;
|
|
1566
|
+
});
|
|
1567
|
+
});
|
|
1568
|
+
|
|
1569
|
+
// Text inputs
|
|
1570
|
+
this.surveyElement.querySelectorAll('.feedback-survey-input').forEach(input => {
|
|
1571
|
+
input.addEventListener('input', (e) => {
|
|
1572
|
+
this.surveyState.customAnswers[input.dataset.question] = e.target.value;
|
|
1573
|
+
});
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
_selectNPS(score) {
|
|
1579
|
+
this.surveyState.score = score;
|
|
1580
|
+
this.surveyElement.querySelectorAll('.feedback-survey-nps-btn').forEach(btn => {
|
|
1581
|
+
const btnScore = parseInt(btn.dataset.score);
|
|
1582
|
+
if (btnScore === score) {
|
|
1583
|
+
btn.style.background = '#007aff';
|
|
1584
|
+
btn.style.borderColor = '#007aff';
|
|
1585
|
+
btn.style.color = '#fff';
|
|
1586
|
+
} else {
|
|
1587
|
+
btn.style.background = this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
|
|
1588
|
+
btn.style.borderColor = this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
|
|
1589
|
+
btn.style.color = this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
|
|
1590
|
+
}
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
_selectCSAT(score) {
|
|
1595
|
+
this.surveyState.score = score;
|
|
1596
|
+
this.surveyElement.querySelectorAll('.feedback-survey-csat-btn').forEach(btn => {
|
|
1597
|
+
const btnScore = parseInt(btn.dataset.score);
|
|
1598
|
+
btn.style.transform = btnScore === score ? 'scale(1.2)' : 'scale(1)';
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
_selectCES(score) {
|
|
1603
|
+
this.surveyState.score = score;
|
|
1604
|
+
this.surveyElement.querySelectorAll('.feedback-survey-ces-btn').forEach(btn => {
|
|
1605
|
+
const btnScore = parseInt(btn.dataset.score);
|
|
1606
|
+
if (btnScore === score) {
|
|
1607
|
+
btn.style.background = '#007aff';
|
|
1608
|
+
btn.style.borderColor = '#007aff';
|
|
1609
|
+
btn.style.color = '#fff';
|
|
1610
|
+
} else {
|
|
1611
|
+
btn.style.background = this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
|
|
1612
|
+
btn.style.borderColor = this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
|
|
1613
|
+
btn.style.color = this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
|
|
1614
|
+
}
|
|
1615
|
+
});
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
_selectFrequency(freq) {
|
|
1619
|
+
this.surveyState.customAnswers.frequency = freq;
|
|
1620
|
+
this.surveyElement.querySelectorAll('.feedback-survey-freq-btn').forEach(btn => {
|
|
1621
|
+
if (btn.dataset.freq === freq) {
|
|
1622
|
+
btn.style.background = '#007aff';
|
|
1623
|
+
btn.style.borderColor = '#007aff';
|
|
1624
|
+
btn.style.color = '#fff';
|
|
1625
|
+
} else {
|
|
1626
|
+
btn.style.background = this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
|
|
1627
|
+
btn.style.borderColor = this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
|
|
1628
|
+
btn.style.color = this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
|
|
1629
|
+
}
|
|
1630
|
+
});
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
async _handleSubmit() {
|
|
1634
|
+
const type = this.surveyOptions.surveyType;
|
|
1635
|
+
|
|
1636
|
+
// Validate
|
|
1637
|
+
if ((type === 'nps' || type === 'csat' || type === 'ces') && this.surveyState.score === null) {
|
|
1638
|
+
this._showError('Please select a rating');
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
const response = {
|
|
1643
|
+
type: type,
|
|
1644
|
+
score: this.surveyState.score,
|
|
1645
|
+
feedback: this.surveyState.feedback,
|
|
1646
|
+
customAnswers: this.surveyState.customAnswers,
|
|
1647
|
+
timestamp: new Date().toISOString(),
|
|
1648
|
+
};
|
|
1649
|
+
|
|
1650
|
+
// Call onSubmit callback if provided
|
|
1651
|
+
if (this.surveyOptions.onSubmit) {
|
|
1652
|
+
this.surveyOptions.onSubmit(response);
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
// Submit to API if not in mock mode
|
|
1656
|
+
if (!this.sdk.config.mock) {
|
|
1657
|
+
try {
|
|
1658
|
+
await this.apiService.submitSurveyResponse(response);
|
|
1659
|
+
} catch (error) {
|
|
1660
|
+
console.error('[SurveyWidget] Failed to submit survey:', error);
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
this.sdk.eventBus.emit('survey:submitted', { widget: this, response });
|
|
1665
|
+
|
|
1666
|
+
this._closeSurvey();
|
|
1667
|
+
this._showSuccessNotification();
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
_handleDismiss() {
|
|
1671
|
+
if (this.surveyOptions.onDismiss) {
|
|
1672
|
+
this.surveyOptions.onDismiss();
|
|
1673
|
+
}
|
|
1674
|
+
this.sdk.eventBus.emit('survey:dismissed', { widget: this });
|
|
1675
|
+
this._closeSurvey();
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
_showError(message) {
|
|
1679
|
+
// Simple error display - could be enhanced
|
|
1680
|
+
const existing = this.surveyElement.querySelector('.feedback-survey-error');
|
|
1681
|
+
if (existing) existing.remove();
|
|
1682
|
+
|
|
1683
|
+
const error = document.createElement('div');
|
|
1684
|
+
error.className = 'feedback-survey-error';
|
|
1685
|
+
error.style.cssText = 'color: #ef4444; font-size: 13px; margin-top: 8px; text-align: center;';
|
|
1686
|
+
error.textContent = message;
|
|
1687
|
+
|
|
1688
|
+
const submitBtn = this.surveyElement.querySelector('.feedback-survey-submit');
|
|
1689
|
+
submitBtn.parentNode.insertBefore(error, submitBtn);
|
|
1690
|
+
|
|
1691
|
+
setTimeout(() => error.remove(), 3000);
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
_showSuccessNotification() {
|
|
1695
|
+
const notification = document.createElement('div');
|
|
1696
|
+
notification.className = 'feedback-survey-success';
|
|
1697
|
+
notification.style.cssText = `
|
|
1698
|
+
position: fixed;
|
|
1699
|
+
top: 24px;
|
|
1700
|
+
right: 24px;
|
|
1701
|
+
background: #10b981;
|
|
1702
|
+
color: white;
|
|
1703
|
+
padding: 16px 24px;
|
|
1704
|
+
border-radius: 12px;
|
|
1705
|
+
font-size: 14px;
|
|
1706
|
+
font-weight: 500;
|
|
1707
|
+
z-index: 10001;
|
|
1708
|
+
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
|
|
1709
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
1710
|
+
`;
|
|
1711
|
+
notification.innerHTML = `
|
|
1712
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
1713
|
+
<span style="font-size: 18px;">✓</span>
|
|
1714
|
+
<span>Thank you for your feedback!</span>
|
|
1715
|
+
</div>
|
|
1716
|
+
`;
|
|
1717
|
+
document.body.appendChild(notification);
|
|
1718
|
+
|
|
1719
|
+
setTimeout(() => {
|
|
1720
|
+
notification.style.opacity = '0';
|
|
1721
|
+
notification.style.transition = 'opacity 0.3s ease';
|
|
1722
|
+
setTimeout(() => notification.remove(), 300);
|
|
1723
|
+
}, 3000);
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
_closeSurvey() {
|
|
1727
|
+
if (this._escapeHandler) {
|
|
1728
|
+
document.removeEventListener('keydown', this._escapeHandler);
|
|
1729
|
+
this._escapeHandler = null;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
// Capture references to avoid race conditions with setTimeout
|
|
1733
|
+
const surveyEl = this.surveyElement;
|
|
1734
|
+
const backdropEl = this.backdropElement;
|
|
1735
|
+
|
|
1736
|
+
if (surveyEl) {
|
|
1737
|
+
surveyEl.style.opacity = '0';
|
|
1738
|
+
surveyEl.style.transform = this.surveyOptions.position === 'center'
|
|
1739
|
+
? 'translate(-50%, -50%) scale(0.95)'
|
|
1740
|
+
: 'translateY(20px)';
|
|
1741
|
+
setTimeout(() => {
|
|
1742
|
+
if (surveyEl && surveyEl.parentNode) {
|
|
1743
|
+
surveyEl.parentNode.removeChild(surveyEl);
|
|
1744
|
+
}
|
|
1745
|
+
}, 300);
|
|
1746
|
+
this.surveyElement = null;
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
if (backdropEl) {
|
|
1750
|
+
backdropEl.style.opacity = '0';
|
|
1751
|
+
setTimeout(() => {
|
|
1752
|
+
if (backdropEl && backdropEl.parentNode) {
|
|
1753
|
+
backdropEl.parentNode.removeChild(backdropEl);
|
|
1754
|
+
}
|
|
1755
|
+
}, 300);
|
|
1756
|
+
this.backdropElement = null;
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
this.surveyState = {
|
|
1760
|
+
score: null,
|
|
1761
|
+
feedback: '',
|
|
1762
|
+
customAnswers: {},
|
|
1763
|
+
isVisible: false,
|
|
1764
|
+
};
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
destroy() {
|
|
1768
|
+
this._closeSurvey();
|
|
1769
|
+
super.destroy();
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1161
1773
|
class TabWidget extends BaseWidget {
|
|
1162
1774
|
constructor(options) {
|
|
1163
1775
|
super({ ...options, type: 'tab' });
|
|
@@ -1227,6 +1839,7 @@
|
|
|
1227
1839
|
['button', ButtonWidget],
|
|
1228
1840
|
['tab', TabWidget],
|
|
1229
1841
|
['inline', InlineWidget],
|
|
1842
|
+
['survey', SurveyWidget],
|
|
1230
1843
|
]);
|
|
1231
1844
|
|
|
1232
1845
|
static register(type, WidgetClass) {
|
|
@@ -1293,6 +1906,8 @@
|
|
|
1293
1906
|
apiUrl: this.config.apiUrl,
|
|
1294
1907
|
workspace: this.config.workspace,
|
|
1295
1908
|
userContext: this.config.userContext,
|
|
1909
|
+
mock: this.config.mock,
|
|
1910
|
+
env: this.config.env,
|
|
1296
1911
|
});
|
|
1297
1912
|
|
|
1298
1913
|
this._bindMethods();
|
|
@@ -1306,8 +1921,9 @@
|
|
|
1306
1921
|
try {
|
|
1307
1922
|
const initData = await this.apiService.init(this.config.userContext);
|
|
1308
1923
|
|
|
1924
|
+
// Merge backend config as base, local config overrides
|
|
1309
1925
|
if (initData.config) {
|
|
1310
|
-
this.config = deepMerge(
|
|
1926
|
+
this.config = deepMerge(initData.config, this.config);
|
|
1311
1927
|
}
|
|
1312
1928
|
|
|
1313
1929
|
this.initialized = true;
|
|
@@ -1356,6 +1972,44 @@
|
|
|
1356
1972
|
return this.widgets.get(id);
|
|
1357
1973
|
}
|
|
1358
1974
|
|
|
1975
|
+
/**
|
|
1976
|
+
* Show a survey widget
|
|
1977
|
+
* @param {Object} options - Survey options
|
|
1978
|
+
* @param {string} options.surveyType - Type of survey: 'nps', 'csat', 'ces', 'custom'
|
|
1979
|
+
* @param {string} options.position - Position: 'bottom-right', 'bottom-left', 'center', 'bottom'
|
|
1980
|
+
* @param {string} options.theme - Theme: 'light', 'dark'
|
|
1981
|
+
* @param {string} options.title - Custom title
|
|
1982
|
+
* @param {string} options.description - Custom description
|
|
1983
|
+
* @param {string} options.lowLabel - Low end label
|
|
1984
|
+
* @param {string} options.highLabel - High end label
|
|
1985
|
+
* @param {Function} options.onSubmit - Callback when survey is submitted
|
|
1986
|
+
* @param {Function} options.onDismiss - Callback when survey is dismissed
|
|
1987
|
+
* @returns {SurveyWidget} The survey widget instance
|
|
1988
|
+
*/
|
|
1989
|
+
showSurvey(options = {}) {
|
|
1990
|
+
if (!this.initialized) {
|
|
1991
|
+
throw new SDKError('SDK must be initialized before showing surveys. Call init() first.');
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
const surveyWidget = this.createWidget('survey', {
|
|
1995
|
+
surveyType: options.surveyType || options.type || 'nps',
|
|
1996
|
+
position: options.position || 'bottom-right',
|
|
1997
|
+
theme: options.theme || this.config.theme || 'light',
|
|
1998
|
+
title: options.title,
|
|
1999
|
+
description: options.description,
|
|
2000
|
+
lowLabel: options.lowLabel,
|
|
2001
|
+
highLabel: options.highLabel,
|
|
2002
|
+
customQuestions: options.customQuestions,
|
|
2003
|
+
onSubmit: options.onSubmit,
|
|
2004
|
+
onDismiss: options.onDismiss,
|
|
2005
|
+
});
|
|
2006
|
+
|
|
2007
|
+
surveyWidget.mount();
|
|
2008
|
+
surveyWidget.show();
|
|
2009
|
+
|
|
2010
|
+
return surveyWidget;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
1359
2013
|
getAllWidgets() {
|
|
1360
2014
|
return Array.from(this.widgets.values());
|
|
1361
2015
|
}
|
|
@@ -1454,6 +2108,8 @@
|
|
|
1454
2108
|
boardId: 'general',
|
|
1455
2109
|
autoShow: true,
|
|
1456
2110
|
debug: false,
|
|
2111
|
+
mock: false,
|
|
2112
|
+
env: 'production', // 'production' or 'staging'
|
|
1457
2113
|
};
|
|
1458
2114
|
|
|
1459
2115
|
const mergedConfig = deepMerge(deepMerge(defaultConfig, existingConfig), newConfig);
|
|
@@ -1566,23 +2222,45 @@
|
|
|
1566
2222
|
left: 20px;
|
|
1567
2223
|
}
|
|
1568
2224
|
|
|
1569
|
-
|
|
2225
|
+
.feedback-widget-button.position-bottom-center {
|
|
2226
|
+
bottom: 20px;
|
|
2227
|
+
left: 50%;
|
|
2228
|
+
transform: translateX(-50%);
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
.feedback-widget-button.position-top-center {
|
|
2232
|
+
top: 20px;
|
|
2233
|
+
left: 50%;
|
|
2234
|
+
transform: translateX(-50%);
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
.feedback-widget-button.position-center {
|
|
2238
|
+
top: 50%;
|
|
2239
|
+
left: 50%;
|
|
2240
|
+
transform: translate(-50%, -50%);
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
/* Circular button design with white bg and blue border */
|
|
1570
2244
|
.feedback-trigger-btn {
|
|
1571
2245
|
width: 56px;
|
|
1572
2246
|
height: 56px;
|
|
1573
|
-
border-radius: 50%;
|
|
1574
|
-
border:
|
|
2247
|
+
border-radius: 50%;
|
|
2248
|
+
border: 2px solid #155eff;
|
|
2249
|
+
background-color: #ffffff;
|
|
1575
2250
|
cursor: pointer;
|
|
1576
2251
|
display: flex;
|
|
1577
2252
|
align-items: center;
|
|
1578
2253
|
justify-content: center;
|
|
1579
|
-
box-shadow: 0 4px 12px rgba(
|
|
2254
|
+
box-shadow: 0 4px 12px rgba(21, 94, 255, 0.15);
|
|
1580
2255
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
1581
2256
|
padding: 0;
|
|
2257
|
+
color: #155eff; /* Icon color matches border */
|
|
1582
2258
|
}
|
|
1583
2259
|
|
|
1584
2260
|
.feedback-trigger-btn:hover {
|
|
1585
|
-
|
|
2261
|
+
background-color: #155eff;
|
|
2262
|
+
color: #ffffff;
|
|
2263
|
+
box-shadow: 0 6px 20px rgba(21, 94, 255, 0.3);
|
|
1586
2264
|
}
|
|
1587
2265
|
|
|
1588
2266
|
.feedback-trigger-btn:active {
|
|
@@ -1593,6 +2271,111 @@
|
|
|
1593
2271
|
flex-shrink: 0;
|
|
1594
2272
|
}
|
|
1595
2273
|
|
|
2274
|
+
/* Dark theme support */
|
|
2275
|
+
.theme-dark .feedback-trigger-btn {
|
|
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;
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
/* Loading Modal */
|
|
2287
|
+
.feedback-loading-modal {
|
|
2288
|
+
position: fixed;
|
|
2289
|
+
top: 50%;
|
|
2290
|
+
left: 50%;
|
|
2291
|
+
transform: translate(-50%, -50%) scale(0.9);
|
|
2292
|
+
z-index: 1000001;
|
|
2293
|
+
opacity: 0;
|
|
2294
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
.feedback-loading-modal.show {
|
|
2298
|
+
opacity: 1;
|
|
2299
|
+
transform: translate(-50%, -50%) scale(1);
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
.feedback-loading-spinner {
|
|
2303
|
+
width: 48px;
|
|
2304
|
+
height: 48px;
|
|
2305
|
+
border: 4px solid rgba(255, 255, 255, 0.3);
|
|
2306
|
+
border-top-color: #155EEF;
|
|
2307
|
+
border-radius: 50%;
|
|
2308
|
+
animation: spin 0.8s linear infinite;
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
.theme-dark .feedback-loading-spinner {
|
|
2312
|
+
border-color: rgba(255, 255, 255, 0.2);
|
|
2313
|
+
border-top-color: #155EEF;
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
@keyframes spin {
|
|
2317
|
+
to { transform: rotate(360deg); }
|
|
2318
|
+
}
|
|
2319
|
+
|
|
2320
|
+
/* Modal Styles (centered) */
|
|
2321
|
+
.feedback-modal {
|
|
2322
|
+
position: fixed;
|
|
2323
|
+
top: 50%;
|
|
2324
|
+
left: 50%;
|
|
2325
|
+
transform: translate(-50%, -50%) scale(0.9);
|
|
2326
|
+
width: 480px;
|
|
2327
|
+
max-width: 90vw;
|
|
2328
|
+
max-height: 85vh;
|
|
2329
|
+
z-index: 1000000;
|
|
2330
|
+
opacity: 0;
|
|
2331
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
2332
|
+
font-family: inherit;
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
.feedback-modal.open {
|
|
2336
|
+
opacity: 1;
|
|
2337
|
+
transform: translate(-50%, -50%) scale(1);
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
.feedback-modal .feedback-panel-content {
|
|
2341
|
+
max-height: 85vh;
|
|
2342
|
+
overflow-y: auto;
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
/* Size variants */
|
|
2346
|
+
.feedback-modal.size-small {
|
|
2347
|
+
width: 360px;
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2350
|
+
.feedback-modal.size-medium {
|
|
2351
|
+
width: 480px;
|
|
2352
|
+
}
|
|
2353
|
+
|
|
2354
|
+
.feedback-modal.size-large {
|
|
2355
|
+
width: 600px;
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
.feedback-panel.size-small {
|
|
2359
|
+
width: 320px;
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
.feedback-panel.size-medium {
|
|
2363
|
+
width: 420px;
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
.feedback-panel.size-large {
|
|
2367
|
+
width: 520px;
|
|
2368
|
+
}
|
|
2369
|
+
|
|
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
|
+
|
|
1596
2379
|
/* Side Panel Styles */
|
|
1597
2380
|
.feedback-panel {
|
|
1598
2381
|
position: fixed;
|
|
@@ -1616,7 +2399,7 @@
|
|
|
1616
2399
|
left: 0;
|
|
1617
2400
|
right: 0;
|
|
1618
2401
|
bottom: 0;
|
|
1619
|
-
background: rgba(0, 0, 0, 0.
|
|
2402
|
+
background: rgba(0, 0, 0, 0.5);
|
|
1620
2403
|
opacity: 0;
|
|
1621
2404
|
transition: opacity 0.3s ease;
|
|
1622
2405
|
pointer-events: none;
|
|
@@ -1629,43 +2412,31 @@
|
|
|
1629
2412
|
}
|
|
1630
2413
|
|
|
1631
2414
|
.feedback-panel-content {
|
|
1632
|
-
background:
|
|
2415
|
+
background: var(--bg-color, #ffffff);
|
|
2416
|
+
color: var(--text-color, #1F2937);
|
|
1633
2417
|
height: 100%;
|
|
1634
2418
|
display: flex;
|
|
1635
2419
|
flex-direction: column;
|
|
1636
2420
|
border-radius: 16px;
|
|
1637
|
-
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),
|
|
2421
|
+
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),
|
|
1638
2422
|
0 10px 10px -5px rgba(0, 0, 0, 0.04),
|
|
1639
2423
|
0 0 0 1px rgba(0, 0, 0, 0.05);
|
|
1640
2424
|
}
|
|
1641
2425
|
|
|
1642
|
-
.feedback-panel.theme-dark .feedback-panel-content {
|
|
1643
|
-
background: #1F2937;
|
|
1644
|
-
color: white;
|
|
1645
|
-
}
|
|
1646
|
-
|
|
1647
2426
|
.feedback-panel-header {
|
|
1648
2427
|
display: flex;
|
|
1649
2428
|
align-items: center;
|
|
1650
2429
|
justify-content: space-between;
|
|
1651
|
-
padding:
|
|
1652
|
-
border-bottom: 1px solid
|
|
2430
|
+
padding: 16px 20px;
|
|
2431
|
+
border-bottom: 1px solid rgba(128, 128, 128, 0.2);
|
|
1653
2432
|
flex-shrink: 0;
|
|
1654
2433
|
}
|
|
1655
2434
|
|
|
1656
|
-
.feedback-panel.theme-dark .feedback-panel-header {
|
|
1657
|
-
border-bottom-color: #374151;
|
|
1658
|
-
}
|
|
1659
|
-
|
|
1660
2435
|
.feedback-panel-header h3 {
|
|
1661
2436
|
margin: 0;
|
|
1662
2437
|
font-size: 18px;
|
|
1663
2438
|
font-weight: 600;
|
|
1664
|
-
color: #111827;
|
|
1665
|
-
}
|
|
1666
|
-
|
|
1667
|
-
.feedback-panel.theme-dark .feedback-panel-header h3 {
|
|
1668
|
-
color: white;
|
|
2439
|
+
color: var(--text-color, #111827);
|
|
1669
2440
|
}
|
|
1670
2441
|
|
|
1671
2442
|
.feedback-panel-close {
|
|
@@ -1673,7 +2444,8 @@
|
|
|
1673
2444
|
border: none;
|
|
1674
2445
|
font-size: 24px;
|
|
1675
2446
|
cursor: pointer;
|
|
1676
|
-
color: #6B7280;
|
|
2447
|
+
color: var(--text-color, #6B7280);
|
|
2448
|
+
opacity: 0.6;
|
|
1677
2449
|
padding: 4px;
|
|
1678
2450
|
width: 32px;
|
|
1679
2451
|
height: 32px;
|
|
@@ -1685,28 +2457,19 @@
|
|
|
1685
2457
|
}
|
|
1686
2458
|
|
|
1687
2459
|
.feedback-panel-close:hover {
|
|
1688
|
-
|
|
1689
|
-
|
|
2460
|
+
opacity: 1;
|
|
2461
|
+
background: rgba(128, 128, 128, 0.1);
|
|
1690
2462
|
}
|
|
1691
2463
|
|
|
1692
2464
|
.feedback-panel-close:focus-visible {
|
|
1693
|
-
outline: 2px solid #155EEF;
|
|
2465
|
+
outline: 2px solid var(--primary-color, #155EEF);
|
|
1694
2466
|
outline-offset: 2px;
|
|
1695
2467
|
}
|
|
1696
2468
|
|
|
1697
|
-
.feedback-panel.theme-dark .feedback-panel-close {
|
|
1698
|
-
color: #9CA3AF;
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1701
|
-
.feedback-panel.theme-dark .feedback-panel-close:hover {
|
|
1702
|
-
background: #374151;
|
|
1703
|
-
color: white;
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1706
2469
|
.feedback-panel-body {
|
|
1707
2470
|
flex: 1;
|
|
1708
2471
|
overflow-y: auto;
|
|
1709
|
-
padding:
|
|
2472
|
+
padding: 16px 20px;
|
|
1710
2473
|
}
|
|
1711
2474
|
|
|
1712
2475
|
.feedback-form {
|
|
@@ -1730,23 +2493,21 @@
|
|
|
1730
2493
|
font-size: 14px;
|
|
1731
2494
|
font-weight: 500;
|
|
1732
2495
|
line-height: 1.25;
|
|
1733
|
-
color: #374151;
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
.feedback-panel.theme-dark .feedback-form-group label {
|
|
1737
|
-
color: #D1D5DB;
|
|
2496
|
+
color: var(--text-color, #374151);
|
|
2497
|
+
opacity: 0.8;
|
|
1738
2498
|
}
|
|
1739
2499
|
|
|
1740
2500
|
.feedback-form-group input {
|
|
1741
2501
|
height: 44px;
|
|
1742
2502
|
width: 100%;
|
|
1743
2503
|
border-radius: 8px;
|
|
1744
|
-
border: 1px solid
|
|
2504
|
+
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
2505
|
+
background: rgba(128, 128, 128, 0.05);
|
|
1745
2506
|
padding: 10px 14px;
|
|
1746
2507
|
font-size: 15px;
|
|
1747
2508
|
font-weight: 400;
|
|
1748
2509
|
line-height: 1.5;
|
|
1749
|
-
color: #1F2937;
|
|
2510
|
+
color: var(--text-color, #1F2937);
|
|
1750
2511
|
font-family: inherit;
|
|
1751
2512
|
outline: none;
|
|
1752
2513
|
transition: all 0.2s ease;
|
|
@@ -1754,11 +2515,12 @@
|
|
|
1754
2515
|
|
|
1755
2516
|
.feedback-form-group input::placeholder {
|
|
1756
2517
|
font-size: 15px;
|
|
1757
|
-
color: #9CA3AF;
|
|
2518
|
+
color: var(--text-color, #9CA3AF);
|
|
2519
|
+
opacity: 0.5;
|
|
1758
2520
|
}
|
|
1759
2521
|
|
|
1760
2522
|
.feedback-form-group input:focus {
|
|
1761
|
-
border-color: #155EEF;
|
|
2523
|
+
border-color: var(--primary-color, #155EEF);
|
|
1762
2524
|
box-shadow: 0 0 0 3px rgba(21, 94, 239, 0.1);
|
|
1763
2525
|
}
|
|
1764
2526
|
|
|
@@ -1771,12 +2533,13 @@
|
|
|
1771
2533
|
width: 100%;
|
|
1772
2534
|
resize: vertical;
|
|
1773
2535
|
border-radius: 8px;
|
|
1774
|
-
border: 1px solid
|
|
2536
|
+
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
2537
|
+
background: rgba(128, 128, 128, 0.05);
|
|
1775
2538
|
padding: 10px 14px;
|
|
1776
2539
|
font-size: 15px;
|
|
1777
2540
|
font-weight: 400;
|
|
1778
2541
|
line-height: 1.5;
|
|
1779
|
-
color: #1F2937;
|
|
2542
|
+
color: var(--text-color, #1F2937);
|
|
1780
2543
|
font-family: inherit;
|
|
1781
2544
|
outline: none;
|
|
1782
2545
|
transition: all 0.2s ease;
|
|
@@ -1784,11 +2547,12 @@
|
|
|
1784
2547
|
|
|
1785
2548
|
.feedback-form-group textarea::placeholder {
|
|
1786
2549
|
font-size: 15px;
|
|
1787
|
-
color: #9CA3AF;
|
|
2550
|
+
color: var(--text-color, #9CA3AF);
|
|
2551
|
+
opacity: 0.5;
|
|
1788
2552
|
}
|
|
1789
2553
|
|
|
1790
2554
|
.feedback-form-group textarea:focus {
|
|
1791
|
-
border-color: #155EEF;
|
|
2555
|
+
border-color: var(--primary-color, #155EEF);
|
|
1792
2556
|
box-shadow: 0 0 0 3px rgba(21, 94, 239, 0.1);
|
|
1793
2557
|
}
|
|
1794
2558
|
|
|
@@ -1796,18 +2560,6 @@
|
|
|
1796
2560
|
outline: none;
|
|
1797
2561
|
}
|
|
1798
2562
|
|
|
1799
|
-
.feedback-panel.theme-dark .feedback-form-group input,
|
|
1800
|
-
.feedback-panel.theme-dark .feedback-form-group textarea {
|
|
1801
|
-
background: #374151;
|
|
1802
|
-
border-color: #4B5563;
|
|
1803
|
-
color: white;
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
.feedback-panel.theme-dark .feedback-form-group input::placeholder,
|
|
1807
|
-
.feedback-panel.theme-dark .feedback-form-group textarea::placeholder {
|
|
1808
|
-
color: #6B7280;
|
|
1809
|
-
}
|
|
1810
|
-
|
|
1811
2563
|
.feedback-btn {
|
|
1812
2564
|
position: relative;
|
|
1813
2565
|
display: inline-flex;
|
|
@@ -1836,38 +2588,29 @@
|
|
|
1836
2588
|
}
|
|
1837
2589
|
|
|
1838
2590
|
.feedback-btn-submit {
|
|
1839
|
-
background: #155EEF;
|
|
2591
|
+
background: var(--primary-color, #155EEF);
|
|
1840
2592
|
color: white;
|
|
1841
2593
|
width: 100%;
|
|
1842
2594
|
}
|
|
1843
2595
|
|
|
1844
2596
|
.feedback-btn-submit:hover:not(:disabled) {
|
|
1845
|
-
background: #
|
|
2597
|
+
background: var(--primary-color, #155EEF);
|
|
2598
|
+
filter: brightness(0.9);
|
|
1846
2599
|
}
|
|
1847
2600
|
|
|
1848
2601
|
.feedback-btn-submit:active:not(:disabled) {
|
|
1849
|
-
background: #
|
|
2602
|
+
background: var(--primary-color, #155EEF);
|
|
2603
|
+
filter: brightness(0.8);
|
|
1850
2604
|
}
|
|
1851
2605
|
|
|
1852
2606
|
.feedback-btn-cancel {
|
|
1853
2607
|
background: transparent;
|
|
1854
|
-
color: #6B7280;
|
|
1855
|
-
border: 1px solid
|
|
2608
|
+
color: var(--text-color, #6B7280);
|
|
2609
|
+
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
1856
2610
|
}
|
|
1857
2611
|
|
|
1858
2612
|
.feedback-btn-cancel:hover:not(:disabled) {
|
|
1859
|
-
background:
|
|
1860
|
-
border-color: #9CA3AF;
|
|
1861
|
-
color: #374151;
|
|
1862
|
-
}
|
|
1863
|
-
|
|
1864
|
-
.feedback-panel.theme-dark .feedback-btn-cancel {
|
|
1865
|
-
color: #D1D5DB;
|
|
1866
|
-
border-color: #4B5563;
|
|
1867
|
-
}
|
|
1868
|
-
|
|
1869
|
-
.feedback-panel.theme-dark .feedback-btn-cancel:hover:not(:disabled) {
|
|
1870
|
-
background: #374151;
|
|
2613
|
+
background: rgba(128, 128, 128, 0.1);
|
|
1871
2614
|
}
|
|
1872
2615
|
|
|
1873
2616
|
.feedback-form-actions {
|
|
@@ -2074,6 +2817,70 @@
|
|
|
2074
2817
|
display: none !important;
|
|
2075
2818
|
}
|
|
2076
2819
|
}
|
|
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
|
+
}
|
|
2077
2884
|
`;
|
|
2078
2885
|
|
|
2079
2886
|
function injectStyles() {
|
|
@@ -2151,6 +2958,7 @@
|
|
|
2151
2958
|
ButtonWidget,
|
|
2152
2959
|
TabWidget,
|
|
2153
2960
|
InlineWidget,
|
|
2961
|
+
SurveyWidget,
|
|
2154
2962
|
WidgetFactory,
|
|
2155
2963
|
EventBus,
|
|
2156
2964
|
APIService,
|
|
@@ -2234,6 +3042,7 @@
|
|
|
2234
3042
|
exports.FeedbackSDK = FeedbackSDK;
|
|
2235
3043
|
exports.InlineWidget = InlineWidget;
|
|
2236
3044
|
exports.SDKError = SDKError;
|
|
3045
|
+
exports.SurveyWidget = SurveyWidget;
|
|
2237
3046
|
exports.TabWidget = TabWidget;
|
|
2238
3047
|
exports.ValidationError = ValidationError;
|
|
2239
3048
|
exports.WidgetError = WidgetError;
|