@product7/product7-js 0.4.1 → 0.4.3

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.
@@ -452,9 +452,9 @@
452
452
  content: feedbackData.content,
453
453
  attachments: feedbackData.attachments || [],
454
454
  ...(contact?.contactId && {
455
- contact_id: contact.contactId,
455
+ contact_id: contact.contactId,
456
456
  contact_email: contact.contactEmail,
457
- contact_name: contact.contactName,
457
+ contact_name: contact.contactName,
458
458
  }),
459
459
  };
460
460
 
@@ -972,9 +972,9 @@
972
972
  }),
973
973
  ...(respondent.email && { email: respondent.email }),
974
974
  ...(contact?.contactId && {
975
- contact_id: contact.contactId,
975
+ contact_id: contact.contactId,
976
976
  contact_email: contact.contactEmail,
977
- contact_name: contact.contactName,
977
+ contact_name: contact.contactName,
978
978
  }),
979
979
  };
980
980
 
@@ -5706,7 +5706,7 @@
5706
5706
  background: var(--color-white);
5707
5707
  border: 1px solid var(--color-neutral-200);
5708
5708
  border-radius: var(--radius-xl);
5709
- box-shadow: var(--shadow-lg);
5709
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
5710
5710
  padding: var(--spacing-6);
5711
5711
  min-width: 320px;
5712
5712
  max-width: 400px;
@@ -5717,11 +5717,10 @@
5717
5717
  }
5718
5718
 
5719
5719
  /* ========================================
5720
- DARK THEME — scoped variable overrides
5720
+ DARK THEME
5721
5721
  ======================================== */
5722
5722
 
5723
5723
  .feedback-survey-theme-dark {
5724
- /* Aligned with messenger dark theme */
5725
5724
  --color-white: #0f1317;
5726
5725
  --color-background: #0f1317;
5727
5726
  --color-surface: #1a1e24;
@@ -5736,7 +5735,6 @@
5736
5735
  --color-text-primary: #e8e8e8;
5737
5736
  --color-text-secondary: #999999;
5738
5737
  --color-text-tertiary: #666666;
5739
- /* Survey-specific tokens */
5740
5738
  --color-primary-light: rgba(21, 94, 239, 0.18);
5741
5739
  --color-primary-border: rgba(21, 94, 239, 0.4);
5742
5740
  --color-error-light: rgba(239, 68, 68, 0.15);
@@ -5766,7 +5764,6 @@
5766
5764
  transform: translate(-50%, -50%) scale(0.97);
5767
5765
  }
5768
5766
 
5769
-
5770
5767
  /* ========================================
5771
5768
  CLOSE BUTTON
5772
5769
  ======================================== */
@@ -5858,7 +5855,7 @@
5858
5855
  }
5859
5856
 
5860
5857
  /* ========================================
5861
- NPS
5858
+ NPS — individual colored buttons
5862
5859
  ======================================== */
5863
5860
 
5864
5861
  .feedback-survey-nps {
@@ -5871,40 +5868,57 @@
5871
5868
  flex: 1;
5872
5869
  height: 40px;
5873
5870
  min-height: unset;
5874
- border: 1px solid var(--color-border);
5875
- border-radius: var(--radius-md);
5876
- background: var(--color-surface);
5871
+ border-radius: 6px;
5877
5872
  cursor: pointer;
5878
5873
  font-size: var(--font-size-sm);
5879
5874
  font-weight: var(--font-weight-medium);
5880
- color: var(--color-text-primary);
5881
- transition: all var(--transition-fast);
5875
+ color: #ffffff;
5876
+ border: 1px solid transparent;
5877
+ transition: filter var(--transition-fast), transform var(--transition-fast);
5882
5878
  font-family: inherit;
5883
5879
  }
5884
5880
 
5885
5881
  .feedback-survey-nps-btn:hover {
5886
- background: var(--color-primary-light);
5887
- border-color: var(--color-primary-border);
5888
- color: var(--color-primary);
5882
+ filter: brightness(1.1);
5889
5883
  }
5890
5884
 
5891
5885
  .feedback-survey-nps-btn.selected {
5892
- background: var(--color-primary-light);
5893
- border-color: var(--color-primary);
5894
- color: var(--color-primary-active);
5895
5886
  transform: scale(1.06);
5896
5887
  z-index: 1;
5897
5888
  position: relative;
5889
+ box-shadow: 0 0 0 2px #fff, 0 0 0 4px currentColor;
5890
+ }
5891
+
5892
+ .feedback-survey-nps-btn:active {
5893
+ transform: translateY(1px);
5894
+ transition-duration: 100ms;
5898
5895
  }
5899
5896
 
