@product7/feedback-sdk 1.6.6 → 1.6.8

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.
@@ -921,15 +921,19 @@
921
921
  body: JSON.stringify(payload),
922
922
  headers: { 'Content-Type': 'application/json' },
923
923
  });
924
+ const initData = this._extractInitResponseData(response);
924
925
 
925
- this.sessionToken = response.session_token;
926
- this.sessionExpiry = new Date(Date.now() + response.expires_in * 1000);
926
+ this.sessionToken = initData.sessionToken;
927
+ this.sessionExpiry = new Date(Date.now() + initData.expiresIn * 1000);
927
928
  this._storeSession();
928
929
 
929
930
  return {
930
931
  sessionToken: this.sessionToken,
931
- config: response.config || {},
932
- expiresIn: response.expires_in,
932
+ config: initData.config,
933
+ expiresIn: initData.expiresIn,
934
+ status: initData.status,
935
+ message: initData.message,
936
+ configVersion: initData.configVersion,
933
937
  };
934
938
  } catch (error) {
935
939
  throw new APIError$1(
@@ -940,6 +944,34 @@
940
944
  }
941
945
  }
942
946
 
947
+ _extractInitResponseData(response) {
948
+ const payload =
949
+ response && typeof response.data === 'object' ? response.data : response || {};
950
+
951
+ const sessionToken = payload.session_token || payload.sessionToken;
952
+ const expiresIn = Number(payload.expires_in ?? payload.expiresIn);
953
+
954
+ if (!sessionToken) {
955
+ throw new APIError$1(500, 'Invalid init response: missing session_token');
956
+ }
957
+
958
+ if (!Number.isFinite(expiresIn) || expiresIn <= 0) {
959
+ throw new APIError$1(500, 'Invalid init response: missing expires_in');
960
+ }
961
+
962
+ return {
963
+ sessionToken,
964
+ expiresIn,
965
+ config:
966
+ payload.config && typeof payload.config === 'object'
967
+ ? payload.config
968
+ : {},
969
+ configVersion: payload.config_version ?? payload.configVersion ?? null,
970
+ status: response?.status ?? payload?.status ?? true,
971
+ message: response?.message ?? payload?.message ?? null,
972
+ };
973
+ }
974
+
943
975
  async _ensureSession() {
944
976
  if (!this.isSessionValid()) {
945
977
  await this.init();
@@ -1695,7 +1727,7 @@
1695
1727
  backgroundColor: options.backgroundColor || '#ffffff',
1696
1728
  textColor: options.textColor || '#1F2937',
1697
1729
  autoShow: false,
1698
- showBackdrop: false,
1730
+ showBackdrop: true,
1699
1731
  customStyles: {},
1700
1732
  suppressAfterSubmission: true,
1701
1733
  suppressionDays: BaseWidget.DEFAULT_COOLDOWN_DAYS,
@@ -1725,6 +1757,15 @@
1725
1757
  mount(container) {
1726
1758
  if (this.mounted || this.destroyed) return this;
1727
1759
 
1760
+ if (this.options.enabled === false) {
1761
+ this.sdk.eventBus.emit('widget:suppressed', {
1762
+ widget: this,
1763
+ type: this.type,
1764
+ reason: 'disabled',
1765
+ });
1766
+ return this;
1767
+ }
1768
+
1728
1769
  if (this.options.suppressAfterSubmission && this._hasRecentlySubmitted()) {
1729
1770
  this.sdk.eventBus.emit('widget:suppressed', {
1730
1771
  widget: this,
@@ -1804,9 +1845,11 @@
1804
1845
  _showLoadingModal() {
1805
1846
  this.state.isLoading = true;
1806
1847
 
1807
- this.backdropElement = document.createElement('div');
1808
- this.backdropElement.className = 'sdk-modal-backdrop';
1809
- document.body.appendChild(this.backdropElement);
1848
+ if (this.options.showBackdrop) {
1849
+ this.backdropElement = document.createElement('div');
1850
+ this.backdropElement.className = 'sdk-modal-backdrop';
1851
+ document.body.appendChild(this.backdropElement);
1852
+ }
1810
1853
 
1811
1854
  this.loadingElement = document.createElement('div');
1812
1855
  this.loadingElement.className = 'feedback-loading-modal';
@@ -1816,7 +1859,9 @@
1816
1859
  document.body.appendChild(this.loadingElement);
1817
1860
 
1818
1861
  requestAnimationFrame(() => {
1819
- this.backdropElement.classList.add('show');
1862
+ if (this.backdropElement) {
1863
+ this.backdropElement.classList.add('show');
1864
+ }
1820
1865
  this.loadingElement.classList.add('show');
1821
1866
  });
1822
1867
  }
@@ -2011,16 +2056,17 @@
2011
2056
  : 'feedback-panel';
2012
2057
  const sizeClass = `size-${this.options.size}`;
2013
2058
  this.panelElement = document.createElement('div');
2014
- this.panelElement.className = `${modeClass} ${sizeClass}`;
2059
+ const themeClass = `theme-${this.options.theme || 'light'}`;
2060
+ this.panelElement.className = `${modeClass} ${sizeClass} ${themeClass}`;
2061
+ this.panelElement.style.setProperty('--color-primary', this.options.primaryColor);
2015
2062
  this.panelElement.style.setProperty(
2016
- '--primary-color',
2017
- this.options.primaryColor
2063
+ '--feedback-panel-bg',
2064
+ this.options.backgroundColor
2018
2065
  );
2019
2066
  this.panelElement.style.setProperty(
2020
- '--bg-color',
2021
- this.options.backgroundColor
2067
+ '--feedback-panel-text',
2068
+ this.options.textColor
2022
2069
  );
2023
- this.panelElement.style.setProperty('--text-color', this.options.textColor);
2024
2070
  this.panelElement.innerHTML = this._getPanelHTML();
2025
2071
 
2026
2072
  document.body.appendChild(this.panelElement);
@@ -2349,7 +2395,7 @@
2349
2395
 
2350
2396
  _render() {
2351
2397
  const trigger = document.createElement('div');
2352
- trigger.className = `changelog-widget position-${this.options.position}`;
2398
+ trigger.className = `changelog-widget position-${this.options.position} changelog-theme-${this.options.theme || 'light'}`;
2353
2399
  trigger.innerHTML = `
2354
2400
  <button class="changelog-trigger-btn" type="button" aria-label="View Updates">
2355
2401
  <svg class="changelog-icon" width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
@@ -2425,12 +2471,12 @@
2425
2471
 
2426
2472
  _createModal() {
2427
2473
  this.backdropElement = document.createElement('div');
2428
- this.backdropElement.className = 'changelog-modal-backdrop';
2474
+ this.backdropElement.className = `changelog-modal-backdrop changelog-theme-${this.options.theme || 'light'}`;
2429
2475
  document.body.appendChild(this.backdropElement);
2430
2476
  this.backdropElement.addEventListener('click', () => this.closeModal());
2431
2477
 
2432
2478
  this.modalElement = document.createElement('div');
2433
- this.modalElement.className = 'changelog-modal';
2479
+ this.modalElement.className = `changelog-modal changelog-theme-${this.options.theme || 'light'}`;
2434
2480
  this.modalElement.innerHTML = `
2435
2481
  <div class="changelog-modal-container">
2436
2482
  <button class="changelog-modal-close" type="button" aria-label="Close"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><line x1="200" y1="56" x2="56" y2="200" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="200" y1="200" x2="56" y2="56" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg></button>
@@ -2568,14 +2614,14 @@
2568
2614
 
2569
2615
  _createListModal() {
2570
2616
  this.listModalBackdropElement = document.createElement('div');
2571
- this.listModalBackdropElement.className = 'changelog-list-modal-backdrop';
2617
+ this.listModalBackdropElement.className = `changelog-list-modal-backdrop changelog-theme-${this.options.theme || 'light'}`;
2572
2618
  document.body.appendChild(this.listModalBackdropElement);
2573
2619
  this.listModalBackdropElement.addEventListener('click', () =>
2574
2620
  this.closeSidebar()
2575
2621
  );
2576
2622
 
2577
2623
  this.listModalElement = document.createElement('div');
2578
- this.listModalElement.className = 'changelog-list-modal';
2624
+ this.listModalElement.className = `changelog-list-modal changelog-theme-${this.options.theme || 'light'}`;
2579
2625
  this.listModalElement.innerHTML = `
2580
2626
  <div class="changelog-list-modal-container">
2581
2627
  <div class="changelog-list-modal-header">
@@ -3357,7 +3403,12 @@
3357
3403
  }
3358
3404
 
3359
3405
  const adjustColor = (hex, percent, alpha = 1) => {
3360
- const num = parseInt(hex.replace('#', ''), 16);
3406
+ const normalized = String(hex || '').trim();
3407
+ if (!/^#?[0-9a-fA-F]{6}$/.test(normalized)) {
3408
+ return normalized || '#000000';
3409
+ }
3410
+
3411
+ const num = parseInt(normalized.replace('#', ''), 16);
3361
3412
  const r = Math.max(0, Math.min(255, (num >> 16) + percent));
3362
3413
  const g = Math.max(0, Math.min(255, ((num >> 8) & 0x00ff) + percent));
3363
3414
  const b = Math.max(0, Math.min(255, (num & 0x0000ff) + percent));
@@ -3369,6 +3420,10 @@
3369
3420
  return '#' + ((r << 16) | (g << 8) | b).toString(16).padStart(6, '0');
3370
3421
  };
3371
3422
 
3423
+ const darkSurface = adjustColor(backgroundColor, 12);
3424
+ const darkSurfaceAlt = adjustColor(backgroundColor, 20);
3425
+ const darkBorder = adjustColor(backgroundColor, 34);
3426
+
3372
3427
  styleElement.textContent = `
3373
3428
  #product7-messenger-widget {
3374
3429
  --color-primary: ${primaryColor} !important;
@@ -3430,6 +3485,77 @@
3430
3485
  `
3431
3486
  : ''
3432
3487
  }
3488
+
3489
+ ${
3490
+ theme === 'dark'
3491
+ ? `
3492
+ .messenger-widget.theme-dark .messenger-panel-content,
3493
+ .messenger-widget.theme-dark .messenger-home-view,
3494
+ .messenger-widget.theme-dark .messenger-nav,
3495
+ .messenger-widget.theme-dark .messenger-chat-compose,
3496
+ .messenger-widget.theme-dark .messenger-compose-attachments-preview,
3497
+ .messenger-widget.theme-dark .messenger-home-featured,
3498
+ .messenger-widget.theme-dark .messenger-chat-header {
3499
+ background: ${backgroundColor} !important;
3500
+ border-color: ${darkBorder} !important;
3501
+ }
3502
+
3503
+ .messenger-widget.theme-dark .messenger-view,
3504
+ .messenger-widget.theme-dark .messenger-chat-title,
3505
+ .messenger-widget.theme-dark .messenger-home-greeting,
3506
+ .messenger-widget.theme-dark .messenger-home-question,
3507
+ .messenger-widget.theme-dark .messenger-home-featured-content h3,
3508
+ .messenger-widget.theme-dark .messenger-home-featured-content p,
3509
+ .messenger-widget.theme-dark .messenger-home-changelog-card-title,
3510
+ .messenger-widget.theme-dark .messenger-home-changelog-card-desc,
3511
+ .messenger-widget.theme-dark .messenger-conversation-title,
3512
+ .messenger-widget.theme-dark .messenger-article-title,
3513
+ .messenger-widget.theme-dark .messenger-compose-input,
3514
+ .messenger-widget.theme-dark .messenger-message-sender,
3515
+ .messenger-widget.theme-dark .messenger-message-time,
3516
+ .messenger-widget.theme-dark .messenger-nav-label {
3517
+ color: ${textColor} !important;
3518
+ }
3519
+
3520
+ .messenger-widget.theme-dark .messenger-home-view {
3521
+ background: linear-gradient(180deg, ${adjustColor(backgroundColor, 10)} 0%, ${backgroundColor} 55%) !important;
3522
+ }
3523
+
3524
+ .messenger-widget.theme-dark .messenger-home-view::before {
3525
+ background: radial-gradient(circle, ${adjustColor(primaryColor, 0, 0.12)} 0%, transparent 70%) !important;
3526
+ }
3527
+
3528
+ .messenger-widget.theme-dark .messenger-home-message-btn,
3529
+ .messenger-widget.theme-dark .messenger-home-changelog-card,
3530
+ .messenger-widget.theme-dark .messenger-compose-input-wrapper,
3531
+ .messenger-widget.theme-dark .messenger-message-received .messenger-message-bubble,
3532
+ .messenger-widget.theme-dark .messenger-message-file,
3533
+ .messenger-widget.theme-dark .messenger-prechat-card,
3534
+ .messenger-widget.theme-dark .messenger-list-item,
3535
+ .messenger-widget.theme-dark .messenger-article-item {
3536
+ background: ${darkSurface} !important;
3537
+ border-color: ${darkBorder} !important;
3538
+ }
3539
+
3540
+ .messenger-widget.theme-dark .messenger-home-message-btn:hover,
3541
+ .messenger-widget.theme-dark .messenger-home-changelog-card:hover,
3542
+ .messenger-widget.theme-dark .messenger-list-item:hover,
3543
+ .messenger-widget.theme-dark .messenger-article-item:hover {
3544
+ background: ${darkSurfaceAlt} !important;
3545
+ }
3546
+
3547
+ .messenger-widget.theme-dark .messenger-message-own .messenger-message-bubble,
3548
+ .messenger-widget.theme-dark .messenger-compose-send,
3549
+ .messenger-widget.theme-dark .messenger-launcher-btn,
3550
+ .messenger-widget.theme-dark .messenger-nav-badge,
3551
+ .messenger-widget.theme-dark .messenger-launcher-badge,
3552
+ .messenger-widget.theme-dark .messenger-home-changelog-cover-text,
3553
+ .messenger-widget.theme-dark .messenger-attachment-remove {
3554
+ color: #FFFFFF !important;
3555
+ }
3556
+ `
3557
+ : ''
3558
+ }
3433
3559
  `;
3434
3560
 
3435
3561
  console.log('✅ Custom messenger styles applied:', { primaryColor, theme });
@@ -5901,6 +6027,19 @@
5901
6027
  class MessengerWidget extends BaseWidget {
5902
6028
  constructor(options) {
5903
6029
  super({ ...options, type: 'messenger' });
6030
+ const resolvedTheme = options.theme || 'light';
6031
+ const hasExplicitTextColor = Object.prototype.hasOwnProperty.call(
6032
+ options,
6033
+ 'textColor'
6034
+ );
6035
+ const hasExplicitBackgroundColor = Object.prototype.hasOwnProperty.call(
6036
+ options,
6037
+ 'backgroundColor'
6038
+ );
6039
+ const defaultTextColor =
6040
+ resolvedTheme === 'dark' ? '#E2E8F0' : '#1d1d1f';
6041
+ const defaultBackgroundColor =
6042
+ resolvedTheme === 'dark' ? '#0F172A' : '#ffffff';
5904
6043
 
5905
6044
  const resolvedEnableChangelog =
5906
6045
  typeof options.enableChangelog === 'boolean'
@@ -5909,10 +6048,12 @@
5909
6048
 
5910
6049
  this.messengerOptions = {
5911
6050
  position: options.position || 'bottom-right',
5912
- theme: options.theme || 'light',
6051
+ theme: resolvedTheme,
5913
6052
  primaryColor: options.primaryColor || '#155EEF',
5914
- textColor: options.textColor || '#1d1d1f',
5915
- backgroundColor: options.backgroundColor || '#ffffff',
6053
+ textColor: hasExplicitTextColor ? options.textColor : defaultTextColor,
6054
+ backgroundColor: hasExplicitBackgroundColor
6055
+ ? options.backgroundColor
6056
+ : defaultBackgroundColor,
5916
6057
  logoUrl: options.logoUrl || 'https://product7.io/p7logo.svg',
5917
6058
  teamName: options.teamName || 'Support',
5918
6059
  teamAvatars: options.teamAvatars || [],
@@ -6824,6 +6965,9 @@
6824
6965
  surveyId: options.surveyId || null,
6825
6966
  surveyType: options.surveyType || 'nps',
6826
6967
  position: options.position || 'bottom-right',
6968
+ theme: options.theme || 'light',
6969
+ enabled:
6970
+ typeof options.enabled === 'boolean' ? options.enabled : undefined,
6827
6971
  title: options.title || null,
6828
6972
  description: options.description || null,
6829
6973
  lowLabel: options.lowLabel || null,
@@ -6866,6 +7010,20 @@
6866
7010
  };
6867
7011
  }
6868
7012
 
7013
+ static removeDanglingElements() {
7014
+ if (typeof document === 'undefined') return;
7015
+
7016
+ document
7017
+ .querySelectorAll(
7018
+ '.feedback-survey, .feedback-survey-backdrop, .feedback-survey-success'
7019
+ )
7020
+ .forEach((el) => {
7021
+ if (el && el.parentNode) {
7022
+ el.parentNode.removeChild(el);
7023
+ }
7024
+ });
7025
+ }
7026
+
6869
7027
  _render() {
6870
7028
  const container = document.createElement('div');
6871
7029
  container.className = 'feedback-survey-container';
@@ -6877,6 +7035,16 @@
6877
7035
  }
6878
7036
 
6879
7037
  show() {
7038
+ if (this.options.enabled === false || this.surveyOptions.enabled === false) {
7039
+ this.sdk.eventBus.emit('survey:suppressed', {
7040
+ widget: this,
7041
+ surveyId: this.surveyOptions.surveyId,
7042
+ reason: 'disabled',
7043
+ });
7044
+ return this;
7045
+ }
7046
+
7047
+ SurveyWidget.removeDanglingElements();
6880
7048
  this._renderSurvey();
6881
7049
  this.surveyState.isVisible = true;
6882
7050
  this.sdk.eventBus.emit('survey:shown', {
@@ -6912,7 +7080,7 @@
6912
7080
 
6913
7081
  if (this.surveyOptions.position === 'center') {
6914
7082
  this.backdropElement = document.createElement('div');
6915
- this.backdropElement.className = 'feedback-survey-backdrop';
7083
+ this.backdropElement.className = `feedback-survey-backdrop feedback-survey-backdrop-${this.surveyOptions.theme}`;
6916
7084
  document.body.appendChild(this.backdropElement);
6917
7085
  this.backdropElement.addEventListener('click', () =>
6918
7086
  this._handleDismiss()
@@ -6920,7 +7088,7 @@
6920
7088
  }
6921
7089
 
6922
7090
  this.surveyElement = document.createElement('div');
6923
- this.surveyElement.className = `feedback-survey feedback-survey-${this.surveyOptions.position}${
7091
+ this.surveyElement.className = `feedback-survey feedback-survey-${this.surveyOptions.position} feedback-survey-theme-${this.surveyOptions.theme}${
6924
7092
  showDescription && !showTitle
6925
7093
  ? ' feedback-survey-description-primary'
6926
7094
  : ''
@@ -7940,7 +8108,7 @@
7940
8108
  }, 3000);
7941
8109
  }
7942
8110
 
7943
- _closeSurvey(resetState = true) {
8111
+ _closeSurvey(resetState = true, immediate = false) {
7944
8112
  if (this._escapeHandler) {
7945
8113
  document.removeEventListener('keydown', this._escapeHandler);
7946
8114
  this._escapeHandler = null;
@@ -7955,21 +8123,33 @@
7955
8123
  this.surveyOptions.position === 'center'
7956
8124
  ? 'translate(-50%, -50%) scale(0.95)'
7957
8125
  : 'translateY(20px)';
7958
- setTimeout(() => {
7959
- if (surveyEl && surveyEl.parentNode) {
8126
+ if (immediate) {
8127
+ if (surveyEl.parentNode) {
7960
8128
  surveyEl.parentNode.removeChild(surveyEl);
7961
8129
  }
7962
- }, 300);
8130
+ } else {
8131
+ setTimeout(() => {
8132
+ if (surveyEl && surveyEl.parentNode) {
8133
+ surveyEl.parentNode.removeChild(surveyEl);
8134
+ }
8135
+ }, 300);
8136
+ }
7963
8137
  this.surveyElement = null;
7964
8138
  }
7965
8139
 
7966
8140
  if (backdropEl) {
7967
8141
  backdropEl.style.opacity = '0';
7968
- setTimeout(() => {
7969
- if (backdropEl && backdropEl.parentNode) {
8142
+ if (immediate) {
8143
+ if (backdropEl.parentNode) {
7970
8144
  backdropEl.parentNode.removeChild(backdropEl);
7971
8145
  }
7972
- }, 300);
8146
+ } else {
8147
+ setTimeout(() => {
8148
+ if (backdropEl && backdropEl.parentNode) {
8149
+ backdropEl.parentNode.removeChild(backdropEl);
8150
+ }
8151
+ }, 300);
8152
+ }
7973
8153
  this.backdropElement = null;
7974
8154
  }
7975
8155
 
@@ -7987,7 +8167,7 @@
7987
8167
  }
7988
8168
 
7989
8169
  destroy() {
7990
- this._closeSurvey();
8170
+ this._closeSurvey(true, true);
7991
8171
  super.destroy();
7992
8172
  }
7993
8173
  }
@@ -8160,6 +8340,10 @@
8160
8340
  const widgetId = generateId('widget');
8161
8341
  const widgetConfig = this._getWidgetTypeConfig(type);
8162
8342
  const explicitOptions = this._omitUndefined(options);
8343
+ const widgetEnabled = this._isWidgetEnabled(type, {
8344
+ ...widgetConfig,
8345
+ ...explicitOptions,
8346
+ });
8163
8347
  const widgetOptions = {
8164
8348
  id: widgetId,
8165
8349
  sdk: this,
@@ -8167,6 +8351,7 @@
8167
8351
  ...this.config,
8168
8352
  ...widgetConfig,
8169
8353
  ...explicitOptions,
8354
+ enabled: widgetEnabled,
8170
8355
  };
8171
8356
 
8172
8357
  try {
@@ -8257,6 +8442,7 @@
8257
8442
  surveyConfig.showDescription ?? surveyConfig.show_description,
8258
8443
  customQuestions: surveyConfig.customQuestions || surveyConfig.questions,
8259
8444
  pages: surveyConfig.pages,
8445
+ enabled: surveyConfig.enabled,
8260
8446
  ...displayOptions,
8261
8447
  });
8262
8448
  }
@@ -8279,6 +8465,17 @@
8279
8465
 
8280
8466
  const normalizedOptions = this._normalizeSurveyConfig(options);
8281
8467
  const surveyConfigDefaults = this._getWidgetTypeConfig('survey');
8468
+ const surveyEnabled = this._isWidgetEnabled('survey', normalizedOptions);
8469
+
8470
+ if (!surveyEnabled) {
8471
+ this.eventBus.emit('survey:suppressed', {
8472
+ surveyId:
8473
+ normalizedOptions.surveyId || normalizedOptions.id || options.id || null,
8474
+ reason: 'disabled',
8475
+ survey: normalizedOptions,
8476
+ });
8477
+ return null;
8478
+ }
8282
8479
 
8283
8480
  const surveyWidget = this.createWidget('survey', {
8284
8481
  surveyId: normalizedOptions.surveyId,
@@ -8310,6 +8507,7 @@
8310
8507
  email: normalizedOptions.email,
8311
8508
  onSubmit: normalizedOptions.onSubmit,
8312
8509
  onDismiss: normalizedOptions.onDismiss,
8510
+ enabled: surveyEnabled,
8313
8511
  });
8314
8512
 
8315
8513
  surveyWidget.mount();
@@ -8403,13 +8601,19 @@
8403
8601
  : {};
8404
8602
 
8405
8603
  const inferredType =
8406
- survey.type || this._inferSurveyTypeFromPage(firstPage) || 'nps';
8604
+ survey.surveyType ||
8605
+ survey.survey_type ||
8606
+ survey.type ||
8607
+ this._inferSurveyTypeFromPage(firstPage) ||
8608
+ 'nps';
8407
8609
 
8408
8610
  return {
8409
8611
  ...survey,
8410
- surveyId: survey.surveyId || survey.id || null,
8411
- surveyType: survey.surveyType || inferredType,
8412
- type: survey.type || inferredType,
8612
+ surveyId: survey.surveyId || survey.survey_id || survey.id || null,
8613
+ surveyType: survey.surveyType || survey.survey_type || inferredType,
8614
+ type: survey.type || survey.survey_type || inferredType,
8615
+ enabled:
8616
+ typeof survey.enabled === 'boolean' ? survey.enabled : undefined,
8413
8617
  should_show:
8414
8618
  survey.should_show ??
8415
8619
  (survey.eligibility ? survey.eligibility.should_show : undefined),
@@ -8438,7 +8642,11 @@
8438
8642
  showTitle: survey.showTitle ?? survey.show_title ?? null,
8439
8643
  showDescription:
8440
8644
  survey.showDescription ?? survey.show_description ?? null,
8441
- customQuestions: survey.customQuestions || survey.questions || [],
8645
+ customQuestions:
8646
+ survey.customQuestions ||
8647
+ survey.custom_questions ||
8648
+ survey.questions ||
8649
+ [],
8442
8650
  pages: this._normalizeSurveyPages(survey.pages || []),
8443
8651
  };
8444
8652
  }
@@ -8513,6 +8721,23 @@
8513
8721
  return this._toCamelCaseObject(mergedTypeConfig);
8514
8722
  }
8515
8723
 
8724
+ _isWidgetEnabled(type, options = {}) {
8725
+ const typeConfig = this._getWidgetTypeConfig(type);
8726
+ if (typeConfig.enabled === false) {
8727
+ return false;
8728
+ }
8729
+
8730
+ if (typeof options.enabled === 'boolean') {
8731
+ return options.enabled;
8732
+ }
8733
+
8734
+ if (typeof typeConfig.enabled === 'boolean') {
8735
+ return typeConfig.enabled;
8736
+ }
8737
+
8738
+ return true;
8739
+ }
8740
+
8516
8741
  _isPlainObject(value) {
8517
8742
  return Object.prototype.toString.call(value) === '[object Object]';
8518
8743
  }
@@ -8566,11 +8791,21 @@
8566
8791
 
8567
8792
  const configDefaults = this._getWidgetTypeConfig('changelog');
8568
8793
  const explicitOptions = this._omitUndefined(options);
8794
+ const changelogEnabled = this._isWidgetEnabled('changelog', explicitOptions);
8795
+
8796
+ if (!changelogEnabled) {
8797
+ this.eventBus.emit('widget:suppressed', {
8798
+ type: 'changelog',
8799
+ reason: 'disabled',
8800
+ });
8801
+ return null;
8802
+ }
8569
8803
 
8570
8804
  const changelogWidget = this.createWidget('changelog', {
8571
8805
  ...defaults,
8572
8806
  ...configDefaults,
8573
8807
  ...explicitOptions,
8808
+ enabled: changelogEnabled,
8574
8809
  });
8575
8810
 
8576
8811
  changelogWidget.mount();
@@ -9025,6 +9260,23 @@
9025
9260
  font-family: inherit;
9026
9261
  }
9027
9262
 
9263
+ .changelog-modal-backdrop,
9264
+ .changelog-list-modal-backdrop {
9265
+ position: fixed;
9266
+ inset: 0;
9267
+ background: rgba(0, 0, 0, 0.5);
9268
+ opacity: 0;
9269
+ pointer-events: none;
9270
+ transition: opacity var(--transition-slow);
9271
+ z-index: var(--z-modal-backdrop);
9272
+ }
9273
+
9274
+ .changelog-modal-backdrop.show,
9275
+ .changelog-list-modal-backdrop.show {
9276
+ opacity: 1;
9277
+ pointer-events: auto;
9278
+ }
9279
+
9028
9280
  .changelog-modal.open {
9029
9281
  pointer-events: auto;
9030
9282
  }
@@ -9288,6 +9540,53 @@
9288
9540
  opacity: 1;
9289
9541
  }
9290
9542
 
9543
+ .changelog-theme-dark.changelog-widget .changelog-trigger-btn {
9544
+ background: #0F172A;
9545
+ color: #E2E8F0;
9546
+ border: 1px solid #334155;
9547
+ }
9548
+
9549
+ .changelog-theme-dark.changelog-modal-backdrop,
9550
+ .changelog-theme-dark.changelog-list-modal-backdrop {
9551
+ background: rgba(2, 6, 23, 0.72);
9552
+ }
9553
+
9554
+ .changelog-theme-dark .changelog-modal-container,
9555
+ .changelog-theme-dark .changelog-list-modal-container {
9556
+ background: #111827;
9557
+ border: 1px solid #334155;
9558
+ }
9559
+
9560
+ .changelog-theme-dark .changelog-list-modal-header {
9561
+ background: #111827;
9562
+ border-bottom-color: #334155;
9563
+ }
9564
+
9565
+ .changelog-theme-dark .changelog-list-modal-header h2,
9566
+ .changelog-theme-dark .changelog-list-item-title,
9567
+ .changelog-theme-dark .changelog-popup-title,
9568
+ .changelog-theme-dark .changelog-view-all-btn {
9569
+ color: #F3F4F6;
9570
+ }
9571
+
9572
+ .changelog-theme-dark .changelog-list-item-description,
9573
+ .changelog-theme-dark .changelog-popup-description,
9574
+ .changelog-theme-dark .changelog-list-item-date {
9575
+ color: #9CA3AF;
9576
+ }
9577
+
9578
+ .changelog-theme-dark .changelog-list-item {
9579
+ border-bottom-color: #334155;
9580
+ }
9581
+
9582
+ .changelog-theme-dark .changelog-list-item:hover {
9583
+ background: #1F2937;
9584
+ }
9585
+
9586
+ .changelog-theme-dark .changelog-popup-btn {
9587
+ color: #FFFFFF;
9588
+ }
9589
+
9291
9590
  .changelog-list-modal-header {
9292
9591
  display: flex;
9293
9592
  align-items: center;
@@ -10258,8 +10557,26 @@
10258
10557
  transform: translateX(0);
10259
10558
  }
10260
10559
 
10560
+ .feedback-modal {
10561
+ position: fixed;
10562
+ top: 50%;
10563
+ left: 50%;
10564
+ transform: translate(-50%, -50%) scale(0.96);
10565
+ width: min(460px, calc(100vw - (var(--spacing-5) * 2)));
10566
+ max-height: min(560px, calc(100vh - (var(--spacing-6) * 2)));
10567
+ z-index: var(--z-popover);
10568
+ transition: transform var(--transition-slow);
10569
+ font-family: inherit;
10570
+ box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
10571
+ }
10572
+
10573
+ .feedback-modal.open {
10574
+ transform: translate(-50%, -50%) scale(1);
10575
+ }
10576
+
10261
10577
  .feedback-panel-content {
10262
- background: var(--color-white);
10578
+ background: var(--feedback-panel-bg, var(--color-white));
10579
+ color: var(--feedback-panel-text, var(--color-text-primary));
10263
10580
  height: 100%;
10264
10581
  display: flex;
10265
10582
  flex-direction: column;
@@ -10279,7 +10596,7 @@
10279
10596
  margin: 0;
10280
10597
  font-size: var(--font-size-xl);
10281
10598
  font-weight: var(--font-weight-semibold);
10282
- color: var(--color-text-primary);
10599
+ color: var(--feedback-panel-text, var(--color-text-primary));
10283
10600
  }
10284
10601
 
10285
10602
  .feedback-panel-body {
@@ -10318,6 +10635,51 @@
10318
10635
  display: block;
10319
10636
  }
10320
10637
 
10638
+ .feedback-panel.theme-dark .feedback-panel-content,
10639
+ .feedback-modal.theme-dark .feedback-panel-content {
10640
+ background: #111827;
10641
+ color: #E2E8F0;
10642
+ }
10643
+
10644
+ .feedback-panel.theme-dark .feedback-panel-header,
10645
+ .feedback-modal.theme-dark .feedback-panel-header {
10646
+ border-bottom-color: #374151;
10647
+ }
10648
+
10649
+ .feedback-panel.theme-dark .sdk-label,
10650
+ .feedback-panel.theme-dark .feedback-panel-header h3,
10651
+ .feedback-modal.theme-dark .sdk-label,
10652
+ .feedback-modal.theme-dark .feedback-panel-header h3 {
10653
+ color: #E2E8F0;
10654
+ }
10655
+
10656
+ .feedback-panel.theme-dark .sdk-input,
10657
+ .feedback-panel.theme-dark .sdk-textarea,
10658
+ .feedback-modal.theme-dark .sdk-input,
10659
+ .feedback-modal.theme-dark .sdk-textarea {
10660
+ background: #1F2937;
10661
+ border-color: #374151;
10662
+ color: #E2E8F0;
10663
+ }
10664
+
10665
+ .feedback-panel.theme-dark .sdk-input::placeholder,
10666
+ .feedback-panel.theme-dark .sdk-textarea::placeholder,
10667
+ .feedback-modal.theme-dark .sdk-input::placeholder,
10668
+ .feedback-modal.theme-dark .sdk-textarea::placeholder {
10669
+ color: #9CA3AF;
10670
+ }
10671
+
10672
+ .feedback-panel.theme-dark .sdk-close-btn,
10673
+ .feedback-modal.theme-dark .sdk-close-btn {
10674
+ color: #9CA3AF;
10675
+ }
10676
+
10677
+ .feedback-panel.theme-dark .sdk-close-btn:hover,
10678
+ .feedback-modal.theme-dark .sdk-close-btn:hover {
10679
+ background: #1F2937;
10680
+ color: #E2E8F0;
10681
+ }
10682
+
10321
10683
  @media (max-width: 768px) {
10322
10684
  .feedback-widget-button {
10323
10685
  bottom: var(--spacing-4);
@@ -12020,6 +12382,10 @@
12020
12382
  animation: fadeIn var(--transition-slow);
12021
12383
  }
12022
12384
 
12385
+ .feedback-survey-backdrop-dark {
12386
+ background: rgba(2, 6, 23, 0.72);
12387
+ }
12388
+
12023
12389
  /* ========================================
12024
12390
  SURVEY CARD
12025
12391
  ======================================== */
@@ -12037,6 +12403,79 @@
12037
12403
  font-family: inherit;
12038
12404
  }
12039
12405
 
12406
+ .feedback-survey-theme-dark {
12407
+ background: #111827;
12408
+ border-color: #374151;
12409
+ }
12410
+
12411
+ .feedback-survey-theme-dark .feedback-survey-title,
12412
+ .feedback-survey-theme-dark .feedback-survey-description-primary .feedback-survey-description {
12413
+ color: #F3F4F6;
12414
+ }
12415
+
12416
+ .feedback-survey-theme-dark .feedback-survey-description,
12417
+ .feedback-survey-theme-dark .feedback-survey-labels,
12418
+ .feedback-survey-theme-dark .feedback-survey-progress {
12419
+ color: #9CA3AF;
12420
+ }
12421
+
12422
+ .feedback-survey-theme-dark .feedback-survey-close {
12423
+ color: #9CA3AF;
12424
+ }
12425
+
12426
+ .feedback-survey-theme-dark .feedback-survey-close:hover {
12427
+ background: #1F2937;
12428
+ color: #F3F4F6;
12429
+ }
12430
+
12431
+ .feedback-survey-theme-dark .feedback-survey-rating-scale {
12432
+ border-color: #374151;
12433
+ background: #1F2937;
12434
+ }
12435
+
12436
+ .feedback-survey-theme-dark .feedback-survey-rating-scale-btn {
12437
+ background: #1F2937;
12438
+ border-right-color: #374151;
12439
+ color: #F3F4F6;
12440
+ }
12441
+
12442
+ .feedback-survey-theme-dark .feedback-survey-rating-scale-btn:hover,
12443
+ .feedback-survey-theme-dark .feedback-survey-nps-btn:hover,
12444
+ .feedback-survey-theme-dark .feedback-survey-ces-btn:hover,
12445
+ .feedback-survey-theme-dark .feedback-survey-page-choice-btn:hover {
12446
+ background: #273549;
12447
+ }
12448
+
12449
+ .feedback-survey-theme-dark .feedback-survey-nps-btn,
12450
+ .feedback-survey-theme-dark .feedback-survey-ces-btn,
12451
+ .feedback-survey-theme-dark .feedback-survey-freq-btn,
12452
+ .feedback-survey-theme-dark .feedback-survey-page-choice-btn {
12453
+ background: #1F2937;
12454
+ border-color: #374151;
12455
+ color: #E5E7EB;
12456
+ }
12457
+
12458
+ .feedback-survey-theme-dark .feedback-survey-page-textarea,
12459
+ .feedback-survey-theme-dark .feedback-survey-select,
12460
+ .feedback-survey-theme-dark .feedback-survey-input,
12461
+ .feedback-survey-theme-dark .feedback-survey-textarea {
12462
+ background: #1F2937;
12463
+ border-color: #374151;
12464
+ color: #F3F4F6;
12465
+ }
12466
+
12467
+ .feedback-survey-theme-dark .feedback-survey-page-textarea::placeholder,
12468
+ .feedback-survey-theme-dark .feedback-survey-input::placeholder,
12469
+ .feedback-survey-theme-dark .feedback-survey-textarea::placeholder {
12470
+ color: #9CA3AF;
12471
+ }
12472
+
12473
+ .feedback-survey-theme-dark .feedback-survey-back {
12474
+ background: #111827;
12475
+ border-color: #374151;
12476
+ color: #E5E7EB;
12477
+ }
12478
+
12040
12479
  .feedback-survey-bottom-right {
12041
12480
  bottom: var(--spacing-6);
12042
12481
  right: var(--spacing-6);