@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.
@@ -40,7 +40,10 @@ export class SurveyWidget extends BaseWidget {
40
40
  show() {
41
41
  this._renderSurvey();
42
42
  this.surveyState.isVisible = true;
43
- this.sdk.eventBus.emit('survey:shown', { widget: this, type: this.surveyOptions.surveyType });
43
+ this.sdk.eventBus.emit('survey:shown', {
44
+ widget: this,
45
+ type: this.surveyOptions.surveyType,
46
+ });
44
47
  return this;
45
48
  }
46
49
 
@@ -55,16 +58,19 @@ export class SurveyWidget extends BaseWidget {
55
58
 
56
59
  const config = this._getSurveyConfig();
57
60
  const positionStyles = this._getPositionStyles();
58
- const themeStyles = this.surveyOptions.theme === 'dark'
59
- ? 'background: #1a1a1a; color: #fff;'
60
- : 'background: #fff; color: #1d1d1f;';
61
+ const themeStyles =
62
+ this.surveyOptions.theme === 'dark'
63
+ ? 'background: #1a1a1a; color: #fff;'
64
+ : 'background: #fff; color: #1d1d1f;';
61
65
 
62
66
  // Create backdrop for center position
63
67
  if (this.surveyOptions.position === 'center') {
64
68
  this.backdropElement = document.createElement('div');
65
69
  this.backdropElement.className = 'feedback-survey-backdrop';
66
70
  document.body.appendChild(this.backdropElement);
67
- this.backdropElement.addEventListener('click', () => this._handleDismiss());
71
+ this.backdropElement.addEventListener('click', () =>
72
+ this._handleDismiss()
73
+ );
68
74
  }
69
75
 
70
76
  this.surveyElement = document.createElement('div');
@@ -88,67 +94,92 @@ export class SurveyWidget extends BaseWidget {
88
94
  // Animate in
89
95
  requestAnimationFrame(() => {
90
96
  this.surveyElement.style.opacity = '1';
91
- this.surveyElement.style.transform = this.surveyOptions.position === 'center'
92
- ? 'translate(-50%, -50%) scale(1)'
93
- : 'translateY(0)';
97
+ this.surveyElement.style.transform =
98
+ this.surveyOptions.position === 'center'
99
+ ? 'translate(-50%, -50%) scale(1)'
100
+ : 'translateY(0)';
94
101
  });
95
102
  }
96
103
 
97
104
  _getSurveyConfig() {
98
105
  const configs = {
99
106
  nps: {
100
- title: this.surveyOptions.title || 'How likely are you to recommend us?',
101
- description: this.surveyOptions.description || 'On a scale of 0-10, how likely are you to recommend our product to a friend or colleague?',
107
+ title:
108
+ this.surveyOptions.title || 'How likely are you to recommend us?',
109
+ description:
110
+ this.surveyOptions.description ||
111
+ 'On a scale of 0-10, how likely are you to recommend our product to a friend or colleague?',
102
112
  html: `
103
113
  <div class="feedback-survey-nps" style="display: flex; justify-content: space-between; gap: 4px;">
104
- ${[...Array(11).keys()].map(n => `
114
+ ${[...Array(11).keys()]
115
+ .map(
116
+ (n) => `
105
117
  <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>
106
- `).join('')}
118
+ `
119
+ )
120
+ .join('')}
107
121
  </div>
108
122
  <div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'};">
109
123
  <span>${this.surveyOptions.lowLabel || 'Not likely'}</span>
110
124
  <span>${this.surveyOptions.highLabel || 'Very likely'}</span>
111
125
  </div>
112
- `
126
+ `,
113
127
  },
114
128
  csat: {
115
129
  title: this.surveyOptions.title || 'How satisfied are you?',
116
- description: this.surveyOptions.description || 'How would you rate your overall satisfaction with our product?',
130
+ description:
131
+ this.surveyOptions.description ||
132
+ 'How would you rate your overall satisfaction with our product?',
117
133
  html: `
118
134
  <div class="feedback-survey-csat" style="display: flex; justify-content: center; gap: 16px;">
119
- ${['😞', '😕', '😐', '🙂', '😄'].map((emoji, i) => `
135
+ ${['😞', '😕', '😐', '🙂', '😄']
136
+ .map(
137
+ (emoji, i) => `
120
138
  <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>
121
- `).join('')}
139
+ `
140
+ )
141
+ .join('')}
122
142
  </div>
123
143
  <div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'};">
124
144
  <span>${this.surveyOptions.lowLabel || 'Very dissatisfied'}</span>
125
145
  <span>${this.surveyOptions.highLabel || 'Very satisfied'}</span>
126
146
  </div>
127
- `
147
+ `,
128
148
  },
129
149
  ces: {
130
150
  title: this.surveyOptions.title || 'How easy was it?',
131
- description: this.surveyOptions.description || 'How easy was it to accomplish your task today?',
151
+ description:
152
+ this.surveyOptions.description ||
153
+ 'How easy was it to accomplish your task today?',
132
154
  html: `
133
155
  <div class="feedback-survey-ces" style="display: flex; justify-content: space-between; gap: 8px;">
134
- ${['Very Difficult', 'Difficult', 'Neutral', 'Easy', 'Very Easy'].map((label, i) => `
156
+ ${['Very Difficult', 'Difficult', 'Neutral', 'Easy', 'Very Easy']
157
+ .map(
158
+ (label, i) => `
135
159
  <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>
136
- `).join('')}
160
+ `
161
+ )
162
+ .join('')}
137
163
  </div>
138
- `
164
+ `,
139
165
  },
140
166
  custom: {
141
167
  title: this.surveyOptions.title || 'Quick Feedback',
142
- description: this.surveyOptions.description || 'Help us improve by answering a few questions.',
143
- html: this._renderCustomQuestions()
144
- }
168
+ description:
169
+ this.surveyOptions.description ||
170
+ 'Help us improve by answering a few questions.',
171
+ html: this._renderCustomQuestions(),
172
+ },
145
173
  };
146
174
 
147
175
  return configs[this.surveyOptions.surveyType] || configs.nps;
148
176
  }
149
177
 
150
178
  _renderCustomQuestions() {
151
- if (!this.surveyOptions.customQuestions || this.surveyOptions.customQuestions.length === 0) {
179
+ if (
180
+ !this.surveyOptions.customQuestions ||
181
+ this.surveyOptions.customQuestions.length === 0
182
+ ) {
152
183
  // Default custom questions
153
184
  return `
154
185
  <div style="margin-bottom: 16px;">
@@ -164,20 +195,28 @@ export class SurveyWidget extends BaseWidget {
164
195
  <div>
165
196
  <label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">How often do you use it?</label>
166
197
  <div class="feedback-survey-frequency" style="display: flex; gap: 8px;">
167
- ${['Daily', 'Weekly', 'Monthly', 'Rarely'].map(freq => `
198
+ ${['Daily', 'Weekly', 'Monthly', 'Rarely']
199
+ .map(
200
+ (freq) => `
168
201
  <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>
169
- `).join('')}
202
+ `
203
+ )
204
+ .join('')}
170
205
  </div>
171
206
  </div>
172
207
  `;
173
208
  }
174
209
 
175
- return this.surveyOptions.customQuestions.map((q, index) => `
210
+ return this.surveyOptions.customQuestions
211
+ .map(
212
+ (q, index) => `
176
213
  <div style="margin-bottom: 16px;">
177
214
  <label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">${q.label}</label>
178
215
  ${this._renderQuestionInput(q, index)}
179
216
  </div>
180
- `).join('');
217
+ `
218
+ )
219
+ .join('');
181
220
  }
182
221
 
183
222
  _renderQuestionInput(question, index) {
@@ -186,7 +225,7 @@ export class SurveyWidget extends BaseWidget {
186
225
  return `
187
226
  <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'};">
188
227
  <option value="">${question.placeholder || 'Select an option'}</option>
189
- ${question.options.map(opt => `<option value="${opt.value}">${opt.label}</option>`).join('')}
228
+ ${question.options.map((opt) => `<option value="${opt.value}">${opt.label}</option>`).join('')}
190
229
  </select>
191
230
  `;
192
231
  case 'text':
@@ -200,10 +239,14 @@ export class SurveyWidget extends BaseWidget {
200
239
 
201
240
  _getPositionStyles() {
202
241
  const positions = {
203
- 'bottom-right': 'bottom: 24px; right: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',
204
- 'bottom-left': 'bottom: 24px; left: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',
205
- 'center': 'top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.95); opacity: 0; transition: all 0.3s ease;',
206
- '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;'
242
+ 'bottom-right':
243
+ 'bottom: 24px; right: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',
244
+ 'bottom-left':
245
+ 'bottom: 24px; left: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',
246
+ center:
247
+ 'top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.95); opacity: 0; transition: all 0.3s ease;',
248
+ bottom:
249
+ '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;',
207
250
  };
208
251
  return positions[this.surveyOptions.position] || positions['bottom-right'];
209
252
  }
@@ -216,11 +259,15 @@ export class SurveyWidget extends BaseWidget {
216
259
  closeBtn.addEventListener('click', () => this._handleDismiss());
217
260
 
218
261
  // Submit button
219
- const submitBtn = this.surveyElement.querySelector('.feedback-survey-submit');
262
+ const submitBtn = this.surveyElement.querySelector(
263
+ '.feedback-survey-submit'
264
+ );
220
265
  submitBtn.addEventListener('click', () => this._handleSubmit());
221
266
 
222
267
  // Feedback textarea
223
- const textarea = this.surveyElement.querySelector('.feedback-survey-textarea');
268
+ const textarea = this.surveyElement.querySelector(
269
+ '.feedback-survey-textarea'
270
+ );
224
271
  textarea.addEventListener('input', (e) => {
225
272
  this.surveyState.feedback = e.target.value;
226
273
  });
@@ -241,133 +288,177 @@ export class SurveyWidget extends BaseWidget {
241
288
  const type = this.surveyOptions.surveyType;
242
289
 
243
290
  if (type === 'nps') {
244
- this.surveyElement.querySelectorAll('.feedback-survey-nps-btn').forEach(btn => {
245
- btn.addEventListener('click', () => this._selectNPS(parseInt(btn.dataset.score)));
246
- btn.addEventListener('mouseenter', () => {
247
- if (this.surveyState.score !== parseInt(btn.dataset.score)) {
248
- btn.style.borderColor = '#007aff';
249
- }
250
- });
251
- btn.addEventListener('mouseleave', () => {
252
- if (this.surveyState.score !== parseInt(btn.dataset.score)) {
253
- btn.style.borderColor = this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
254
- }
291
+ this.surveyElement
292
+ .querySelectorAll('.feedback-survey-nps-btn')
293
+ .forEach((btn) => {
294
+ btn.addEventListener('click', () =>
295
+ this._selectNPS(parseInt(btn.dataset.score))
296
+ );
297
+ btn.addEventListener('mouseenter', () => {
298
+ if (this.surveyState.score !== parseInt(btn.dataset.score)) {
299
+ btn.style.borderColor = '#007aff';
300
+ }
301
+ });
302
+ btn.addEventListener('mouseleave', () => {
303
+ if (this.surveyState.score !== parseInt(btn.dataset.score)) {
304
+ btn.style.borderColor =
305
+ this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
306
+ }
307
+ });
255
308
  });
256
- });
257
309
  }
258
310
 
259
311
  if (type === 'csat') {
260
- this.surveyElement.querySelectorAll('.feedback-survey-csat-btn').forEach(btn => {
261
- btn.addEventListener('click', () => this._selectCSAT(parseInt(btn.dataset.score)));
262
- btn.addEventListener('mouseenter', () => {
263
- btn.style.transform = 'scale(1.1)';
264
- });
265
- btn.addEventListener('mouseleave', () => {
266
- if (this.surveyState.score !== parseInt(btn.dataset.score)) {
267
- btn.style.transform = 'scale(1)';
268
- }
312
+ this.surveyElement
313
+ .querySelectorAll('.feedback-survey-csat-btn')
314
+ .forEach((btn) => {
315
+ btn.addEventListener('click', () =>
316
+ this._selectCSAT(parseInt(btn.dataset.score))
317
+ );
318
+ btn.addEventListener('mouseenter', () => {
319
+ btn.style.transform = 'scale(1.1)';
320
+ });
321
+ btn.addEventListener('mouseleave', () => {
322
+ if (this.surveyState.score !== parseInt(btn.dataset.score)) {
323
+ btn.style.transform = 'scale(1)';
324
+ }
325
+ });
269
326
  });
270
- });
271
327
  }
272
328
 
273
329
  if (type === 'ces') {
274
- this.surveyElement.querySelectorAll('.feedback-survey-ces-btn').forEach(btn => {
275
- btn.addEventListener('click', () => this._selectCES(parseInt(btn.dataset.score)));
276
- btn.addEventListener('mouseenter', () => {
277
- if (this.surveyState.score !== parseInt(btn.dataset.score)) {
278
- btn.style.borderColor = '#007aff';
279
- }
330
+ this.surveyElement
331
+ .querySelectorAll('.feedback-survey-ces-btn')
332
+ .forEach((btn) => {
333
+ btn.addEventListener('click', () =>
334
+ this._selectCES(parseInt(btn.dataset.score))
335
+ );
336
+ btn.addEventListener('mouseenter', () => {
337
+ if (this.surveyState.score !== parseInt(btn.dataset.score)) {
338
+ btn.style.borderColor = '#007aff';
339
+ }
340
+ });
341
+ btn.addEventListener('mouseleave', () => {
342
+ if (this.surveyState.score !== parseInt(btn.dataset.score)) {
343
+ btn.style.borderColor =
344
+ this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
345
+ }
346
+ });
280
347
  });
281
- btn.addEventListener('mouseleave', () => {
282
- if (this.surveyState.score !== parseInt(btn.dataset.score)) {
283
- btn.style.borderColor = this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
284
- }
285
- });
286
- });
287
348
  }
288
349
 
289
350
  if (type === 'custom') {
290
351
  // Frequency buttons
291
- this.surveyElement.querySelectorAll('.feedback-survey-freq-btn').forEach(btn => {
292
- btn.addEventListener('click', () => this._selectFrequency(btn.dataset.freq));
293
- });
352
+ this.surveyElement
353
+ .querySelectorAll('.feedback-survey-freq-btn')
354
+ .forEach((btn) => {
355
+ btn.addEventListener('click', () =>
356
+ this._selectFrequency(btn.dataset.freq)
357
+ );
358
+ });
294
359
 
295
360
  // Select inputs
296
- this.surveyElement.querySelectorAll('.feedback-survey-select').forEach(select => {
297
- select.addEventListener('change', (e) => {
298
- this.surveyState.customAnswers[select.dataset.question] = e.target.value;
361
+ this.surveyElement
362
+ .querySelectorAll('.feedback-survey-select')
363
+ .forEach((select) => {
364
+ select.addEventListener('change', (e) => {
365
+ this.surveyState.customAnswers[select.dataset.question] =
366
+ e.target.value;
367
+ });
299
368
  });
300
- });
301
369
 
302
370
  // Text inputs
303
- this.surveyElement.querySelectorAll('.feedback-survey-input').forEach(input => {
304
- input.addEventListener('input', (e) => {
305
- this.surveyState.customAnswers[input.dataset.question] = e.target.value;
371
+ this.surveyElement
372
+ .querySelectorAll('.feedback-survey-input')
373
+ .forEach((input) => {
374
+ input.addEventListener('input', (e) => {
375
+ this.surveyState.customAnswers[input.dataset.question] =
376
+ e.target.value;
377
+ });
306
378
  });
307
- });
308
379
  }
309
380
  }
310
381
 
311
382
  _selectNPS(score) {
312
383
  this.surveyState.score = score;
313
- this.surveyElement.querySelectorAll('.feedback-survey-nps-btn').forEach(btn => {
314
- const btnScore = parseInt(btn.dataset.score);
315
- if (btnScore === score) {
316
- btn.style.background = '#007aff';
317
- btn.style.borderColor = '#007aff';
318
- btn.style.color = '#fff';
319
- } else {
320
- btn.style.background = this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
321
- btn.style.borderColor = this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
322
- btn.style.color = this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
323
- }
324
- });
384
+ this.surveyElement
385
+ .querySelectorAll('.feedback-survey-nps-btn')
386
+ .forEach((btn) => {
387
+ const btnScore = parseInt(btn.dataset.score);
388
+ if (btnScore === score) {
389
+ btn.style.background = '#007aff';
390
+ btn.style.borderColor = '#007aff';
391
+ btn.style.color = '#fff';
392
+ } else {
393
+ btn.style.background =
394
+ this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
395
+ btn.style.borderColor =
396
+ this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
397
+ btn.style.color =
398
+ this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
399
+ }
400
+ });
325
401
  }
326
402
 
327
403
  _selectCSAT(score) {
328
404
  this.surveyState.score = score;
329
- this.surveyElement.querySelectorAll('.feedback-survey-csat-btn').forEach(btn => {
330
- const btnScore = parseInt(btn.dataset.score);
331
- btn.style.transform = btnScore === score ? 'scale(1.2)' : 'scale(1)';
332
- });
405
+ this.surveyElement
406
+ .querySelectorAll('.feedback-survey-csat-btn')
407
+ .forEach((btn) => {
408
+ const btnScore = parseInt(btn.dataset.score);
409
+ btn.style.transform = btnScore === score ? 'scale(1.2)' : 'scale(1)';
410
+ });
333
411
  }
334
412
 
335
413
  _selectCES(score) {
336
414
  this.surveyState.score = score;
337
- this.surveyElement.querySelectorAll('.feedback-survey-ces-btn').forEach(btn => {
338
- const btnScore = parseInt(btn.dataset.score);
339
- if (btnScore === score) {
340
- btn.style.background = '#007aff';
341
- btn.style.borderColor = '#007aff';
342
- btn.style.color = '#fff';
343
- } else {
344
- btn.style.background = this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
345
- btn.style.borderColor = this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
346
- btn.style.color = this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
347
- }
348
- });
415
+ this.surveyElement
416
+ .querySelectorAll('.feedback-survey-ces-btn')
417
+ .forEach((btn) => {
418
+ const btnScore = parseInt(btn.dataset.score);
419
+ if (btnScore === score) {
420
+ btn.style.background = '#007aff';
421
+ btn.style.borderColor = '#007aff';
422
+ btn.style.color = '#fff';
423
+ } else {
424
+ btn.style.background =
425
+ this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
426
+ btn.style.borderColor =
427
+ this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
428
+ btn.style.color =
429
+ this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
430
+ }
431
+ });
349
432
  }
350
433
 
351
434
  _selectFrequency(freq) {
352
435
  this.surveyState.customAnswers.frequency = freq;
353
- this.surveyElement.querySelectorAll('.feedback-survey-freq-btn').forEach(btn => {
354
- if (btn.dataset.freq === freq) {
355
- btn.style.background = '#007aff';
356
- btn.style.borderColor = '#007aff';
357
- btn.style.color = '#fff';
358
- } else {
359
- btn.style.background = this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
360
- btn.style.borderColor = this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
361
- btn.style.color = this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
362
- }
363
- });
436
+ this.surveyElement
437
+ .querySelectorAll('.feedback-survey-freq-btn')
438
+ .forEach((btn) => {
439
+ if (btn.dataset.freq === freq) {
440
+ btn.style.background = '#007aff';
441
+ btn.style.borderColor = '#007aff';
442
+ btn.style.color = '#fff';
443
+ } else {
444
+ btn.style.background =
445
+ this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';
446
+ btn.style.borderColor =
447
+ this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';
448
+ btn.style.color =
449
+ this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';
450
+ }
451
+ });
364
452
  }
365
453
 
366
454
  async _handleSubmit() {
367
455
  const type = this.surveyOptions.surveyType;
368
456
 
369
457
  // Validate
370
- if ((type === 'nps' || type === 'csat' || type === 'ces') && this.surveyState.score === null) {
458
+ if (
459
+ (type === 'nps' || type === 'csat' || type === 'ces') &&
460
+ this.surveyState.score === null
461
+ ) {
371
462
  this._showError('Please select a rating');
372
463
  return;
373
464
  }
@@ -415,10 +506,13 @@ export class SurveyWidget extends BaseWidget {
415
506
 
416
507
  const error = document.createElement('div');
417
508
  error.className = 'feedback-survey-error';
418
- error.style.cssText = 'color: #ef4444; font-size: 13px; margin-top: 8px; text-align: center;';
509
+ error.style.cssText =
510
+ 'color: #ef4444; font-size: 13px; margin-top: 8px; text-align: center;';
419
511
  error.textContent = message;
420
512
 
421
- const submitBtn = this.surveyElement.querySelector('.feedback-survey-submit');
513
+ const submitBtn = this.surveyElement.querySelector(
514
+ '.feedback-survey-submit'
515
+ );
422
516
  submitBtn.parentNode.insertBefore(error, submitBtn);
423
517
 
424
518
  setTimeout(() => error.remove(), 3000);
@@ -468,9 +562,10 @@ export class SurveyWidget extends BaseWidget {
468
562
 
469
563
  if (surveyEl) {
470
564
  surveyEl.style.opacity = '0';
471
- surveyEl.style.transform = this.surveyOptions.position === 'center'
472
- ? 'translate(-50%, -50%) scale(0.95)'
473
- : 'translateY(20px)';
565
+ surveyEl.style.transform =
566
+ this.surveyOptions.position === 'center'
567
+ ? 'translate(-50%, -50%) scale(0.95)'
568
+ : 'translateY(20px)';
474
569
  setTimeout(() => {
475
570
  if (surveyEl && surveyEl.parentNode) {
476
571
  surveyEl.parentNode.removeChild(surveyEl);
package/types/index.d.ts CHANGED
@@ -1,68 +1,73 @@
1
-
2
1
  declare module '@product7/feedback-sdk' {
3
- export interface FeedbackConfig {
4
- workspace: string;
5
- userContext?: UserContext;
6
- debug?: boolean;
7
- boardId?: string;
8
- position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
9
- theme?: 'light' | 'dark';
10
- apiUrl?: string;
11
- autoShow?: boolean;
12
- }
2
+ export interface FeedbackConfig {
3
+ workspace: string;
4
+ userContext?: UserContext;
5
+ debug?: boolean;
6
+ boardId?: string;
7
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
8
+ theme?: 'light' | 'dark';
9
+ apiUrl?: string;
10
+ autoShow?: boolean;
11
+ }
13
12
 
14
- export interface UserContext {
15
- user_id?: string;
16
- email?: string;
17
- name?: string;
18
- custom_fields?: Record<string, any>;
19
- company?: {
20
- id?: string;
21
- name?: string;
22
- monthly_spend?: number;
23
- };
24
- }
13
+ export interface UserContext {
14
+ user_id?: string;
15
+ email?: string;
16
+ name?: string;
17
+ custom_fields?: Record<string, any>;
18
+ company?: {
19
+ id?: string;
20
+ name?: string;
21
+ monthly_spend?: number;
22
+ };
23
+ }
25
24
 
26
- export interface ButtonWidget {
27
- id: string;
28
- type: 'button';
29
- mount(container?: string | HTMLElement): this;
30
- destroy(): void;
31
- show(): this;
32
- hide(): this;
33
- openModal(): void;
34
- closeModal(): void;
35
- }
25
+ export interface ButtonWidget {
26
+ id: string;
27
+ type: 'button';
28
+ mount(container?: string | HTMLElement): this;
29
+ destroy(): void;
30
+ show(): this;
31
+ hide(): this;
32
+ openModal(): void;
33
+ closeModal(): void;
34
+ }
36
35
 
37
- export class FeedbackSDK {
38
- constructor(config: FeedbackConfig);
39
- init(): Promise<{
40
- initialized: boolean;
41
- config?: any;
42
- sessionToken?: string;
43
- expiresIn?: number;
44
- }>;
45
- createWidget(type: 'button', options?: Partial<FeedbackConfig>): ButtonWidget;
46
- setUserContext(userContext: UserContext): void;
47
- getUserContext(): UserContext | null;
48
- destroy(): void;
49
- readonly initialized: boolean;
50
- }
36
+ export class FeedbackSDK {
37
+ constructor(config: FeedbackConfig);
38
+ init(): Promise<{
39
+ initialized: boolean;
40
+ config?: any;
41
+ sessionToken?: string;
42
+ expiresIn?: number;
43
+ }>;
44
+ createWidget(
45
+ type: 'button',
46
+ options?: Partial<FeedbackConfig>
47
+ ): ButtonWidget;
48
+ setUserContext(userContext: UserContext): void;
49
+ getUserContext(): UserContext | null;
50
+ destroy(): void;
51
+ readonly initialized: boolean;
52
+ }
51
53
 
52
- interface FeedbackSDKExport {
53
- FeedbackSDK: typeof FeedbackSDK;
54
- ButtonWidget: any;
55
- create: (config: FeedbackConfig) => FeedbackSDK;
56
- initWithUser: (config: Omit<FeedbackConfig, 'userContext'>, userContext: UserContext) => Promise<FeedbackSDK>;
57
- getInstance: () => FeedbackSDK | null;
58
- isReady: () => boolean;
59
- setUserContext: (userContext: UserContext) => void;
60
- onReady: (callback: (sdk: FeedbackSDK) => void) => void;
61
- onError: (callback: (error: Error) => void) => void;
62
- version: string;
63
- instance: FeedbackSDK | null;
64
- }
54
+ interface FeedbackSDKExport {
55
+ FeedbackSDK: typeof FeedbackSDK;
56
+ ButtonWidget: any;
57
+ create: (config: FeedbackConfig) => FeedbackSDK;
58
+ initWithUser: (
59
+ config: Omit<FeedbackConfig, 'userContext'>,
60
+ userContext: UserContext
61
+ ) => Promise<FeedbackSDK>;
62
+ getInstance: () => FeedbackSDK | null;
63
+ isReady: () => boolean;
64
+ setUserContext: (userContext: UserContext) => void;
65
+ onReady: (callback: (sdk: FeedbackSDK) => void) => void;
66
+ onError: (callback: (error: Error) => void) => void;
67
+ version: string;
68
+ instance: FeedbackSDK | null;
69
+ }
65
70
 
66
- const FeedbackSDKDefault: FeedbackSDKExport;
67
- export default FeedbackSDKDefault;
68
- }
71
+ const FeedbackSDKDefault: FeedbackSDKExport;
72
+ export default FeedbackSDKDefault;
73
+ }