5897
+ .feedback-survey-nps-btn.selected:active {
5898
+ transform: scale(1.06) translateY(1px);
5899
+ }
5900
+
5901
+ /* NPS score colors */
5902
+ .feedback-survey-nps-score-0 { background: #dc2626; border-color: #dc2626; }
5903
+ .feedback-survey-nps-score-1 { background: #ef4444; border-color: #ef4444; }
5904
+ .feedback-survey-nps-score-2 { background: #f97316; border-color: #f97316; }
5905
+ .feedback-survey-nps-score-3 { background: #fb923c; border-color: #fb923c; }
5906
+ .feedback-survey-nps-score-4 { background: #fdba74; border-color: #fdba74; }
5907
+ .feedback-survey-nps-score-5 { background: #fbbf24; border-color: #fbbf24; }
5908
+ .feedback-survey-nps-score-6 { background: #fde047; border-color: #fde047; color: #171717; }
5909
+ .feedback-survey-nps-score-7 { background: #e5e7eb; border-color: #e5e7eb; color: #374151; }
5910
+ .feedback-survey-nps-score-8 { background: #e5e7eb; border-color: #e5e7eb; color: #374151; }
5911
+ .feedback-survey-nps-score-9 { background: #4ade80; border-color: #4ade80; }
5912
+ .feedback-survey-nps-score-10 { background: #16a34a; border-color: #16a34a; }
5913
+
5900
5914
  /* ========================================
5901
- CSAT
5915
+ CSAT — emoji row
5902
5916
  ======================================== */
5903
5917
 
5904
5918
  .feedback-survey-csat {
5905
5919
  display: flex;
5906
- justify-content: center;
5907
- gap: var(--spacing-4);
5920
+ justify-content: space-between;
5921
+ gap: var(--spacing-3);
5908
5922
  padding: var(--spacing-2) 0;
5909
5923
  }
5910
5924
 
@@ -5914,7 +5928,7 @@
5914
5928
  cursor: pointer;
5915
5929
  font-size: 32px;
5916
5930
  transition: transform var(--transition-fast), opacity var(--transition-fast);
5917
- padding: var(--spacing-2);
5931
+ padding: var(--spacing-2) var(--spacing-1);
5918
5932
  min-width: 44px;
5919
5933
  min-height: 44px;
5920
5934
  display: flex;
@@ -5937,147 +5951,24 @@
5937
5951
  opacity: 0.3;
5938
5952
  }
5939
5953
 
5940
- /* ========================================
5941
- CES SEGMENTED (short scale)
5942
- ======================================== */
5943
-
5944
- .feedback-survey-ces {
5945
- display: flex;
5946
- justify-content: space-between;
5947
- gap: var(--spacing-2);
5948
- }
5949
-
5950
- .feedback-survey-ces-btn {
5951
- flex: 1;
5952
- height: 40px;
5953
- padding: 0 var(--spacing-2);
5954
- border: 1px solid var(--color-border);
5955
- border-radius: var(--radius-md);
5956
- background: var(--color-surface);
5957
- cursor: pointer;
5958
- font-size: var(--font-size-xs);
5959
- font-weight: var(--font-weight-medium);
5960
- color: var(--color-text-primary);
5961
- transition: all var(--transition-fast);
5962
- font-family: inherit;
5963
- text-align: center;
5964
- }
5965
-
5966
- .feedback-survey-ces-btn:hover {
5967
- background: var(--color-primary-light);
5968
- border-color: var(--color-primary-border);
5969
- color: var(--color-primary);
5970
- }
5971
-
5972
- .feedback-survey-ces-btn.selected {
5973
- background: var(--color-primary-light);
5974
- border-color: var(--color-primary);
5975
- color: var(--color-primary-active);
5976
- }
5977
-
5978
- /* ========================================
5979
- CES LIST
5980
- ======================================== */
5981
-
5982
- .feedback-survey-ces-list {
5983
- display: flex;
5984
- flex-direction: column;
5985
- gap: var(--spacing-2);
5986
- }
5987
-
5988
- .feedback-survey-ces-list-btn {
5989
- width: 100%;
5990
- height: 40px;
5991
- padding: 0 var(--spacing-4);
5992
- border: 1px solid var(--color-border);
5993
- border-radius: var(--radius-md);
5994
- background: var(--color-surface);
5995
- cursor: pointer;
5996
- font-size: var(--font-size-base);
5997
- font-weight: var(--font-weight-medium);
5998
- color: var(--color-text-primary);
5999
- transition: all var(--transition-fast);
6000
- font-family: inherit;
6001
- text-align: left;
6002
- display: flex;
6003
- align-items: center;
6004
- justify-content: space-between;
6005
- }
6006
-
6007
- .feedback-survey-ces-list-btn:hover {
6008
- background: var(--color-primary-light);
6009
- border-color: var(--color-primary-border);
6010
- color: var(--color-primary);
6011
- }
6012
-
6013
- .feedback-survey-ces-list-btn.selected {
6014
- background: var(--color-primary-light);
6015
- border-color: var(--color-primary);
6016
- color: var(--color-primary-active);
6017
- }
6018
-
6019
- /* ========================================
6020
- SELECTION INDICATOR (choice & CES list)
6021
- ======================================== */
6022
-
6023
- .feedback-survey-ces-list-btn::after,
6024
- .feedback-survey-page-choice-btn::after {
6025
- content: '';
6026
- width: 18px;
6027
- height: 18px;
6028
- border-radius: 50%;
6029
- border: 1.5px solid var(--color-neutral-300);
6030
- flex-shrink: 0;
6031
- background: transparent;
6032
- background-size: 10px 10px;
6033
- background-repeat: no-repeat;
6034
- background-position: center;
6035
- transition: all var(--transition-fast);
5954
+ .feedback-survey-csat-btn:active {
5955
+ transform: scale(1.05) translateY(1px);
5956
+ transition-duration: 100ms;
6036
5957
  }
6037
5958
 
6038
- .feedback-survey-ces-list-btn.selected::after,
6039
- .feedback-survey-page-choice-btn.selected::after {
6040
- border-color: var(--color-primary);
6041
- background-color: var(--color-primary);
6042
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpolyline points='2,6.5 5,9.5 10,3' stroke='white' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
5959
+ .feedback-survey-csat-btn.selected:active {
5960
+ transform: scale(1.2) translateY(1px);
6043
5961
  }
6044
5962
 
6045
5963
  /* ========================================
6046
- RATING SCALE (generic)
5964
+ NUMBER RATING (segmented scale)
6047
5965
  ======================================== */
6048
5966
 
6049
- .feedback-survey-stars {
6050
- display: flex;
6051
- gap: var(--spacing-4);
6052
- justify-content: center;
6053
- }
6054
-
6055
- .feedback-survey-star-btn {
6056
- background: none;
6057
- border: none;
6058
- cursor: pointer;
6059
- font-size: 2.75rem;
6060
- color: var(--color-neutral-300);
6061
- padding: 0;
6062
- line-height: 1;
6063
- transition: color var(--transition-fast), transform var(--transition-fast);
6064
- }
6065
-
6066
- .feedback-survey-star-btn.filled,
6067
- .feedback-survey-star-btn.hovered {
6068
- color: #f59e0b;
6069
- }
6070
-
6071
- .feedback-survey-star-btn:active {
6072
- transform: scale(0.9);
6073
- }
6074
-
6075
5967
  .feedback-survey-rating-scale {
6076
5968
  display: flex;
6077
- gap: 0;
6078
- border: 1px solid var(--color-neutral-200);
6079
- border-radius: var(--radius-md);
6080
5969
  overflow: hidden;
5970
+ border: 1px solid var(--color-neutral-200);
5971
+ border-radius: 6px;
6081
5972
  background: var(--color-white);
6082
5973
  }
6083
5974
 
@@ -6092,9 +5983,9 @@
6092
5983
  cursor: pointer;
6093
5984
  font-size: clamp(14px, 3vw, 18px);
6094
5985
  font-weight: var(--font-weight-medium);
6095
- color: var(--color-text-primary);
5986
+ color: #374151;
6096
5987
  transition: background var(--transition-fast), color var(--transition-fast);
6097
- position: relative;
5988
+ font-family: inherit;
6098
5989
  }
6099
5990
 
6100
5991
  .feedback-survey-rating-scale-btn:last-child {
@@ -6118,59 +6009,59 @@
6118
6009
  box-shadow: inset 0 0 0 2px var(--color-primary);
6119
6010
  }
6120
6011
 
6121
- /* ========================================
6122
- SCALE LABELS
6123
- ======================================== */
6124
-
6125
- .feedback-survey-labels {
6126
- display: flex;
6127
- justify-content: space-between;
6128
- margin-top: var(--spacing-2);
6129
- font-size: var(--font-size-xs);
6130
- color: var(--color-text-tertiary);
6131
- }
6132
-
6133
- .feedback-survey-rating-scale + .feedback-survey-labels {
6134
- margin-top: var(--spacing-3);
6135
- padding: 0 var(--spacing-1);
6136
- font-size: var(--font-size-sm);
6137
- color: var(--color-text-tertiary);
6012
+ .feedback-survey-rating-scale-btn:active {
6013
+ transform: translateY(1px);
6014
+ transition-duration: 100ms;
6138
6015
  }
6139
6016
 
6140
6017
  /* ========================================
6141
- FREQUENCY
6018
+ STARS
6142
6019
  ======================================== */
6143
6020
 
6144
- .feedback-survey-frequency {
6021
+ .feedback-survey-stars {
6145
6022
  display: flex;
6146
6023
  gap: var(--spacing-2);
6024
+ justify-content: center;
6147
6025
  }
6148
6026
 
6149
- .feedback-survey-freq-btn {
6150
- flex: 1;
6151
- height: 40px;
6152
- padding: 0 var(--spacing-3);
6153
- border: 1px solid var(--color-border);
6154
- border-radius: var(--radius-md);
6155
- background: var(--color-surface);
6027
+ .feedback-survey-star-btn {
6028
+ background: none;
6029
+ border: none;
6156
6030
  cursor: pointer;
6157
- font-size: var(--font-size-sm);
6158
- font-weight: var(--font-weight-medium);
6159
- color: var(--color-text-primary);
6160
- transition: all var(--transition-fast);
6161
- font-family: inherit;
6031
+ padding: 0;
6032
+ line-height: 1;
6033
+ color: var(--color-neutral-300);
6034
+ transition: color var(--transition-fast), transform var(--transition-fast);
6035
+ display: flex;
6036
+ align-items: center;
6037
+ justify-content: center;
6162
6038
  }
6163
6039
 
6164
- .feedback-survey-freq-btn:hover {
6165
- background: var(--color-primary-light);
6166
- border-color: var(--color-primary-border);
6167
- color: var(--color-primary);
6040
+ .feedback-survey-star-btn.filled,
6041
+ .feedback-survey-star-btn.hovered {
6042
+ color: #f59e0b;
6168
6043
  }
6169
6044
 
6170
- .feedback-survey-freq-btn.selected {
6171
- background: var(--color-primary-light);
6172
- border-color: var(--color-primary);
6173
- color: var(--color-primary-active);
6045
+ .feedback-survey-star-btn:hover {
6046
+ color: #f59e0b;
6047
+ }
6048
+
6049
+ .feedback-survey-star-btn:active {
6050
+ transform: scale(0.9);
6051
+ transition-duration: 100ms;
6052
+ }
6053
+
6054
+ /* ========================================
6055
+ SCALE LABELS
6056
+ ======================================== */
6057
+
6058
+ .feedback-survey-labels {
6059
+ display: flex;
6060
+ justify-content: space-between;
6061
+ margin-top: var(--spacing-2);
6062
+ padding: 0 var(--spacing-1);
6063
+ font-size: var(--font-size-xs);
6064
+ color: var(--color-text-tertiary);
6174
6065
  }
6175
6066
 
6176
6067
  /* ========================================
@@ -6206,50 +6097,6 @@
6206
6097
  box-shadow: 0 0 0 3px var(--color-primary-light);
6207
6098
  }
6208
6099
 
6209
- .feedback-survey-select {
6210
- width: 100%;
6211
- height: 40px;
6212
- padding: 0 var(--spacing-3);
6213
- border: 1px solid var(--color-border);
6214
- border-radius: var(--radius-md);
6215
- font-size: var(--font-size-base);
6216
- background: var(--color-white);
6217
- color: var(--color-text-primary);
6218
- font-family: inherit;
6219
- cursor: pointer;
6220
- transition: border-color var(--transition-base);
6221
- outline: none;
6222
- }
6223
-
6224
- .feedback-survey-select:focus {
6225
- border-color: var(--color-primary);
6226
- box-shadow: 0 0 0 3px var(--color-primary-light);
6227
- }
6228
-
6229
- .feedback-survey-input {
6230
- width: 100%;
6231
- height: 40px;
6232
- padding: 0 var(--spacing-3);
6233
- border: 1px solid var(--color-border);
6234
- border-radius: var(--radius-md);
6235
- font-size: var(--font-size-base);
6236
- background: var(--color-white);
6237
- color: var(--color-text-primary);
6238
- font-family: inherit;
6239
- box-sizing: border-box;
6240
- transition: border-color var(--transition-base);
6241
- outline: none;
6242
- }
6243
-
6244
- .feedback-survey-input::placeholder {
6245
- color: var(--color-text-tertiary);
6246
- }
6247
-
6248
- .feedback-survey-input:focus {
6249
- border-color: var(--color-primary);
6250
- box-shadow: 0 0 0 3px var(--color-primary-light);
6251
- }
6252
-
6253
6100
  /* ========================================
6254
6101
  MULTI-PAGE TEXT INPUT
6255
6102
  ======================================== */
@@ -6260,7 +6107,7 @@
6260
6107
  padding: var(--spacing-3);
6261
6108
  border: 1px solid var(--color-border);
6262
6109
  border-radius: var(--radius-md);
6263
- font-size: var(--font-size-base);
6110
+ font-size: var(--font-size-sm);
6264
6111
  font-family: inherit;
6265
6112
  background: var(--color-white);
6266
6113
  color: var(--color-text-primary);
@@ -6293,12 +6140,12 @@
6293
6140
  width: 100%;
6294
6141
  height: 40px;
6295
6142
  padding: 0 var(--spacing-4);
6296
- border: 1px solid var(--color-border);
6143
+ border: 1px solid var(--color-neutral-200);
6297
6144
  border-radius: var(--radius-md);
6298
- background: var(--color-surface);
6299
- color: var(--color-text-primary);
6145
+ background: var(--color-white);
6146
+ color: #374151;
6300
6147
  text-align: left;
6301
- font-size: var(--font-size-base);
6148
+ font-size: var(--font-size-sm);
6302
6149
  font-weight: var(--font-weight-medium);
6303
6150
  cursor: pointer;
6304
6151
  font-family: inherit;
@@ -6308,33 +6155,41 @@
6308
6155
  transition: all var(--transition-fast);
6309
6156
  }
6310
6157
 
6158
+ .feedback-survey-page-choice-btn::after {
6159
+ content: '';
6160
+ width: 18px;
6161
+ height: 18px;
6162
+ border-radius: 50%;
6163
+ border: 1.5px solid #D1D5DB;
6164
+ flex-shrink: 0;
6165
+ background: transparent;
6166
+ transition: all var(--transition-fast);
6167
+ }
6168
+
6311
6169
  .feedback-survey-page-choice-btn:hover {
6170
+ border-color: var(--color-primary);
6312
6171
  background: var(--color-primary-light);
6313
- border-color: var(--color-primary-border);
6314
6172
  color: var(--color-primary);
6315
6173
  }
6316
6174
 
6317
- .feedback-survey-page-choice-btn.selected {
6318
- background: var(--color-primary-light);
6175
+ .feedback-survey-page-choice-btn:hover::after {
6319
6176
  border-color: var(--color-primary);
6320
- color: var(--color-primary-active);
6321
6177
  }
6322
6178
 
6323
- /* ========================================
6324
- LINK PAGE
6325
- ======================================== */
6326
-
6327
- .feedback-survey-link-page {
6328
- display: flex;
6329
- flex-direction: column;
6330
- gap: var(--spacing-3);
6179
+ .feedback-survey-page-choice-btn.selected {
6180
+ border-color: var(--color-primary);
6181
+ background: var(--color-primary-light);
6182
+ color: var(--color-primary-active);
6331
6183
  }
6332
6184
 
6333
- .feedback-survey-link-text {
6334
- font-size: var(--font-size-base);
6335
- color: var(--color-text-secondary);
6336
- line-height: var(--line-height-relaxed);
6337
- margin: 0;
6185
+ .feedback-survey-page-choice-btn.selected::after {
6186
+ border-color: var(--color-primary);
6187
+ background-color: var(--color-primary);
6188
+ }
6189
+
6190
+ .feedback-survey-page-choice-btn:active {
6191
+ transform: translateY(1px);
6192
+ transition-duration: 100ms;
6338
6193
  }
6339
6194
 
6340
6195
  /* ========================================
@@ -6353,9 +6208,9 @@
6353
6208
  min-height: 40px;
6354
6209
  border: 1px solid var(--color-border);
6355
6210
  border-radius: var(--radius-md);
6356
- background: var(--color-surface);
6211
+ background: var(--color-white);
6357
6212
  color: var(--color-text-secondary);
6358
- font-size: var(--font-size-base);
6213
+ font-size: var(--font-size-sm);
6359
6214
  font-weight: var(--font-weight-medium);
6360
6215
  cursor: pointer;
6361
6216
  font-family: inherit;
@@ -6374,8 +6229,13 @@
6374
6229
  color: var(--color-text-primary);
6375
6230
  }
6376
6231
 
6232
+ .feedback-survey-back:active {
6233
+ transform: translateY(1px);
6234
+ transition-duration: 100ms;
6235
+ }
6236
+
6377
6237
  /* ========================================
6378
- SUBMIT & LINK BUTTON
6238
+ SUBMIT BUTTON
6379
6239
  ======================================== */
6380
6240
 
6381
6241
  .feedback-survey-submit {
@@ -6390,7 +6250,7 @@
6390
6250
  color: #ffffff;
6391
6251
  border: 1px solid var(--color-primary);
6392
6252
  border-radius: var(--radius-md);
6393
- font-size: var(--font-size-base);
6253
+ font-size: var(--font-size-sm);
6394
6254
  font-weight: var(--font-weight-medium);
6395
6255
  cursor: pointer;
6396
6256
  font-family: inherit;
@@ -6408,43 +6268,14 @@
6408
6268
  cursor: not-allowed;
6409
6269
  }
6410
6270
 
6411
- .feedback-survey-link-btn {
6412
- display: flex;
6413
- align-items: center;
6414
- justify-content: center;
6415
- gap: var(--spacing-2);
6416
- width: 100%;
6417
- min-height: 40px;
6418
- padding: 0 var(--spacing-4);
6419
- background: var(--color-primary);
6420
- color: #ffffff;
6421
- border: 1px solid var(--color-primary);
6422
- border-radius: var(--radius-md);
6423
- font-size: var(--font-size-base);
6424
- font-weight: var(--font-weight-medium);
6425
- cursor: pointer;
6426
- font-family: inherit;
6427
- text-align: center;
6428
- text-decoration: none;
6429
- transition: all var(--transition-base);
6430
- }
6431
-
6432
- .feedback-survey-link-btn:hover {
6433
- background: var(--color-primary-hover);
6434
- border-color: var(--color-primary-hover);
6435
- color: var(--color-white);
6436
- text-decoration: none;
6437
- }
6438
-
6439
- .feedback-survey-link-btn iconify-icon,
6440
- .feedback-survey-submit iconify-icon {
6441
- flex-shrink: 0;
6442
- color: #ffffff;
6271
+ .feedback-survey-submit:active:not(:disabled) {
6272
+ transform: translateY(1px);
6273
+ transition-duration: 100ms;
6443
6274
  }
6444
6275
 
6276
+ .feedback-survey-submit iconify-icon,
6445
6277
  .feedback-survey-back iconify-icon {
6446
6278
  flex-shrink: 0;
6447
- color: currentColor;
6448
6279
  }
6449
6280
 
6450
6281
  /* ========================================
@@ -6469,47 +6300,64 @@
6469
6300
  }
6470
6301
 
6471
6302
  /* ========================================
6472
- DARK MODE — SELECTED STATE OVERRIDES
6303
+ THANK YOU SCREEN
6473
6304
  ======================================== */
6474
6305
 
6475
- .feedback-survey-theme-dark .feedback-survey-ces-list-btn.selected,
6476
- .feedback-survey-theme-dark .feedback-survey-page-choice-btn.selected,
6477
- .feedback-survey-theme-dark .feedback-survey-freq-btn.selected,
6478
- .feedback-survey-theme-dark .feedback-survey-ces-btn.selected,
6479
- .feedback-survey-theme-dark .feedback-survey-nps-btn.selected,
6480
- .feedback-survey-theme-dark .feedback-survey-rating-scale-btn.selected {
6481
- color: var(--color-text-primary);
6306
+ .feedback-survey-thankyou {
6307
+ display: flex;
6308
+ flex-direction: column;
6309
+ align-items: center;
6310
+ text-align: center;
6311
+ padding: var(--spacing-6) 0;
6482
6312
  }
6483
6313
 
6484
- /* ========================================
6485
- PRESS EFFECT
6486
- ======================================== */
6314
+ .feedback-survey-thankyou-icon {
6315
+ color: #10b981;
6316
+ margin-bottom: var(--spacing-4);
6317
+ display: block;
6318
+ }
6487
6319
 
6488
- .feedback-survey-close:active,
6489
- .feedback-survey-submit:active,
6490
- .feedback-survey-back:active,
6491
- .feedback-survey-link-btn:active,
6492
- .feedback-survey-ces-btn:active,
6493
- .feedback-survey-ces-list-btn:active,
6494
- .feedback-survey-page-choice-btn:active,
6495
- .feedback-survey-freq-btn:active,
6496
- .feedback-survey-rating-scale-btn:active,
6497
- .feedback-survey-nps-btn:active {
6498
- transform: translateY(1px);
6499
- transition-duration: 100ms;
6320
+ .feedback-survey-thankyou-title {
6321
+ margin: 0;
6322
+ font-size: var(--font-size-xl);
6323
+ font-weight: var(--font-weight-semibold);
6324
+ line-height: var(--line-height-snug);
6325
+ color: var(--color-text-primary);
6500
6326
  }
6501
6327
 
6502
- .feedback-survey-nps-btn.selected:active {
6503
- transform: scale(1.06) translateY(1px);
6328
+ .feedback-survey-thankyou-btn {
6329
+ margin-top: var(--spacing-5);
6330
+ display: inline-flex;
6331
+ align-items: center;
6332
+ justify-content: center;
6333
+ gap: var(--spacing-2);
6334
+ height: 40px;
6335
+ padding: 0 var(--spacing-6);
6336
+ background: var(--color-primary);
6337
+ color: #ffffff;
6338
+ border: 1px solid var(--color-primary);
6339
+ border-radius: var(--radius-md);
6340
+ font-size: var(--font-size-sm);
6341
+ font-weight: var(--font-weight-medium);
6342
+ text-decoration: none;
6343
+ transition: all var(--transition-base);
6504
6344
  }
6505
6345
 
6506
- .feedback-survey-csat-btn:active {
6507
- transform: scale(1.05) translateY(1px);
6508
- transition-duration: 100ms;
6346
+ .feedback-survey-thankyou-btn:hover {
6347
+ background: var(--color-primary-hover);
6348
+ border-color: var(--color-primary-hover);
6349
+ color: #ffffff;
6350
+ text-decoration: none;
6509
6351
  }
6510
6352
 
6511
- .feedback-survey-csat-btn.selected:active {
6512
- transform: scale(1.2) translateY(1px);
6353
+ /* ========================================
6354
+ DARK MODE — SELECTED STATE OVERRIDES
6355
+ ======================================== */
6356
+
6357
+ .feedback-survey-theme-dark .feedback-survey-page-choice-btn.selected,
6358
+ .feedback-survey-theme-dark .feedback-survey-rating-scale-btn.selected,
6359
+ .feedback-survey-theme-dark .feedback-survey-nps-btn.selected {
6360
+ color: var(--color-text-primary);
6513
6361
  }
6514
6362
 
6515
6363
  /* ========================================
@@ -6542,22 +6390,10 @@
6542
6390
  flex-shrink: 0;
6543
6391
  }
6544
6392
 
6545
- .product7-notification-success {
6546
- background: #037F0C;
6547
- }
6548
-
6549
- .product7-notification-error {
6550
- background: #D13212;
6551
- }
6552
-
6553
- .product7-notification-warning {
6554
- background: #FF9900;
6555
- color: #000;
6556
- }
6557
-
6558
- .product7-notification-info {
6559
- background: #0972D3;
6560
- }
6393
+ .product7-notification-success { background: #037F0C; }
6394
+ .product7-notification-error { background: #D13212; }
6395
+ .product7-notification-warning { background: #FF9900; color: #000; }
6396
+ .product7-notification-info { background: #0972D3; }
6561
6397
 
6562
6398
  /* ========================================
6563
6399
  RESPONSIVE
@@ -6569,7 +6405,7 @@
6569
6405
  padding: var(--spacing-5);
6570
6406
  }
6571
6407
 
6572
- .feedback-survey-nps-btn {
6408
+ .feedback-survey-nps-btn {
6573
6409
  font-size: var(--font-size-xs);
6574
6410
  }
6575
6411
 
@@ -6590,10 +6426,6 @@
6590
6426
  .feedback-survey-rating-scale-btn {
6591
6427
  font-size: clamp(13px, 5vw, 16px);
6592
6428
  }
6593
-
6594
- .feedback-survey-rating-scale + .feedback-survey-labels {
6595
- font-size: var(--font-size-xs);
6596
- }
6597
6429
  }
6598
6430
  `;
6599
6431
 
@@ -8255,152 +8087,9 @@
8255
8087
 
8256
8088
  setPlaceholder(field, placeholder) {
8257
8089
  const input = this.element?.querySelector(`[name="${field}"]`);
8258
- if (input) {
8259
- input.placeholder = placeholder;
8260
- }
8261
- }
8262
- }
8263
-
8264
- var BUNDLED_SOUND = "data:audio/mpeg;base64,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BeaJKOtqtegdfu08KKta9TmppaKVKbNRgAAdr/tXGB6CSCPl1Lelt7XW7T01ifVk2zjE1bLW839346gs//uAZPGAAtMh2Hn4GlhT52rfPeJdDAirVe28aaE2Dmr9tY0siLho4mUCDpWMFgQGgu42pLnLawWb/bpWNprQxluj9TNaXJSgOIMS1KzM0TRIAAAABFakEh3cgBQEGVwwSAstoCBiYpGhkVAplAwJmPAkYLCBkEDgYHpEhgdJRk+AeYkqaA6eReiyrxNIvmnxxStER14EjE2/9hljaO2siCoAhzKnpuRt269O0veD7Pq/uNbdzt6jfydzch/Kkpf1/dcqV6ta/y3Y1MWIft8iMqtZzUahrWPO71nqvG43fsROXu5Y3KZJGnRZbEH1clnOWX//OZ/+2WTnxeAH4ZfTSxQdl7ovLbXkoM0tW5UzXqqe3b9bPWP/+H7q59vrHa/P1WVuvIHDdeijc/LKqG114l3Joq5VSQSsRUcUBhEnmWs49v5f///////////////y/mff///////////////3Ad21LEZyZxNSU0SUaZb/+8Bk6AADBiBVfWGgCEbieq+nmAEjzhFJ+cyQBEdCKT85gkCgwCAAAAA6AP0AywXlGoy0hpYVBKCMGkNVAtKWyXWFQkQg10C3jJ4dCWsMS6ezji0j3yF6W6MVa5lLJbaXvIFSNMi8Vdp4aejr0kYgJ/IpLXJpq0lmN4S38scPty+3K4brc1En1pL+vzx/k/bwt3IYllNldscl0R/HlzH9/zJ2IEd+3kzt34vWlVWVWqbn5Z/njz8O/+aXAXCHDZovNNc0AZypebBMlXypavJwV2u4yFL1vG4qA//93+9d/ff/Fg5dCKWEFHZcd41TwOim499QNk7qNZnHhm2uvA4NA5XIelTssq//5////////////////KFL24Op////////////////I3ifN9VM55RBBXv+tQAA8aAYzpLaSOxTi1EgJ6SJFPyUphVqcwGS1LvW/Hx+27zX1/f7Y2w5rdPTwuJkLERYGnMZHg0LksCgqGoKvEWkqYTKtOnRLvoGgFPadXgqdiKxbu2ws92sNCIOHN0xkAtG+saAAuK4rNZxyl0v8x2rfuXaCm7ruwZLSEFAQkKru7B2WMZy0qeUZjNZr5eXDP+8VVSOR/5cly6S3120bi5SXY5P/1/U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";
8265
-
8266
- /**
8267
- * NotificationSound — plays a soft ping when a new agent message arrives.
8268
- *
8269
- * Default: the bundled notification-sound.mp3 (inlined as base64 at build time).
8270
- * Falls back to a Web Audio API synthetic chime if the file was not bundled.
8271
- * Override: pass `soundUrl` (MP3/OGG/WAV URL or base64 data URI) to use a different file.
8272
- */
8273
-
8274
- class NotificationSound {
8275
- constructor({ soundUrl = BUNDLED_SOUND, volume = 0.4 } = {}) {
8276
- this._soundUrl = soundUrl;
8277
- this._volume = Math.min(1, Math.max(0, volume));
8278
- this._enabled = true;
8279
- this._audioCtx = null;
8280
- this._audioBuffer = null;
8281
- this._loadPromise = null;
8282
-
8283
- if (soundUrl) {
8284
- this._loadPromise = this._loadAudioFile(soundUrl);
8285
- }
8286
- }
8287
-
8288
- setEnabled(enabled) {
8289
- this._enabled = Boolean(enabled);
8290
- }
8291
-
8292
- setVolume(volume) {
8293
- this._volume = Math.min(1, Math.max(0, volume));
8294
- }
8295
-
8296
- async play() {
8297
- if (!this._enabled) return;
8298
- if (typeof window === 'undefined') return;
8299
-
8300
- try {
8301
- if (this._soundUrl) {
8302
- await this._playFile();
8303
- } else {
8304
- this._playSynthetic();
8305
- }
8306
- } catch {
8307
- /* autoplay policy or context suspended — silent fail */
8308
- }
8309
- }
8310
-
8311
- // ── Private ────────────────────────────────────────────────────────────────
8312
-
8313
- _getAudioContext() {
8314
- if (!this._audioCtx || this._audioCtx.state === 'closed') {
8315
- const AudioContext = window.AudioContext || window.webkitAudioContext;
8316
- if (!AudioContext) return null;
8317
- this._audioCtx = new AudioContext();
8318
- }
8319
- return this._audioCtx;
8320
- }
8321
-
8322
- /**
8323
- * Synthetic two-tone chime via Web Audio API — no file required.
8324
- * • First tone: 880 Hz, 0–80 ms
8325
- * • Second tone: 1100 Hz, 60–160 ms
8326
- * Sounds like a gentle message ping.
8327
- */
8328
- _playSynthetic() {
8329
- const ctx = this._getAudioContext();
8330
- if (!ctx) return;
8331
-
8332
- if (ctx.state === 'suspended') {
8333
- ctx.resume().catch(() => {});
8334
- }
8335
-
8336
- const now = ctx.currentTime;
8337
- const vol = this._volume;
8338
-
8339
- const tones = [
8340
- { freq: 880, start: 0, end: 0.08 },
8341
- { freq: 1100, start: 0.06, end: 0.16 },
8342
- ];
8343
-
8344
- tones.forEach(({ freq, start, end }) => {
8345
- const osc = ctx.createOscillator();
8346
- const gain = ctx.createGain();
8347
-
8348
- osc.type = 'sine';
8349
- osc.frequency.value = freq;
8350
-
8351
- gain.gain.setValueAtTime(0, now + start);
8352
- gain.gain.linearRampToValueAtTime(vol, now + start + 0.01);
8353
- gain.gain.linearRampToValueAtTime(0, now + end);
8354
-
8355
- osc.connect(gain);
8356
- gain.connect(ctx.destination);
8357
-
8358
- osc.start(now + start);
8359
- osc.stop(now + end + 0.01);
8360
- });
8361
- }
8362
-
8363
- async _loadAudioFile(url) {
8364
- try {
8365
- const ctx = this._getAudioContext();
8366
- if (!ctx) return;
8367
-
8368
- const response = await fetch(url);
8369
- const arrayBuffer = await response.arrayBuffer();
8370
- this._audioBuffer = await ctx.decodeAudioData(arrayBuffer);
8371
- } catch {
8372
- /* failed to load — fall back to synthetic */
8373
- this._soundUrl = null;
8374
- }
8375
- }
8376
-
8377
- async _playFile() {
8378
- if (this._loadPromise) {
8379
- await this._loadPromise;
8380
- this._loadPromise = null;
8381
- }
8382
-
8383
- if (!this._audioBuffer) {
8384
- this._playSynthetic();
8385
- return;
8386
- }
8387
-
8388
- const ctx = this._getAudioContext();
8389
- if (!ctx) return;
8390
-
8391
- if (ctx.state === 'suspended') {
8392
- await ctx.resume();
8393
- }
8394
-
8395
- const source = ctx.createBufferSource();
8396
- const gain = ctx.createGain();
8397
-
8398
- source.buffer = this._audioBuffer;
8399
- gain.gain.value = this._volume;
8400
-
8401
- source.connect(gain);
8402
- gain.connect(ctx.destination);
8403
- source.start();
8090
+ if (input) {
8091
+ input.placeholder = placeholder;
8092
+ }
8404
8093
  }
8405
8094
  }
8406
8095
 
@@ -8795,6 +8484,149 @@
8795
8484
  }
8796
8485
  }
8797
8486
 
8487
+ var BUNDLED_SOUND = "data:audio/mpeg;base64,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BeaJKOtqtegdfu08KKta9TmppaKVKbNRgAAdr/tXGB6CSCPl1Lelt7XW7T01ifVk2zjE1bLW839346gs//uAZPGAAtMh2Hn4GlhT52rfPeJdDAirVe28aaE2Dmr9tY0siLho4mUCDpWMFgQGgu42pLnLawWb/bpWNprQxluj9TNaXJSgOIMS1KzM0TRIAAAABFakEh3cgBQEGVwwSAstoCBiYpGhkVAplAwJmPAkYLCBkEDgYHpEhgdJRk+AeYkqaA6eReiyrxNIvmnxxStER14EjE2/9hljaO2siCoAhzKnpuRt269O0veD7Pq/uNbdzt6jfydzch/Kkpf1/dcqV6ta/y3Y1MWIft8iMqtZzUahrWPO71nqvG43fsROXu5Y3KZJGnRZbEH1clnOWX//OZ/+2WTnxeAH4ZfTSxQdl7ovLbXkoM0tW5UzXqqe3b9bPWP/+H7q59vrHa/P1WVuvIHDdeijc/LKqG114l3Joq5VSQSsRUcUBhEnmWs49v5f///////////////y/mff///////////////3Ad21LEZyZxNSU0SUaZb/+8Bk6AADBiBVfWGgCEbieq+nmAEjzhFJ+cyQBEdCKT85gkCgwCAAAAA6AP0AywXlGoy0hpYVBKCMGkNVAtKWyXWFQkQg10C3jJ4dCWsMS6ezji0j3yF6W6MVa5lLJbaXvIFSNMi8Vdp4aejr0kYgJ/IpLXJpq0lmN4S38scPty+3K4brc1En1pL+vzx/k/bwt3IYllNldscl0R/HlzH9/zJ2IEd+3kzt34vWlVWVWqbn5Z/njz8O/+aXAXCHDZovNNc0AZypebBMlXypavJwV2u4yFL1vG4qA//93+9d/ff/Fg5dCKWEFHZcd41TwOim499QNk7qNZnHhm2uvA4NA5XIelTssq//5////////////////KFL24Op////////////////I3ifN9VM55RBBXv+tQAA8aAYzpLaSOxTi1EgJ6SJFPyUphVqcwGS1LvW/Hx+27zX1/f7Y2w5rdPTwuJkLERYGnMZHg0LksCgqGoKvEWkqYTKtOnRLvoGgFPadXgqdiKxbu2ws92sNCIOHN0xkAtG+saAAuK4rNZxyl0v8x2rfuXaCm7ruwZLSEFAQkKru7B2WMZy0qeUZjNZr5eXDP+8VVSOR/5cly6S3120bi5SXY5P/1/U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";
8488
+
8489
+ /**
8490
+ * NotificationSound — plays a soft ping when a new agent message arrives.
8491
+ *
8492
+ * Default: the bundled notification-sound.mp3 (inlined as base64 at build time).
8493
+ * Falls back to a Web Audio API synthetic chime if the file was not bundled.
8494
+ * Override: pass `soundUrl` (MP3/OGG/WAV URL or base64 data URI) to use a different file.
8495
+ */
8496
+
8497
+ class NotificationSound {
8498
+ constructor({ soundUrl = BUNDLED_SOUND, volume = 0.4 } = {}) {
8499
+ this._soundUrl = soundUrl;
8500
+ this._volume = Math.min(1, Math.max(0, volume));
8501
+ this._enabled = true;
8502
+ this._audioCtx = null;
8503
+ this._audioBuffer = null;
8504
+ this._loadPromise = null;
8505
+
8506
+ if (soundUrl) {
8507
+ this._loadPromise = this._loadAudioFile(soundUrl);
8508
+ }
8509
+ }
8510
+
8511
+ setEnabled(enabled) {
8512
+ this._enabled = Boolean(enabled);
8513
+ }
8514
+
8515
+ setVolume(volume) {
8516
+ this._volume = Math.min(1, Math.max(0, volume));
8517
+ }
8518
+
8519
+ async play() {
8520
+ if (!this._enabled) return;
8521
+ if (typeof window === 'undefined') return;
8522
+
8523
+ try {
8524
+ if (this._soundUrl) {
8525
+ await this._playFile();
8526
+ } else {
8527
+ await this._playSynthetic();
8528
+ }
8529
+ } catch {
8530
+ /* autoplay policy or context suspended — silent fail */
8531
+ }
8532
+ }
8533
+
8534
+ // ── Private ────────────────────────────────────────────────────────────────
8535
+
8536
+ _getAudioContext() {
8537
+ if (!this._audioCtx || this._audioCtx.state === 'closed') {
8538
+ const AudioContext = window.AudioContext || window.webkitAudioContext;
8539
+ if (!AudioContext) return null;
8540
+ this._audioCtx = new AudioContext();
8541
+ }
8542
+ return this._audioCtx;
8543
+ }
8544
+
8545
+ /**
8546
+ * Synthetic two-tone chime via Web Audio API — no file required.
8547
+ * • First tone: 880 Hz, 0–80 ms
8548
+ * • Second tone: 1100 Hz, 60–160 ms
8549
+ * Sounds like a gentle message ping.
8550
+ */
8551
+ async _playSynthetic() {
8552
+ const ctx = this._getAudioContext();
8553
+ if (!ctx) return;
8554
+
8555
+ if (ctx.state === 'suspended') {
8556
+ await ctx.resume();
8557
+ }
8558
+
8559
+ const now = ctx.currentTime;
8560
+ const vol = this._volume;
8561
+
8562
+ const tones = [
8563
+ { freq: 880, start: 0, end: 0.08 },
8564
+ { freq: 1100, start: 0.06, end: 0.16 },
8565
+ ];
8566
+
8567
+ tones.forEach(({ freq, start, end }) => {
8568
+ const osc = ctx.createOscillator();
8569
+ const gain = ctx.createGain();
8570
+
8571
+ osc.type = 'sine';
8572
+ osc.frequency.value = freq;
8573
+
8574
+ gain.gain.setValueAtTime(0, now + start);
8575
+ gain.gain.linearRampToValueAtTime(vol, now + start + 0.01);
8576
+ gain.gain.linearRampToValueAtTime(0, now + end);
8577
+
8578
+ osc.connect(gain);
8579
+ gain.connect(ctx.destination);
8580
+
8581
+ osc.start(now + start);
8582
+ osc.stop(now + end + 0.01);
8583
+ });
8584
+ }
8585
+
8586
+ async _loadAudioFile(url) {
8587
+ try {
8588
+ const ctx = this._getAudioContext();
8589
+ if (!ctx) return;
8590
+
8591
+ const response = await fetch(url);
8592
+ const arrayBuffer = await response.arrayBuffer();
8593
+ this._audioBuffer = await ctx.decodeAudioData(arrayBuffer);
8594
+ } catch {
8595
+ /* failed to load — fall back to synthetic */
8596
+ this._soundUrl = null;
8597
+ }
8598
+ }
8599
+
8600
+ async _playFile() {
8601
+ if (this._loadPromise) {
8602
+ await this._loadPromise;
8603
+ this._loadPromise = null;
8604
+ }
8605
+
8606
+ if (!this._audioBuffer) {
8607
+ this._playSynthetic();
8608
+ return;
8609
+ }
8610
+
8611
+ const ctx = this._getAudioContext();
8612
+ if (!ctx) return;
8613
+
8614
+ if (ctx.state === 'suspended') {
8615
+ await ctx.resume();
8616
+ }
8617
+
8618
+ const source = ctx.createBufferSource();
8619
+ const gain = ctx.createGain();
8620
+
8621
+ source.buffer = this._audioBuffer;
8622
+ gain.gain.value = this._volume;
8623
+
8624
+ source.connect(gain);
8625
+ gain.connect(ctx.destination);
8626
+ source.start();
8627
+ }
8628
+ }
8629
+
8798
8630
  class MessengerState {
8799
8631
  constructor(options = {}) {
8800
8632
  this.currentView = 'home';
@@ -11524,12 +11356,16 @@
11524
11356
  this._wsUnsubscribers = [];
11525
11357
  this._feedbackWidget = null;
11526
11358
 
11527
- const notificationSoundOption = options.notificationSound !== undefined
11528
- ? options.notificationSound
11529
- : true;
11359
+ const notificationSoundOption =
11360
+ options.notificationSound !== undefined
11361
+ ? options.notificationSound
11362
+ : true;
11530
11363
 
11531
11364
  this._notificationSound = new NotificationSound({
11532
- soundUrl: typeof notificationSoundOption === 'string' ? notificationSoundOption : null,
11365
+ soundUrl:
11366
+ typeof notificationSoundOption === 'string'
11367
+ ? notificationSoundOption
11368
+ : undefined,
11533
11369
  volume: options.notificationVolume ?? 0.4,
11534
11370
  });
11535
11371
 
@@ -11863,14 +11699,8 @@
11863
11699
 
11864
11700
  const isOwnMessage = message.sender_type === 'customer';
11865
11701
 
11866
- if (!isOwnMessage) {
11867
- const panelOpenOnThisConversation =
11868
- this.messengerState.isOpen &&
11869
- this.messengerState.activeConversationId === conversation_id;
11870
-
11871
- if (!panelOpenOnThisConversation) {
11872
- this._notificationSound.play();
11873
- }
11702
+ if (!isOwnMessage && this.messengerState.isIdentified) {
11703
+ this._notificationSound.play();
11874
11704
  }
11875
11705
 
11876
11706
  if (
@@ -12544,6 +12374,8 @@
12544
12374
  : null,
12545
12375
  customQuestions: options.customQuestions || [],
12546
12376
  pages: Array.isArray(options.pages) ? options.pages : [],
12377
+ thankYouConfig:
12378
+ options.thankYouConfig || options.thank_you_config || null,
12547
12379
  respondentId: options.respondentId || null,
12548
12380
  email: options.email || null,
12549
12381
  onSubmit: options.onSubmit || null,
@@ -12872,10 +12704,6 @@
12872
12704
 
12873
12705
  _shouldShowActions() {
12874
12706
  if (this._isMultiPageSurvey()) {
12875
- const page = this._getCurrentPage();
12876
- if (page && page.type === 'link') {
12877
- return false;
12878
- }
12879
12707
  return true;
12880
12708
  }
12881
12709
  if (typeof this.surveyOptions.showSubmitButton === 'boolean') {
@@ -12924,8 +12752,6 @@
12924
12752
  return this._renderMultipleChoicePage(page);
12925
12753
  case 'text':
12926
12754
  return this._renderTextPage(page);
12927
- case 'link':
12928
- return this._renderLinkPage(page);
12929
12755
  default:
12930
12756
  return '';
12931
12757
  }
@@ -12933,62 +12759,36 @@
12933
12759
 
12934
12760
  _renderRatingPage(page) {
12935
12761
  const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
12936
- const config = page.ratingConfig || page.rating_config || {};
12762
+ const config = page.rating_config || page.ratingConfig || {};
12937
12763
  const scale = Number(config.scale) || 5;
12938
- const topSurveyType = this.surveyOptions.surveyType;
12939
- const configType = config.survey_type;
12940
- let ratingType;
12941
- if (topSurveyType === 'nps') {
12942
- ratingType = 'nps';
12943
- } else if (configType) {
12944
- ratingType = configType;
12945
- } else if (topSurveyType === 'ces') {
12946
- ratingType = 'ces';
12947
- } else if (topSurveyType === 'csat') {
12948
- ratingType = 'emoji';
12949
- } else {
12950
- ratingType = topSurveyType || 'csat';
12951
- }
12764
+ const ratingType = config.survey_type || 'number';
12952
12765
  const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
12953
12766
  const currentRating = pageAnswer.rating;
12954
- const defaultLowLabel =
12955
- ratingType === 'nps'
12956
- ? scale === 11
12957
- ? 'Not likely'
12958
- : 'Strongly Disagree'
12959
- : '';
12960
- const defaultHighLabel =
12961
- ratingType === 'nps'
12962
- ? scale === 11
12963
- ? 'Very likely'
12964
- : 'Strongly Agree'
12965
- : '';
12966
- const lowLabel =
12967
- config.low_label || this.surveyOptions.lowLabel || defaultLowLabel;
12968
- const highLabel =
12969
- config.high_label || this.surveyOptions.highLabel || defaultHighLabel;
12767
+
12768
+ const labelDefaults = {
12769
+ nps:
12770
+ scale === 11
12771
+ ? ['Not likely', 'Very likely']
12772
+ : ['Strongly Disagree', 'Strongly Agree'],
12773
+ emoji: ['Very dissatisfied', 'Very satisfied'],
12774
+ number: ['Poor', 'Excellent'],
12775
+ star: ['Poor', 'Excellent'],
12776
+ };
12777
+ const [defaultLow, defaultHigh] = labelDefaults[ratingType] || ['', ''];
12778
+ const lowLabel = config.low_label || defaultLow;
12779
+ const highLabel = config.high_label || defaultHigh;
12970
12780
  const labels = this._renderScaleLabels(lowLabel, highLabel);
12971
12781
 
12972
12782
  if (ratingType === 'nps') {
12973
- const npsScale = Number.isFinite(scale) && scale >= 2 ? scale : 5;
12783
+ const npsScale = Number.isFinite(scale) && scale >= 2 ? scale : 11;
12974
12784
  const start = npsScale === 11 ? 0 : 1;
12975
- const values = Array.from(
12976
- { length: npsScale },
12977
- (_, index) => start + index
12978
- );
12979
- const usesSegmentedScale = values.length <= 7;
12980
- const containerClass = usesSegmentedScale
12981
- ? 'feedback-survey-ces feedback-survey-rating-scale'
12982
- : 'feedback-survey-nps';
12983
- const buttonClass = usesSegmentedScale
12984
- ? 'feedback-survey-page-rating-btn feedback-survey-nps-btn feedback-survey-ces-btn feedback-survey-rating-scale-btn'
12985
- : 'feedback-survey-page-rating-btn feedback-survey-nps-btn';
12785
+ const values = Array.from({ length: npsScale }, (_, i) => start + i);
12986
12786
  return `
12987
- <div class="${containerClass}" data-page-id="${pageId}">
12787
+ <div class="feedback-survey-nps" data-page-id="${pageId}">
12988
12788
  ${values
12989
12789
  .map((n) => {
12990
12790
  const selected = currentRating === n ? ' selected' : '';
12991
- return `<button class="${buttonClass}${selected}" data-page-id="${pageId}" data-score="${n}">${n}</button>`;
12791
+ return `<button class="feedback-survey-page-rating-btn feedback-survey-nps-btn feedback-survey-nps-score-${n}${selected}" data-page-id="${pageId}" data-score="${n}">${n}</button>`;
12992
12792
  })
12993
12793
  .join('')}
12994
12794
  </div>
@@ -12996,28 +12796,7 @@
12996
12796
  `;
12997
12797
  }
12998
12798
 
12999
- if (ratingType === 'ces') {
13000
- const cesLabels = [
13001
- 'Very Difficult',
13002
- 'Difficult',
13003
- 'Neutral',
13004
- 'Easy',
13005
- 'Very Easy',
13006
- ];
13007
- return `
13008
- <div class="feedback-survey-ces-list" data-page-id="${pageId}">
13009
- ${cesLabels
13010
- .map((label, i) => {
13011
- const score = i + 1;
13012
- const selected = currentRating === score ? ' selected' : '';
13013
- return `<button class="feedback-survey-page-rating-btn feedback-survey-ces-list-btn${selected}" data-page-id="${pageId}" data-score="${score}">${label}</button>`;
13014
- })
13015
- .join('')}
13016
- </div>
13017
- `;
13018
- }
13019
-
13020
- if (ratingType === 'emoji' && scale === 5) {
12799
+ if (ratingType === 'emoji') {
13021
12800
  const emojis = [
13022
12801
  '\uD83D\uDE1E',
13023
12802
  '\uD83D\uDE15',
@@ -13025,9 +12804,12 @@
13025
12804
  '\uD83D\uDE42',
13026
12805
  '\uD83D\uDE04',
13027
12806
  ];
12807
+ const emojiScale =
12808
+ Number.isFinite(scale) && scale >= 2 ? Math.min(scale, 5) : 5;
13028
12809
  return `
13029
12810
  <div class="feedback-survey-csat" data-page-id="${pageId}">
13030
12811
  ${emojis
12812
+ .slice(0, emojiScale)
13031
12813
  .map((emoji, i) => {
13032
12814
  const score = i + 1;
13033
12815
  const selected = currentRating === score ? ' selected' : '';
@@ -13043,27 +12825,27 @@
13043
12825
  const starScale = Number.isFinite(scale) && scale >= 2 ? scale : 5;
13044
12826
  return `
13045
12827
  <div class="feedback-survey-stars" data-page-id="${pageId}">
13046
- ${[...Array(starScale).keys()]
13047
- .map((i) => {
13048
- const score = i + 1;
13049
- const filled = currentRating >= score ? ' filled' : '';
13050
- return `<button class="feedback-survey-page-rating-btn feedback-survey-star-btn${filled}" data-page-id="${pageId}" data-score="${score}">★</button>`;
13051
- })
13052
- .join('')}
12828
+ ${Array.from({ length: starScale }, (_, i) => {
12829
+ const score = i + 1;
12830
+ const filled =
12831
+ typeof currentRating === 'number' && currentRating >= score
12832
+ ? ' filled'
12833
+ : '';
12834
+ return `<button class="feedback-survey-page-rating-btn feedback-survey-star-btn${filled}" data-page-id="${pageId}" data-score="${score}"><iconify-icon icon="ph:star-duotone" width="32" height="32" style="pointer-events:none;"></iconify-icon></button>`;
12835
+ }).join('')}
13053
12836
  </div>
13054
12837
  ${labels}
13055
12838
  `;
13056
12839
  }
13057
12840
 
12841
+ const numScale = Number.isFinite(scale) && scale >= 2 ? scale : 5;
13058
12842
  return `
13059
12843
  <div class="feedback-survey-rating-scale" data-page-id="${pageId}">
13060
- ${[...Array(scale).keys()]
13061
- .map((i) => {
13062
- const score = i + 1;
13063
- const selected = currentRating === score ? ' selected' : '';
13064
- return `<button class="feedback-survey-page-rating-btn feedback-survey-rating-scale-btn${selected}" data-page-id="${pageId}" data-score="${score}">${score}</button>`;
13065
- })
13066
- .join('')}
12844
+ ${Array.from({ length: numScale }, (_, i) => {
12845
+ const score = i + 1;
12846
+ const selected = currentRating === score ? ' selected' : '';
12847
+ return `<button class="feedback-survey-page-rating-btn feedback-survey-rating-scale-btn${selected}" data-page-id="${pageId}" data-score="${score}">${score}</button>`;
12848
+ }).join('')}
13067
12849
  </div>
13068
12850
  ${labels}
13069
12851
  `;
@@ -13113,32 +12895,6 @@
13113
12895
  `;
13114
12896
  }
13115
12897
 
13116
- _renderLinkPage(page) {
13117
- const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
13118
- const config = page.link_config || page.linkConfig || {};
13119
- const buttonText = config.button_text || config.buttonText || 'Click here';
13120
- const linkText = config.link_text || config.linkText || '';
13121
- const redirectUrl = config.redirect_url || config.redirectUrl || '#';
13122
- const openIn = config.open_in || config.openIn || 'new_tab';
13123
- const target = openIn === 'new_tab' ? '_blank' : '_self';
13124
- const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
13125
- const clicked = pageAnswer.clicked === true;
13126
-
13127
- const iconExternalLink = `<iconify-icon icon="ph:arrow-square-out-duotone" width="15" height="15"></iconify-icon>`;
13128
- return `
13129
- <div class="feedback-survey-link-page" data-page-id="${pageId}">
13130
- ${linkText ? `<p class="feedback-survey-link-text">${linkText}</p>` : ''}
13131
- <a class="feedback-survey-link-btn${clicked ? ' selected' : ''}"
13132
- href="${redirectUrl}"
13133
- target="${target}"
13134
- rel="noopener noreferrer"
13135
- data-page-id="${pageId}">
13136
- ${buttonText} ${iconExternalLink}
13137
- </a>
13138
- </div>
13139
- `;
13140
- }
13141
-
13142
12898
  _renderCustomQuestions() {
13143
12899
  if (
13144
12900
  !this.surveyOptions.customQuestions ||
@@ -13421,24 +13177,6 @@
13421
13177
  });
13422
13178
  }
13423
13179
  }
13424
-
13425
- if (page.type === 'link') {
13426
- this.surveyElement
13427
- .querySelectorAll('.feedback-survey-link-btn')
13428
- .forEach((btn) => {
13429
- btn.addEventListener('click', () => {
13430
- const pId = btn.dataset.pageId;
13431
- this._setPageAnswer(pId, { clicked: true });
13432
- btn.classList.add('selected');
13433
-
13434
- const navigation = page.afterThisPage || page.after_this_page;
13435
- const goesTo = navigation ? navigation.default : null;
13436
- if (!goesTo || goesTo === 'end_survey') {
13437
- setTimeout(() => this._handleSubmit(), 400);
13438
- }
13439
- });
13440
- });
13441
- }
13442
13180
  }
13443
13181
 
13444
13182
  _selectNPS(score) {
@@ -13447,11 +13185,7 @@
13447
13185
  .querySelectorAll('.feedback-survey-nps-btn')
13448
13186
  .forEach((btn) => {
13449
13187
  const btnScore = parseInt(btn.dataset.score);
13450
- if (btnScore === score) {
13451
- btn.classList.add('selected');
13452
- } else {
13453
- btn.classList.remove('selected');
13454
- }
13188
+ btn.classList.toggle('selected', btnScore === score);
13455
13189
  });
13456
13190
  this._maybeAutoSubmit();
13457
13191
  }
@@ -13462,50 +13196,16 @@
13462
13196
  .querySelectorAll('.feedback-survey-csat-btn')
13463
13197
  .forEach((btn) => {
13464
13198
  const btnScore = parseInt(btn.dataset.score);
13465
- if (btnScore === score) {
13466
- btn.classList.add('selected');
13467
- } else {
13468
- btn.classList.remove('selected');
13469
- }
13470
- });
13471
- this._maybeAutoSubmit();
13472
- }
13473
-
13474
- _selectCES(score) {
13475
- this.surveyState.score = score;
13476
- this.surveyElement
13477
- .querySelectorAll('.feedback-survey-ces-btn')
13478
- .forEach((btn) => {
13479
- const btnScore = parseInt(btn.dataset.score);
13480
- if (btnScore === score) {
13481
- btn.classList.add('selected');
13482
- } else {
13483
- btn.classList.remove('selected');
13484
- }
13199
+ btn.classList.toggle('selected', btnScore === score);
13485
13200
  });
13486
13201
  this._maybeAutoSubmit();
13487
13202
  }
13488
13203
 
13489
13204
  _maybeAutoSubmit() {
13490
- if (!this._shouldAutoSubmitOnSelect()) {
13491
- return;
13492
- }
13205
+ if (!this._shouldAutoSubmitOnSelect()) return;
13493
13206
  this._handleSubmit();
13494
13207
  }
13495
13208
 
13496
- _selectFrequency(freq) {
13497
- this.surveyState.customAnswers.frequency = freq;
13498
- this.surveyElement
13499
- .querySelectorAll('.feedback-survey-freq-btn')
13500
- .forEach((btn) => {
13501
- if (btn.dataset.freq === freq) {
13502
- btn.classList.add('selected');
13503
- } else {
13504
- btn.classList.remove('selected');
13505
- }
13506
- });
13507
- }
13508
-
13509
13209
  _setSubmitLoading(loading) {
13510
13210
  const btn = this.surveyElement?.querySelector('.feedback-survey-submit');
13511
13211
  if (!btn) return;
@@ -13585,8 +13285,7 @@
13585
13285
  await this.apiService.submitSurveyResponse(surveyId, responseData);
13586
13286
 
13587
13287
  this.sdk.eventBus.emit('survey:submitted', { widget: this, response });
13588
- this._closeSurvey();
13589
- this._showSuccessNotification();
13288
+ this._showThankYouScreen();
13590
13289
  } catch (error) {
13591
13290
  console.error('[SurveyWidget] Failed to submit survey:', error);
13592
13291
  this._showError('Something went wrong. Please try again.');
@@ -13622,9 +13321,8 @@
13622
13321
 
13623
13322
  _validateCurrentPage() {
13624
13323
  const page = this._getCurrentPage();
13625
- if (!page || page.required === false) return true;
13324
+ if (!page || page.required !== true) return true;
13626
13325
  const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
13627
-
13628
13326
  const answer = this.surveyState.pageAnswers[pageId] || {};
13629
13327
 
13630
13328
  if (page.type === 'rating') {
@@ -13635,9 +13333,10 @@
13635
13333
  }
13636
13334
 
13637
13335
  if (page.type === 'multiple_choice') {
13638
- const hasSingle = Boolean(answer.value);
13639
- const hasMany = Array.isArray(answer.values) && answer.values.length > 0;
13640
- if (!hasSingle && !hasMany) {
13336
+ const hasAnswer =
13337
+ Boolean(answer.value) ||
13338
+ (Array.isArray(answer.values) && answer.values.length > 0);
13339
+ if (!hasAnswer) {
13641
13340
  this._showError('Please select an option');
13642
13341
  return false;
13643
13342
  }
@@ -13650,55 +13349,88 @@
13650
13349
  }
13651
13350
  }
13652
13351
 
13653
- if (page.type === 'link') {
13654
- if (page.required && !answer.clicked) {
13655
- this._showError('Please click the link to continue');
13656
- return false;
13657
- }
13658
- }
13659
-
13660
13352
  return true;
13661
13353
  }
13662
13354
 
13663
13355
  _getNextPageIndex() {
13664
- if (!this._isMultiPageSurvey()) {
13665
- return -1;
13666
- }
13356
+ if (!this._isMultiPageSurvey()) return -1;
13667
13357
 
13668
13358
  const page = this._getCurrentPage();
13669
13359
  const total = this.surveyOptions.pages.length;
13670
13360
  const currentIndex = this.surveyState.currentPageIndex;
13671
13361
  const fallbackNext = currentIndex + 1 < total ? currentIndex + 1 : -1;
13672
- const navigation = page ? page.afterThisPage || page.after_this_page : null;
13673
- if (!navigation) {
13674
- return fallbackNext;
13675
- }
13362
+ const navigation = page ? page.after_this_page || page.afterThisPage : null;
13363
+ if (!navigation) return fallbackNext;
13676
13364
 
13677
- const nextValue = navigation.default;
13678
- if (!nextValue) {
13679
- return fallbackNext;
13680
- }
13365
+ const conditions = Array.isArray(navigation.conditions)
13366
+ ? navigation.conditions
13367
+ : [];
13368
+ const pageId = page.id || `page_${currentIndex}`;
13369
+ const answer = this.surveyState.pageAnswers[pageId] || {};
13681
13370
 
13682
- if (nextValue === 'end_survey') {
13683
- return -1;
13684
- }
13685
- if (nextValue === 'next_page' || nextValue === 'next') {
13686
- return fallbackNext;
13371
+ for (const condition of conditions) {
13372
+ if (this._evaluateCondition(condition, page, answer)) {
13373
+ return this._resolvePageTarget(condition.go_to, total, fallbackNext);
13374
+ }
13687
13375
  }
13688
13376
 
13689
- if (typeof nextValue === 'number') {
13690
- return nextValue >= 0 && nextValue < total ? nextValue : fallbackNext;
13377
+ return this._resolvePageTarget(navigation.default, total, fallbackNext);
13378
+ }
13379
+
13380
+ _evaluateCondition(condition, page, answer) {
13381
+ const { operator, values } = condition;
13382
+ if (!operator || !Array.isArray(values)) return false;
13383
+
13384
+ let answerValue = null;
13385
+ if (page.type === 'rating') {
13386
+ answerValue = typeof answer.rating === 'number' ? answer.rating : null;
13387
+ } else if (page.type === 'multiple_choice') {
13388
+ answerValue =
13389
+ answer.value ||
13390
+ (Array.isArray(answer.values) ? answer.values[0] : null);
13391
+ } else if (page.type === 'text') {
13392
+ answerValue = answer.text || null;
13393
+ }
13394
+
13395
+ if (operator === 'is_empty')
13396
+ return answerValue === null || answerValue === '';
13397
+ if (operator === 'not_empty')
13398
+ return answerValue !== null && answerValue !== '';
13399
+ if (answerValue === null) return false;
13400
+
13401
+ const [v1, v2] = values;
13402
+ switch (operator) {
13403
+ case 'equals':
13404
+ return String(answerValue) === String(v1);
13405
+ case 'greater_than':
13406
+ return Number(answerValue) > Number(v1);
13407
+ case 'less_than':
13408
+ return Number(answerValue) < Number(v1);
13409
+ case 'between':
13410
+ return (
13411
+ Number(answerValue) >= Number(v1) && Number(answerValue) <= Number(v2)
13412
+ );
13413
+ case 'contains':
13414
+ return String(answerValue).includes(String(v1));
13415
+ default:
13416
+ return false;
13691
13417
  }
13418
+ }
13692
13419
 
13693
- if (typeof nextValue === 'string') {
13694
- const normalizedId = nextValue.replace(/^page:/, '');
13695
- const pageIndex = this.surveyOptions.pages.findIndex(
13696
- (item) => item.id === normalizedId
13420
+ _resolvePageTarget(target, total, fallback) {
13421
+ if (!target) return fallback;
13422
+ if (target === 'end_survey') return -1;
13423
+ if (target === 'next_page' || target === 'next') return fallback;
13424
+ if (typeof target === 'number')
13425
+ return target >= 0 && target < total ? target : fallback;
13426
+ if (typeof target === 'string') {
13427
+ const normalizedId = target.replace(/^page:/, '');
13428
+ const idx = this.surveyOptions.pages.findIndex(
13429
+ (p) => p.id === normalizedId
13697
13430
  );
13698
- return pageIndex >= 0 ? pageIndex : fallbackNext;
13431
+ return idx >= 0 ? idx : fallback;
13699
13432
  }
13700
-
13701
- return fallbackNext;
13433
+ return fallback;
13702
13434
  }
13703
13435
 
13704
13436
  _getSubmissionRating() {
@@ -13803,23 +13535,45 @@
13803
13535
  setTimeout(() => error.remove(), 3000);
13804
13536
  }
13805
13537
 
13806
- _showSuccessNotification() {
13807
- const notification = document.createElement('div');
13808
- notification.className =
13809
- 'product7-notification product7-notification-success';
13810
- notification.innerHTML = `
13811
- <div>
13812
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M173.66,98.34a8,8,0,0,1,0,11.32l-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35A8,8,0,0,1,173.66,98.34ZM232,128A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z" fill="currentColor"/></svg>
13813
- <span>Thank you for your feedback!</span>
13538
+ _showThankYouScreen() {
13539
+ if (!this.surveyElement) return;
13540
+
13541
+ const config = this.surveyOptions.thankYouConfig || {};
13542
+ const title = config.title || 'Thanks for your feedback!';
13543
+ const buttonText = config.button_text || null;
13544
+ const buttonUrl = config.button_url || '#';
13545
+
13546
+ if (this._escapeHandler) {
13547
+ document.removeEventListener('keydown', this._escapeHandler);
13548
+ this._escapeHandler = null;
13549
+ }
13550
+
13551
+ this.surveyElement.innerHTML = `
13552
+ <button class="feedback-survey-close"><iconify-icon icon="ph:x-duotone" width="16" height="16"></iconify-icon></button>
13553
+ <div class="feedback-survey-thankyou">
13554
+ <iconify-icon icon="ph:check-circle-duotone" width="48" height="48" class="feedback-survey-thankyou-icon"></iconify-icon>
13555
+ <h3 class="feedback-survey-thankyou-title">${title}</h3>
13556
+ ${
13557
+ buttonText
13558
+ ? `
13559
+ <a class="feedback-survey-thankyou-btn" href="${buttonUrl}" target="_blank" rel="noopener noreferrer">
13560
+ ${buttonText}
13561
+ <iconify-icon icon="ph:arrow-square-out-duotone" width="15" height="15" style="pointer-events:none;"></iconify-icon>
13562
+ </a>`
13563
+ : ''
13564
+ }
13814
13565
  </div>
13815
13566
  `;
13816
- document.body.appendChild(notification);
13817
13567
 
13818
- setTimeout(() => {
13819
- notification.style.opacity = '0';
13820
- notification.style.transition = 'opacity 0.3s ease';
13821
- setTimeout(() => notification.remove(), 300);
13822
- }, 3000);
13568
+ const closeBtn = this.surveyElement.querySelector('.feedback-survey-close');
13569
+ if (closeBtn) closeBtn.addEventListener('click', () => this._closeSurvey());
13570
+
13571
+ setTimeout(
13572
+ () => {
13573
+ if (this.surveyElement) this._closeSurvey();
13574
+ },
13575
+ buttonText ? 6000 : 3500
13576
+ );
13823
13577
  }
13824
13578
 
13825
13579
  _closeSurvey(resetState = true, immediate = false) {
@@ -14292,6 +14046,7 @@
14292
14046
  showDescription: normalizedOptions.showDescription,
14293
14047
  customQuestions: normalizedOptions.customQuestions,
14294
14048
  pages: normalizedOptions.pages,
14049
+ thankYouConfig: normalizedOptions.thankYouConfig,
14295
14050
  respondentId: normalizedOptions.respondentId,
14296
14051
  email: normalizedOptions.email,
14297
14052
  onSubmit: normalizedOptions.onSubmit,
@@ -14435,6 +14190,7 @@
14435
14190
  survey.custom_questions ||
14436
14191
  survey.questions ||
14437
14192
  [],
14193
+ thankYouConfig: survey.thankYouConfig || survey.thank_you_config || null,
14438
14194
  pages: this._normalizeSurveyPages(survey.pages || []),
14439
14195
  };
14440
14196
  }
@@ -14451,7 +14207,7 @@
14451
14207
  title: page.title || '',
14452
14208
  description: page.description || '',
14453
14209
  placeholder: page.placeholder || '',
14454
- required: page.required !== false,
14210
+ required: page.required === true,
14455
14211
  position: page.position ?? index,
14456
14212
  ratingConfig: page.ratingConfig || page.rating_config || null,
14457
14213
  multipleChoiceConfig: