@product7/product7-js 0.4.2 → 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
 
6175
+ .feedback-survey-page-choice-btn:hover::after {
6176
+ border-color: var(--color-primary);
6177
+ }
6178
+
6317
6179
  .feedback-survey-page-choice-btn.selected {
6318
- background: var(--color-primary-light);
6319
6180
  border-color: var(--color-primary);
6181
+ background: var(--color-primary-light);
6320
6182
  color: var(--color-primary-active);
6321
6183
  }
6322
6184
 
6323
- /* ========================================
6324
- LINK PAGE
6325
- ======================================== */
6326
-
6327
- .feedback-survey-link-page {
6328
- display: flex;
6329
- flex-direction: column;
6330
- gap: var(--spacing-3);
6185
+ .feedback-survey-page-choice-btn.selected::after {
6186
+ border-color: var(--color-primary);
6187
+ background-color: var(--color-primary);
6331
6188
  }
6332
6189
 
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;
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
- await 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
- async _playSynthetic() {
8329
- const ctx = this._getAudioContext();
8330
- if (!ctx) return;
8331
-
8332
- if (ctx.state === 'suspended') {
8333
- await ctx.resume();
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 : undefined,
11365
+ soundUrl:
11366
+ typeof notificationSoundOption === 'string'
11367
+ ? notificationSoundOption
11368
+ : undefined,
11533
11369
  volume: options.notificationVolume ?? 0.4,
11534
11370
  });
11535
11371
 
@@ -12538,6 +12374,8 @@
12538
12374
  : null,
12539
12375
  customQuestions: options.customQuestions || [],
12540
12376
  pages: Array.isArray(options.pages) ? options.pages : [],
12377
+ thankYouConfig:
12378
+ options.thankYouConfig || options.thank_you_config || null,
12541
12379
  respondentId: options.respondentId || null,
12542
12380
  email: options.email || null,
12543
12381
  onSubmit: options.onSubmit || null,
@@ -12866,10 +12704,6 @@
12866
12704
 
12867
12705
  _shouldShowActions() {
12868
12706
  if (this._isMultiPageSurvey()) {
12869
- const page = this._getCurrentPage();
12870
- if (page && page.type === 'link') {
12871
- return false;
12872
- }
12873
12707
  return true;
12874
12708
  }
12875
12709
  if (typeof this.surveyOptions.showSubmitButton === 'boolean') {
@@ -12918,8 +12752,6 @@
12918
12752
  return this._renderMultipleChoicePage(page);
12919
12753
  case 'text':
12920
12754
  return this._renderTextPage(page);
12921
- case 'link':
12922
- return this._renderLinkPage(page);
12923
12755
  default:
12924
12756
  return '';
12925
12757
  }
@@ -12927,62 +12759,36 @@
12927
12759
 
12928
12760
  _renderRatingPage(page) {
12929
12761
  const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
12930
- const config = page.ratingConfig || page.rating_config || {};
12762
+ const config = page.rating_config || page.ratingConfig || {};
12931
12763
  const scale = Number(config.scale) || 5;
12932
- const topSurveyType = this.surveyOptions.surveyType;
12933
- const configType = config.survey_type;
12934
- let ratingType;
12935
- if (topSurveyType === 'nps') {
12936
- ratingType = 'nps';
12937
- } else if (configType) {
12938
- ratingType = configType;
12939
- } else if (topSurveyType === 'ces') {
12940
- ratingType = 'ces';
12941
- } else if (topSurveyType === 'csat') {
12942
- ratingType = 'emoji';
12943
- } else {
12944
- ratingType = topSurveyType || 'csat';
12945
- }
12764
+ const ratingType = config.survey_type || 'number';
12946
12765
  const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
12947
12766
  const currentRating = pageAnswer.rating;
12948
- const defaultLowLabel =
12949
- ratingType === 'nps'
12950
- ? scale === 11
12951
- ? 'Not likely'
12952
- : 'Strongly Disagree'
12953
- : '';
12954
- const defaultHighLabel =
12955
- ratingType === 'nps'
12956
- ? scale === 11
12957
- ? 'Very likely'
12958
- : 'Strongly Agree'
12959
- : '';
12960
- const lowLabel =
12961
- config.low_label || this.surveyOptions.lowLabel || defaultLowLabel;
12962
- const highLabel =
12963
- 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;
12964
12780
  const labels = this._renderScaleLabels(lowLabel, highLabel);
12965
12781
 
12966
12782
  if (ratingType === 'nps') {
12967
- const npsScale = Number.isFinite(scale) && scale >= 2 ? scale : 5;
12783
+ const npsScale = Number.isFinite(scale) && scale >= 2 ? scale : 11;
12968
12784
  const start = npsScale === 11 ? 0 : 1;
12969
- const values = Array.from(
12970
- { length: npsScale },
12971
- (_, index) => start + index
12972
- );
12973
- const usesSegmentedScale = values.length <= 7;
12974
- const containerClass = usesSegmentedScale
12975
- ? 'feedback-survey-ces feedback-survey-rating-scale'
12976
- : 'feedback-survey-nps';
12977
- const buttonClass = usesSegmentedScale
12978
- ? 'feedback-survey-page-rating-btn feedback-survey-nps-btn feedback-survey-ces-btn feedback-survey-rating-scale-btn'
12979
- : 'feedback-survey-page-rating-btn feedback-survey-nps-btn';
12785
+ const values = Array.from({ length: npsScale }, (_, i) => start + i);
12980
12786
  return `
12981
- <div class="${containerClass}" data-page-id="${pageId}">
12787
+ <div class="feedback-survey-nps" data-page-id="${pageId}">
12982
12788
  ${values
12983
12789
  .map((n) => {
12984
12790
  const selected = currentRating === n ? ' selected' : '';
12985
- 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>`;
12986
12792
  })
12987
12793
  .join('')}
12988
12794
  </div>
@@ -12990,28 +12796,7 @@
12990
12796
  `;
12991
12797
  }
12992
12798
 
12993
- if (ratingType === 'ces') {
12994
- const cesLabels = [
12995
- 'Very Difficult',
12996
- 'Difficult',
12997
- 'Neutral',
12998
- 'Easy',
12999
- 'Very Easy',
13000
- ];
13001
- return `
13002
- <div class="feedback-survey-ces-list" data-page-id="${pageId}">
13003
- ${cesLabels
13004
- .map((label, i) => {
13005
- const score = i + 1;
13006
- const selected = currentRating === score ? ' selected' : '';
13007
- return `<button class="feedback-survey-page-rating-btn feedback-survey-ces-list-btn${selected}" data-page-id="${pageId}" data-score="${score}">${label}</button>`;
13008
- })
13009
- .join('')}
13010
- </div>
13011
- `;
13012
- }
13013
-
13014
- if (ratingType === 'emoji' && scale === 5) {
12799
+ if (ratingType === 'emoji') {
13015
12800
  const emojis = [
13016
12801
  '\uD83D\uDE1E',
13017
12802
  '\uD83D\uDE15',
@@ -13019,9 +12804,12 @@
13019
12804
  '\uD83D\uDE42',
13020
12805
  '\uD83D\uDE04',
13021
12806
  ];
12807
+ const emojiScale =
12808
+ Number.isFinite(scale) && scale >= 2 ? Math.min(scale, 5) : 5;
13022
12809
  return `
13023
12810
  <div class="feedback-survey-csat" data-page-id="${pageId}">
13024
12811
  ${emojis
12812
+ .slice(0, emojiScale)
13025
12813
  .map((emoji, i) => {
13026
12814
  const score = i + 1;
13027
12815
  const selected = currentRating === score ? ' selected' : '';
@@ -13037,27 +12825,27 @@
13037
12825
  const starScale = Number.isFinite(scale) && scale >= 2 ? scale : 5;
13038
12826
  return `
13039
12827
  <div class="feedback-survey-stars" data-page-id="${pageId}">
13040
- ${[...Array(starScale).keys()]
13041
- .map((i) => {
13042
- const score = i + 1;
13043
- const filled = currentRating >= score ? ' filled' : '';
13044
- return `<button class="feedback-survey-page-rating-btn feedback-survey-star-btn${filled}" data-page-id="${pageId}" data-score="${score}">★</button>`;
13045
- })
13046
- .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('')}
13047
12836
  </div>
13048
12837
  ${labels}
13049
12838
  `;
13050
12839
  }
13051
12840
 
12841
+ const numScale = Number.isFinite(scale) && scale >= 2 ? scale : 5;
13052
12842
  return `
13053
12843
  <div class="feedback-survey-rating-scale" data-page-id="${pageId}">
13054
- ${[...Array(scale).keys()]
13055
- .map((i) => {
13056
- const score = i + 1;
13057
- const selected = currentRating === score ? ' selected' : '';
13058
- return `<button class="feedback-survey-page-rating-btn feedback-survey-rating-scale-btn${selected}" data-page-id="${pageId}" data-score="${score}">${score}</button>`;
13059
- })
13060
- .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('')}
13061
12849
  </div>
13062
12850
  ${labels}
13063
12851
  `;
@@ -13107,32 +12895,6 @@
13107
12895
  `;
13108
12896
  }
13109
12897
 
13110
- _renderLinkPage(page) {
13111
- const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
13112
- const config = page.link_config || page.linkConfig || {};
13113
- const buttonText = config.button_text || config.buttonText || 'Click here';
13114
- const linkText = config.link_text || config.linkText || '';
13115
- const redirectUrl = config.redirect_url || config.redirectUrl || '#';
13116
- const openIn = config.open_in || config.openIn || 'new_tab';
13117
- const target = openIn === 'new_tab' ? '_blank' : '_self';
13118
- const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
13119
- const clicked = pageAnswer.clicked === true;
13120
-
13121
- const iconExternalLink = `<iconify-icon icon="ph:arrow-square-out-duotone" width="15" height="15"></iconify-icon>`;
13122
- return `
13123
- <div class="feedback-survey-link-page" data-page-id="${pageId}">
13124
- ${linkText ? `<p class="feedback-survey-link-text">${linkText}</p>` : ''}
13125
- <a class="feedback-survey-link-btn${clicked ? ' selected' : ''}"
13126
- href="${redirectUrl}"
13127
- target="${target}"
13128
- rel="noopener noreferrer"
13129
- data-page-id="${pageId}">
13130
- ${buttonText} ${iconExternalLink}
13131
- </a>
13132
- </div>
13133
- `;
13134
- }
13135
-
13136
12898
  _renderCustomQuestions() {
13137
12899
  if (
13138
12900
  !this.surveyOptions.customQuestions ||
@@ -13415,24 +13177,6 @@
13415
13177
  });
13416
13178
  }
13417
13179
  }
13418
-
13419
- if (page.type === 'link') {
13420
- this.surveyElement
13421
- .querySelectorAll('.feedback-survey-link-btn')
13422
- .forEach((btn) => {
13423
- btn.addEventListener('click', () => {
13424
- const pId = btn.dataset.pageId;
13425
- this._setPageAnswer(pId, { clicked: true });
13426
- btn.classList.add('selected');
13427
-
13428
- const navigation = page.afterThisPage || page.after_this_page;
13429
- const goesTo = navigation ? navigation.default : null;
13430
- if (!goesTo || goesTo === 'end_survey') {
13431
- setTimeout(() => this._handleSubmit(), 400);
13432
- }
13433
- });
13434
- });
13435
- }
13436
13180
  }
13437
13181
 
13438
13182
  _selectNPS(score) {
@@ -13441,11 +13185,7 @@
13441
13185
  .querySelectorAll('.feedback-survey-nps-btn')
13442
13186
  .forEach((btn) => {
13443
13187
  const btnScore = parseInt(btn.dataset.score);
13444
- if (btnScore === score) {
13445
- btn.classList.add('selected');
13446
- } else {
13447
- btn.classList.remove('selected');
13448
- }
13188
+ btn.classList.toggle('selected', btnScore === score);
13449
13189
  });
13450
13190
  this._maybeAutoSubmit();
13451
13191
  }
@@ -13456,50 +13196,16 @@
13456
13196
  .querySelectorAll('.feedback-survey-csat-btn')
13457
13197
  .forEach((btn) => {
13458
13198
  const btnScore = parseInt(btn.dataset.score);
13459
- if (btnScore === score) {
13460
- btn.classList.add('selected');
13461
- } else {
13462
- btn.classList.remove('selected');
13463
- }
13464
- });
13465
- this._maybeAutoSubmit();
13466
- }
13467
-
13468
- _selectCES(score) {
13469
- this.surveyState.score = score;
13470
- this.surveyElement
13471
- .querySelectorAll('.feedback-survey-ces-btn')
13472
- .forEach((btn) => {
13473
- const btnScore = parseInt(btn.dataset.score);
13474
- if (btnScore === score) {
13475
- btn.classList.add('selected');
13476
- } else {
13477
- btn.classList.remove('selected');
13478
- }
13199
+ btn.classList.toggle('selected', btnScore === score);
13479
13200
  });
13480
13201
  this._maybeAutoSubmit();
13481
13202
  }
13482
13203
 
13483
13204
  _maybeAutoSubmit() {
13484
- if (!this._shouldAutoSubmitOnSelect()) {
13485
- return;
13486
- }
13205
+ if (!this._shouldAutoSubmitOnSelect()) return;
13487
13206
  this._handleSubmit();
13488
13207
  }
13489
13208
 
13490
- _selectFrequency(freq) {
13491
- this.surveyState.customAnswers.frequency = freq;
13492
- this.surveyElement
13493
- .querySelectorAll('.feedback-survey-freq-btn')
13494
- .forEach((btn) => {
13495
- if (btn.dataset.freq === freq) {
13496
- btn.classList.add('selected');
13497
- } else {
13498
- btn.classList.remove('selected');
13499
- }
13500
- });
13501
- }
13502
-
13503
13209
  _setSubmitLoading(loading) {
13504
13210
  const btn = this.surveyElement?.querySelector('.feedback-survey-submit');
13505
13211
  if (!btn) return;
@@ -13579,8 +13285,7 @@
13579
13285
  await this.apiService.submitSurveyResponse(surveyId, responseData);
13580
13286
 
13581
13287
  this.sdk.eventBus.emit('survey:submitted', { widget: this, response });
13582
- this._closeSurvey();
13583
- this._showSuccessNotification();
13288
+ this._showThankYouScreen();
13584
13289
  } catch (error) {
13585
13290
  console.error('[SurveyWidget] Failed to submit survey:', error);
13586
13291
  this._showError('Something went wrong. Please try again.');
@@ -13616,9 +13321,8 @@
13616
13321
 
13617
13322
  _validateCurrentPage() {
13618
13323
  const page = this._getCurrentPage();
13619
- if (!page || page.required === false) return true;
13324
+ if (!page || page.required !== true) return true;
13620
13325
  const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
13621
-
13622
13326
  const answer = this.surveyState.pageAnswers[pageId] || {};
13623
13327
 
13624
13328
  if (page.type === 'rating') {
@@ -13629,9 +13333,10 @@
13629
13333
  }
13630
13334
 
13631
13335
  if (page.type === 'multiple_choice') {
13632
- const hasSingle = Boolean(answer.value);
13633
- const hasMany = Array.isArray(answer.values) && answer.values.length > 0;
13634
- if (!hasSingle && !hasMany) {
13336
+ const hasAnswer =
13337
+ Boolean(answer.value) ||
13338
+ (Array.isArray(answer.values) && answer.values.length > 0);
13339
+ if (!hasAnswer) {
13635
13340
  this._showError('Please select an option');
13636
13341
  return false;
13637
13342
  }
@@ -13644,55 +13349,88 @@
13644
13349
  }
13645
13350
  }
13646
13351
 
13647
- if (page.type === 'link') {
13648
- if (page.required && !answer.clicked) {
13649
- this._showError('Please click the link to continue');
13650
- return false;
13651
- }
13652
- }
13653
-
13654
13352
  return true;
13655
13353
  }
13656
13354
 
13657
13355
  _getNextPageIndex() {
13658
- if (!this._isMultiPageSurvey()) {
13659
- return -1;
13660
- }
13356
+ if (!this._isMultiPageSurvey()) return -1;
13661
13357
 
13662
13358
  const page = this._getCurrentPage();
13663
13359
  const total = this.surveyOptions.pages.length;
13664
13360
  const currentIndex = this.surveyState.currentPageIndex;
13665
13361
  const fallbackNext = currentIndex + 1 < total ? currentIndex + 1 : -1;
13666
- const navigation = page ? page.afterThisPage || page.after_this_page : null;
13667
- if (!navigation) {
13668
- return fallbackNext;
13669
- }
13362
+ const navigation = page ? page.after_this_page || page.afterThisPage : null;
13363
+ if (!navigation) return fallbackNext;
13670
13364
 
13671
- const nextValue = navigation.default;
13672
- if (!nextValue) {
13673
- return fallbackNext;
13674
- }
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] || {};
13675
13370
 
13676
- if (nextValue === 'end_survey') {
13677
- return -1;
13678
- }
13679
- if (nextValue === 'next_page' || nextValue === 'next') {
13680
- 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
+ }
13681
13375
  }
13682
13376
 
13683
- if (typeof nextValue === 'number') {
13684
- 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;
13685
13417
  }
13418
+ }
13686
13419
 
13687
- if (typeof nextValue === 'string') {
13688
- const normalizedId = nextValue.replace(/^page:/, '');
13689
- const pageIndex = this.surveyOptions.pages.findIndex(
13690
- (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
13691
13430
  );
13692
- return pageIndex >= 0 ? pageIndex : fallbackNext;
13431
+ return idx >= 0 ? idx : fallback;
13693
13432
  }
13694
-
13695
- return fallbackNext;
13433
+ return fallback;
13696
13434
  }
13697
13435
 
13698
13436
  _getSubmissionRating() {
@@ -13797,23 +13535,45 @@
13797
13535
  setTimeout(() => error.remove(), 3000);
13798
13536
  }
13799
13537
 
13800
- _showSuccessNotification() {
13801
- const notification = document.createElement('div');
13802
- notification.className =
13803
- 'product7-notification product7-notification-success';
13804
- notification.innerHTML = `
13805
- <div>
13806
- <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>
13807
- <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
+ }
13808
13565
  </div>
13809
13566
  `;
13810
- document.body.appendChild(notification);
13811
13567
 
13812
- setTimeout(() => {
13813
- notification.style.opacity = '0';
13814
- notification.style.transition = 'opacity 0.3s ease';
13815
- setTimeout(() => notification.remove(), 300);
13816
- }, 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
+ );
13817
13577
  }
13818
13578
 
13819
13579
  _closeSurvey(resetState = true, immediate = false) {
@@ -14286,6 +14046,7 @@
14286
14046
  showDescription: normalizedOptions.showDescription,
14287
14047
  customQuestions: normalizedOptions.customQuestions,
14288
14048
  pages: normalizedOptions.pages,
14049
+ thankYouConfig: normalizedOptions.thankYouConfig,
14289
14050
  respondentId: normalizedOptions.respondentId,
14290
14051
  email: normalizedOptions.email,
14291
14052
  onSubmit: normalizedOptions.onSubmit,
@@ -14429,6 +14190,7 @@
14429
14190
  survey.custom_questions ||
14430
14191
  survey.questions ||
14431
14192
  [],
14193
+ thankYouConfig: survey.thankYouConfig || survey.thank_you_config || null,
14432
14194
  pages: this._normalizeSurveyPages(survey.pages || []),
14433
14195
  };
14434
14196
  }
@@ -14445,7 +14207,7 @@
14445
14207
  title: page.title || '',
14446
14208
  description: page.description || '',
14447
14209
  placeholder: page.placeholder || '',
14448
- required: page.required !== false,
14210
+ required: page.required === true,
14449
14211
  position: page.position ?? index,
14450
14212
  ratingConfig: page.ratingConfig || page.rating_config || null,
14451
14213
  multipleChoiceConfig: