@product7/feedback-sdk 1.6.8 → 1.7.0

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.
@@ -179,31 +179,172 @@
179
179
  const MOCK_SURVEYS = [
180
180
  {
181
181
  id: 'mock_nps_survey',
182
- type: 'nps',
183
- title: 'How likely are you to recommend us?',
184
- description: 'Your feedback helps us improve',
185
- low_label: 'Not likely',
186
- high_label: 'Very likely',
187
- trigger: 'manual',
182
+ name: 'NPS Score',
183
+ slug: 'nps',
188
184
  status: 'active',
185
+ trigger_type: 'manual',
186
+ pages: [
187
+ {
188
+ id: 'nps-page-1',
189
+ type: 'rating',
190
+ title: 'How likely are you to recommend us to a friend?',
191
+ description: '',
192
+ placeholder: '',
193
+ rating_config: { scale: 11, low_label: 'Very unlikely', high_label: 'Very likely', survey_type: 'nps' },
194
+ multiple_choice_config: null,
195
+ link_config: null,
196
+ after_this_page: { default: 'end_survey', conditions: [] },
197
+ required: true,
198
+ },
199
+ ],
189
200
  },
190
201
  {
191
202
  id: 'mock_csat_survey',
192
- type: 'csat',
193
- title: 'How satisfied are you?',
194
- description: 'Rate your experience with our product',
195
- trigger: 'manual',
203
+ name: 'CSAT Survey',
204
+ slug: 'csat',
196
205
  status: 'active',
206
+ trigger_type: 'manual',
207
+ pages: [
208
+ {
209
+ id: 'csat-page-1',
210
+ type: 'rating',
211
+ title: 'How satisfied are you with our service?',
212
+ description: '',
213
+ placeholder: '',
214
+ rating_config: { scale: 5, low_label: 'Very dissatisfied', high_label: 'Very satisfied', survey_type: 'emoji' },
215
+ multiple_choice_config: null,
216
+ link_config: null,
217
+ after_this_page: { default: 'end_survey', conditions: [] },
218
+ required: true,
219
+ },
220
+ ],
197
221
  },
198
222
  {
199
223
  id: 'mock_ces_survey',
200
- type: 'ces',
201
- title: 'How easy was it?',
202
- description: 'Rate the ease of completing your task',
203
- low_label: 'Very difficult',
204
- high_label: 'Very easy',
205
- trigger: 'manual',
224
+ name: 'Customer Effort Score',
225
+ slug: 'ces',
226
+ status: 'active',
227
+ trigger_type: 'manual',
228
+ pages: [
229
+ {
230
+ id: 'ces-page-1',
231
+ type: 'rating',
232
+ title: 'How easy was it to use our product?',
233
+ description: '',
234
+ placeholder: '',
235
+ rating_config: { scale: 5, low_label: 'Very difficult', high_label: 'Very easy', survey_type: 'ces' },
236
+ multiple_choice_config: null,
237
+ link_config: null,
238
+ after_this_page: { default: 'end_survey', conditions: [] },
239
+ required: true,
240
+ },
241
+ ],
242
+ },
243
+ {
244
+ id: 'mock_open_question_survey',
245
+ name: 'Open Question',
246
+ slug: 'open-question',
206
247
  status: 'active',
248
+ trigger_type: 'manual',
249
+ pages: [
250
+ {
251
+ id: 'open-page-1',
252
+ type: 'text',
253
+ title: 'What could we do better?',
254
+ description: 'Is there anything we could do to make our product better for you?',
255
+ placeholder: 'Type your answer here',
256
+ rating_config: null,
257
+ multiple_choice_config: null,
258
+ link_config: null,
259
+ after_this_page: { default: 'end_survey', conditions: [] },
260
+ required: true,
261
+ },
262
+ ],
263
+ },
264
+ {
265
+ id: 'mock_product_idea_poll_survey',
266
+ name: 'Product Idea Poll',
267
+ slug: 'product-idea-poll',
268
+ status: 'active',
269
+ trigger_type: 'manual',
270
+ pages: [
271
+ {
272
+ id: 'poll-page-1',
273
+ type: 'multiple_choice',
274
+ title: 'Which feature should we add next?',
275
+ description: 'Vote on the feature you would like to see next.',
276
+ placeholder: '',
277
+ rating_config: null,
278
+ multiple_choice_config: {
279
+ allow_multiple_selection: false,
280
+ survey_type: 'regular',
281
+ options: [
282
+ { id: 'opt1', label: 'Better reporting' },
283
+ { id: 'opt2', label: 'Mobile app' },
284
+ { id: 'opt3', label: 'Integrations' },
285
+ { id: 'opt4', label: 'AI features' },
286
+ ],
287
+ },
288
+ link_config: null,
289
+ after_this_page: { default: 'end_survey', conditions: [] },
290
+ required: true,
291
+ },
292
+ ],
293
+ },
294
+ {
295
+ id: 'mock_pmf_survey',
296
+ name: 'Product Market Fit (PMF)',
297
+ slug: 'pmf',
298
+ status: 'active',
299
+ trigger_type: 'manual',
300
+ pages: [
301
+ {
302
+ id: 'pmf-page-1',
303
+ type: 'multiple_choice',
304
+ title: 'How would you feel if you could no longer use our product?',
305
+ description: '',
306
+ placeholder: '',
307
+ rating_config: null,
308
+ multiple_choice_config: {
309
+ allow_multiple_selection: false,
310
+ survey_type: 'regular',
311
+ options: [
312
+ { id: 'very_disappointed', label: 'Very disappointed' },
313
+ { id: 'somewhat_disappointed', label: 'Somewhat disappointed' },
314
+ { id: 'not_disappointed', label: 'Not disappointed' },
315
+ ],
316
+ },
317
+ link_config: null,
318
+ after_this_page: { default: 'end_survey', conditions: [] },
319
+ required: true,
320
+ },
321
+ ],
322
+ },
323
+ {
324
+ id: 'mock_user_interview_survey',
325
+ name: 'User Interview Request',
326
+ slug: 'user-interview',
327
+ status: 'active',
328
+ trigger_type: 'manual',
329
+ pages: [
330
+ {
331
+ id: 'interview-page-1',
332
+ type: 'link',
333
+ title: 'Would you like to hop on a quick demo?',
334
+ description: 'We would love to hear your thoughts and answer any questions you have.',
335
+ placeholder: '',
336
+ rating_config: null,
337
+ multiple_choice_config: null,
338
+ link_config: {
339
+ button_text: 'Book a demo',
340
+ link_text: '',
341
+ redirect_url: 'https://example.com',
342
+ open_in: 'new_tab',
343
+ },
344
+ after_this_page: { default: 'end_survey', conditions: [] },
345
+ required: true,
346
+ },
347
+ ],
207
348
  },
208
349
  ];
209
350
 
@@ -2390,6 +2531,7 @@
2390
2531
  this.isLoading = false;
2391
2532
  this.modalElement = null;
2392
2533
  this.sidebarElement = null;
2534
+ this.listModalBackdropElement = null;
2393
2535
  this.currentIndex = 0;
2394
2536
  }
2395
2537
 
@@ -2470,10 +2612,12 @@
2470
2612
  }
2471
2613
 
2472
2614
  _createModal() {
2473
- this.backdropElement = document.createElement('div');
2474
- this.backdropElement.className = `changelog-modal-backdrop changelog-theme-${this.options.theme || 'light'}`;
2475
- document.body.appendChild(this.backdropElement);
2476
- this.backdropElement.addEventListener('click', () => this.closeModal());
2615
+ if (this.options.showBackdrop !== false) {
2616
+ this.backdropElement = document.createElement('div');
2617
+ this.backdropElement.className = `changelog-modal-backdrop changelog-theme-${this.options.theme || 'light'}`;
2618
+ document.body.appendChild(this.backdropElement);
2619
+ this.backdropElement.addEventListener('click', () => this.closeModal());
2620
+ }
2477
2621
 
2478
2622
  this.modalElement = document.createElement('div');
2479
2623
  this.modalElement.className = `changelog-modal changelog-theme-${this.options.theme || 'light'}`;
@@ -2613,12 +2757,14 @@
2613
2757
  }
2614
2758
 
2615
2759
  _createListModal() {
2616
- this.listModalBackdropElement = document.createElement('div');
2617
- this.listModalBackdropElement.className = `changelog-list-modal-backdrop changelog-theme-${this.options.theme || 'light'}`;
2618
- document.body.appendChild(this.listModalBackdropElement);
2619
- this.listModalBackdropElement.addEventListener('click', () =>
2620
- this.closeSidebar()
2621
- );
2760
+ if (this.options.showBackdrop !== false) {
2761
+ this.listModalBackdropElement = document.createElement('div');
2762
+ this.listModalBackdropElement.className = `changelog-list-modal-backdrop changelog-theme-${this.options.theme || 'light'}`;
2763
+ document.body.appendChild(this.listModalBackdropElement);
2764
+ this.listModalBackdropElement.addEventListener('click', () =>
2765
+ this.closeSidebar()
2766
+ );
2767
+ }
2622
2768
 
2623
2769
  this.listModalElement = document.createElement('div');
2624
2770
  this.listModalElement.className = `changelog-list-modal changelog-theme-${this.options.theme || 'light'}`;
@@ -7363,6 +7509,8 @@
7363
7509
  return this._renderMultipleChoicePage(page);
7364
7510
  case 'text':
7365
7511
  return this._renderTextPage(page);
7512
+ case 'link':
7513
+ return this._renderLinkPage(page);
7366
7514
  default:
7367
7515
  return this._renderTextPage(page);
7368
7516
  }
@@ -7421,6 +7569,21 @@
7421
7569
  `;
7422
7570
  }
7423
7571
 
7572
+ if (ratingType === 'ces') {
7573
+ const cesLabels = ['Very Difficult', 'Difficult', 'Neutral', 'Easy', 'Very Easy'];
7574
+ return `
7575
+ <div class="feedback-survey-ces" data-page-id="${pageId}">
7576
+ ${cesLabels
7577
+ .map((label, i) => {
7578
+ const score = i + 1;
7579
+ const selected = currentRating === score ? ' selected' : '';
7580
+ return `<button class="feedback-survey-page-rating-btn feedback-survey-ces-btn${selected}" data-page-id="${pageId}" data-score="${score}">${label}</button>`;
7581
+ })
7582
+ .join('')}
7583
+ </div>
7584
+ `;
7585
+ }
7586
+
7424
7587
  if (ratingType === 'emoji' && scale === 5) {
7425
7588
  const emojis = [
7426
7589
  '\uD83D\uDE1E',
@@ -7463,7 +7626,9 @@
7463
7626
  page.multipleChoiceConfig || page.multiple_choice_config || {};
7464
7627
  const options = Array.isArray(config.options) ? config.options : [];
7465
7628
  const allowMultiple =
7466
- config.allow_multiple === true || config.multiple === true;
7629
+ config.allow_multiple === true ||
7630
+ config.multiple === true ||
7631
+ config.allow_multiple_selection === true;
7467
7632
  const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
7468
7633
  const selectedValues = Array.isArray(pageAnswer.values)
7469
7634
  ? pageAnswer.values
@@ -7490,10 +7655,36 @@
7490
7655
  const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
7491
7656
  const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
7492
7657
  const value = pageAnswer.text || '';
7658
+ const placeholder = page.placeholder || 'Type your answer...';
7493
7659
 
7494
7660
  return `
7495
7661
  <div class="feedback-survey-text-page" data-page-id="${pageId}">
7496
- <textarea class="feedback-survey-page-textarea" data-page-id="${pageId}" placeholder="Type your answer...">${value}</textarea>
7662
+ <textarea class="feedback-survey-page-textarea" data-page-id="${pageId}" placeholder="${placeholder}">${value}</textarea>
7663
+ </div>
7664
+ `;
7665
+ }
7666
+
7667
+ _renderLinkPage(page) {
7668
+ const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
7669
+ const config = page.link_config || page.linkConfig || {};
7670
+ const buttonText = config.button_text || config.buttonText || 'Click here';
7671
+ const linkText = config.link_text || config.linkText || '';
7672
+ const redirectUrl = config.redirect_url || config.redirectUrl || '#';
7673
+ const openIn = config.open_in || config.openIn || 'new_tab';
7674
+ const target = openIn === 'new_tab' ? '_blank' : '_self';
7675
+ const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
7676
+ const clicked = pageAnswer.clicked === true;
7677
+
7678
+ return `
7679
+ <div class="feedback-survey-link-page" data-page-id="${pageId}">
7680
+ ${linkText ? `<p class="feedback-survey-link-text">${linkText}</p>` : ''}
7681
+ <a class="feedback-survey-link-btn${clicked ? ' selected' : ''}"
7682
+ href="${redirectUrl}"
7683
+ target="${target}"
7684
+ rel="noopener noreferrer"
7685
+ data-page-id="${pageId}">
7686
+ ${buttonText}
7687
+ </a>
7497
7688
  </div>
7498
7689
  `;
7499
7690
  }
@@ -7742,6 +7933,24 @@
7742
7933
  });
7743
7934
  }
7744
7935
  }
7936
+
7937
+ if (page.type === 'link') {
7938
+ this.surveyElement
7939
+ .querySelectorAll('.feedback-survey-link-btn')
7940
+ .forEach((btn) => {
7941
+ btn.addEventListener('click', () => {
7942
+ const pId = btn.dataset.pageId;
7943
+ this._setPageAnswer(pId, { clicked: true });
7944
+ btn.classList.add('selected');
7945
+
7946
+ const navigation = page.afterThisPage || page.after_this_page;
7947
+ const goesTo = navigation ? navigation.default : null;
7948
+ if (!goesTo || goesTo === 'end_survey') {
7949
+ setTimeout(() => this._handleSubmit(), 400);
7950
+ }
7951
+ });
7952
+ });
7953
+ }
7745
7954
  }
7746
7955
 
7747
7956
  _selectNPS(score) {
@@ -7933,6 +8142,13 @@
7933
8142
  }
7934
8143
  }
7935
8144
 
8145
+ if (page.type === 'link') {
8146
+ if (page.required && !answer.clicked) {
8147
+ this._showError('Please click the link to continue');
8148
+ return false;
8149
+ }
8150
+ }
8151
+
7936
8152
  return true;
7937
8153
  }
7938
8154
 
@@ -8787,6 +9003,7 @@
8787
9003
  triggerText: "What's New",
8788
9004
  showBadge: true,
8789
9005
  viewButtonText: 'View Update',
9006
+ showBackdrop: true,
8790
9007
  };
8791
9008
 
8792
9009
  const configDefaults = this._getWidgetTypeConfig('changelog');