@product7/feedback-sdk 1.3.3 → 1.3.5

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.
Files changed (39) hide show
  1. package/dist/feedback-sdk.js +2441 -3240
  2. package/dist/feedback-sdk.js.map +1 -1
  3. package/dist/feedback-sdk.min.js +1 -1
  4. package/dist/feedback-sdk.min.js.map +1 -1
  5. package/package.json +1 -1
  6. package/src/api/services/MessengerService.js +76 -0
  7. package/src/core/BaseAPIService.js +4 -0
  8. package/src/index.js +2 -3
  9. package/src/styles/base.js +27 -52
  10. package/src/styles/changelog.js +152 -269
  11. package/src/styles/components.js +489 -0
  12. package/src/styles/design-tokens.js +104 -0
  13. package/src/styles/feedback.js +59 -369
  14. package/src/styles/messenger-core.js +390 -0
  15. package/src/styles/messenger-features.js +347 -0
  16. package/src/styles/messenger-help.js +298 -0
  17. package/src/styles/messenger-themes.js +500 -0
  18. package/src/styles/messenger-views.js +618 -0
  19. package/src/styles/messenger.js +558 -0
  20. package/src/styles/styles.js +24 -2
  21. package/src/styles/surveys.js +354 -0
  22. package/src/widgets/BaseWidget.js +25 -58
  23. package/src/widgets/ButtonWidget.js +3 -18
  24. package/src/widgets/ChangelogWidget.js +7 -48
  25. package/src/widgets/InlineWidget.js +16 -13
  26. package/src/widgets/MessengerWidget.js +37 -51
  27. package/src/widgets/SurveyWidget.js +42 -146
  28. package/src/widgets/TabWidget.js +2 -22
  29. package/src/widgets/messenger/MessengerState.js +49 -46
  30. package/src/widgets/messenger/components/MessengerLauncher.js +10 -5
  31. package/src/widgets/messenger/components/MessengerPanel.js +5 -27
  32. package/src/widgets/messenger/components/NavigationTabs.js +5 -14
  33. package/src/widgets/messenger/views/ChangelogView.js +13 -14
  34. package/src/widgets/messenger/views/ChatView.js +43 -36
  35. package/src/widgets/messenger/views/ConversationsView.js +16 -21
  36. package/src/widgets/messenger/views/HelpView.js +10 -10
  37. package/src/widgets/messenger/views/HomeView.js +11 -16
  38. package/src/widgets/messenger/views/PreChatFormView.js +18 -30
  39. package/src/styles/messengerStyles.js +0 -2328
@@ -36,7 +36,7 @@ export class HomeView {
36
36
  ${this.options.logoUrl ? `<img src="${this.options.logoUrl}" alt="${this.state.teamName}" />` : ''}
37
37
  </div>
38
38
  <div class="messenger-home-avatars">${avatarsHtml}</div>
39
- <button class="messenger-close-btn" aria-label="Close">
39
+ <button class="sdk-close-btn" aria-label="Close">
40
40
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
41
41
  <path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
42
42
  </svg>
@@ -66,30 +66,25 @@ export class HomeView {
66
66
  if (!avatars || avatars.length === 0) {
67
67
  return `
68
68
  <div class="messenger-avatar-stack">
69
- <div class="messenger-avatar" style="background: #5856d6;">S</div>
70
- <div class="messenger-avatar" style="background: #007aff;">T</div>
69
+ <div class="sdk-avatar sdk-avatar-md">S</div>
70
+ <div class="sdk-avatar sdk-avatar-md">T</div>
71
71
  </div>
72
72
  `;
73
73
  }
74
74
 
75
75
  const avatarItems = avatars
76
76
  .slice(0, 3)
77
- .map((avatar, i) => {
77
+ .map((avatar) => {
78
78
  if (typeof avatar === 'string' && avatar.startsWith('http')) {
79
- return `<img class="messenger-avatar" src="${avatar}" alt="Team member" style="z-index: ${3 - i};" />`;
79
+ return `<div class="sdk-avatar sdk-avatar-md"><img src="${avatar}" alt="Team member" /></div>`;
80
80
  }
81
- return `<div class="messenger-avatar" style="background: ${this._getAvatarColor(i)}; z-index: ${3 - i};">${avatar.charAt(0).toUpperCase()}</div>`;
81
+ return `<div class="sdk-avatar sdk-avatar-md">${avatar.charAt(0).toUpperCase()}</div>`;
82
82
  })
83
83
  .join('');
84
84
 
85
85
  return `<div class="messenger-avatar-stack">${avatarItems}</div>`;
86
86
  }
87
87
 
88
- _getAvatarColor(index) {
89
- const colors = ['#5856d6', '#007aff', '#34c759', '#ff9500', '#ff3b30'];
90
- return colors[index % colors.length];
91
- }
92
-
93
88
  _renderAvailabilityStatus() {
94
89
  const isOnline = this.state.agentsOnline;
95
90
  const responseTime =
@@ -130,7 +125,7 @@ export class HomeView {
130
125
  <span class="messenger-home-continue-label">Continue conversation</span>
131
126
  <span class="messenger-home-continue-preview">${preview}</span>
132
127
  </div>
133
- <i class="ph ph-arrow-right" style="font-size: 16px;"></i>
128
+ <i class="ph ph-arrow-right"></i>
134
129
  </button>
135
130
  `;
136
131
  }
@@ -138,7 +133,7 @@ export class HomeView {
138
133
  return `
139
134
  <button class="messenger-home-message-btn">
140
135
  <span>Send us a message</span>
141
- <i class="ph ph-arrow-right" style="font-size: 16px;"></i>
136
+ <i class="ph ph-arrow-right"></i>
142
137
  </button>
143
138
  `;
144
139
  }
@@ -158,7 +153,7 @@ export class HomeView {
158
153
  <h3>${title}</h3>
159
154
  <p>${description}</p>
160
155
  </div>
161
- ${action ? `<button class="messenger-home-featured-btn" data-action="${action.type}" data-value="${action.value}">${action.label}</button>` : ''}
156
+ ${action ? `<button class="sdk-btn sdk-btn-primary messenger-home-featured-btn" data-action="${action.type}" data-value="${action.value}">${action.label}</button>` : ''}
162
157
  </div>
163
158
  `;
164
159
  }
@@ -213,7 +208,7 @@ export class HomeView {
213
208
 
214
209
  _attachEvents() {
215
210
  this.element
216
- .querySelector('.messenger-close-btn')
211
+ .querySelector('.sdk-close-btn')
217
212
  .addEventListener('click', () => {
218
213
  this.state.setOpen(false);
219
214
  });
@@ -279,4 +274,4 @@ export class HomeView {
279
274
  this.element.parentNode.removeChild(this.element);
280
275
  }
281
276
  }
282
- }
277
+ }
@@ -1,6 +1,3 @@
1
- /**
2
- * PreChatFormView - Collects user info after the first message
3
- */
4
1
  export class PreChatFormView {
5
2
  constructor(state, options = {}) {
6
3
  this.state = state;
@@ -19,16 +16,15 @@ export class PreChatFormView {
19
16
  }
20
17
 
21
18
  _updateContent() {
22
- // Pre-fill from userContext if available
23
19
  const existingName = this.state.userContext?.name || '';
24
20
  const existingEmail = this.state.userContext?.email || '';
25
21
 
26
22
  this.element.innerHTML = `
27
23
  <div class="messenger-prechat-overlay">
28
24
  <div class="messenger-prechat-card">
29
- <h4>Get notified when we reply</h4>
30
- <form class="messenger-prechat-form" novalidate>
31
- <div class="messenger-prechat-fields">
25
+ <h4 class="messenger-prechat-title">Get notified when we reply</h4>
26
+ <form class="sdk-form-group" novalidate>
27
+ <div class="sdk-form-group">
32
28
  <input
33
29
  type="text"
34
30
  id="messenger-prechat-name"
@@ -36,8 +32,10 @@ export class PreChatFormView {
36
32
  placeholder="Name (optional)"
37
33
  value="${this._escapeHtml(existingName)}"
38
34
  autocomplete="name"
39
- class="messenger-prechat-input"
35
+ class="sdk-input"
40
36
  />
37
+ </div>
38
+ <div class="sdk-form-group">
41
39
  <input
42
40
  type="email"
43
41
  id="messenger-prechat-email"
@@ -46,16 +44,16 @@ export class PreChatFormView {
46
44
  value="${this._escapeHtml(existingEmail)}"
47
45
  required
48
46
  autocomplete="email"
49
- class="messenger-prechat-input"
47
+ class="sdk-input"
50
48
  />
49
+ <span class="messenger-prechat-error" id="messenger-email-error"></span>
51
50
  </div>
52
- <span class="messenger-prechat-error" id="messenger-email-error"></span>
53
51
  <div class="messenger-prechat-actions">
54
- <button type="button" class="messenger-prechat-skip">Skip</button>
55
- <button type="submit" class="messenger-prechat-submit" disabled>
52
+ <button type="button" class="sdk-btn sdk-btn-secondary messenger-prechat-skip">Skip</button>
53
+ <button type="submit" class="sdk-btn sdk-btn-primary sdk-btn-block messenger-prechat-submit" disabled>
56
54
  <span class="messenger-prechat-submit-text">Continue</span>
57
- <span class="messenger-prechat-submit-loading" style="display: none;">
58
- <i class="ph ph-spinner" style="font-size: 16px;"></i>
55
+ <span class="messenger-prechat-submit-loading">
56
+ <i class="ph ph-spinner"></i>
59
57
  </span>
60
58
  </button>
61
59
  </div>
@@ -72,20 +70,19 @@ export class PreChatFormView {
72
70
  if (!avatars || avatars.length === 0) {
73
71
  return `
74
72
  <div class="messenger-avatar-stack">
75
- <div class="messenger-avatar" style="background: #5856d6;">S</div>
76
- <div class="messenger-avatar" style="background: #007aff;">T</div>
73
+ <div class="sdk-avatar sdk-avatar-md">S</div>
74
+ <div class="sdk-avatar sdk-avatar-md">T</div>
77
75
  </div>
78
76
  `;
79
77
  }
80
78
 
81
- const colors = ['#5856d6', '#007aff', '#34c759', '#ff9500', '#ff3b30'];
82
79
  const avatarItems = avatars
83
80
  .slice(0, 3)
84
- .map((avatar, i) => {
81
+ .map((avatar) => {
85
82
  if (typeof avatar === 'string' && avatar.startsWith('http')) {
86
- return `<img class="messenger-avatar" src="${avatar}" alt="Team member" style="z-index: ${3 - i};" />`;
83
+ return `<div class="sdk-avatar sdk-avatar-md"><img src="${avatar}" alt="Team member" /></div>`;
87
84
  }
88
- return `<div class="messenger-avatar" style="background: ${colors[i % colors.length]}; z-index: ${3 - i};">${avatar.charAt(0).toUpperCase()}</div>`;
85
+ return `<div class="sdk-avatar sdk-avatar-md">${avatar.charAt(0).toUpperCase()}</div>`;
89
86
  })
90
87
  .join('');
91
88
 
@@ -103,7 +100,7 @@ export class PreChatFormView {
103
100
 
104
101
  _attachEvents() {
105
102
  // Form validation
106
- const form = this.element.querySelector('.messenger-prechat-form');
103
+ const form = this.element.querySelector('form');
107
104
  const emailInput = this.element.querySelector('#messenger-prechat-email');
108
105
  const submitBtn = this.element.querySelector('.messenger-prechat-submit');
109
106
  const skipBtn = this.element.querySelector('.messenger-prechat-skip');
@@ -127,12 +124,10 @@ export class PreChatFormView {
127
124
  }
128
125
  });
129
126
 
130
- // Skip button - go back to chat without collecting info
131
127
  skipBtn.addEventListener('click', () => {
132
128
  this.state.setView('chat');
133
129
  });
134
130
 
135
- // Form submission
136
131
  form.addEventListener('submit', async (e) => {
137
132
  e.preventDefault();
138
133
  if (this._isSubmitting) return;
@@ -143,10 +138,8 @@ export class PreChatFormView {
143
138
  await this._handleSubmit();
144
139
  });
145
140
 
146
- // Set initial button state
147
141
  validateForm();
148
142
 
149
- // Focus email input
150
143
  setTimeout(() => emailInput.focus(), 100);
151
144
  }
152
145
 
@@ -181,19 +174,16 @@ export class PreChatFormView {
181
174
  const name = nameInput.value.trim();
182
175
  const email = emailInput.value.trim();
183
176
 
184
- // Show loading state
185
177
  this._isSubmitting = true;
186
178
  submitBtn.disabled = true;
187
179
  submitText.style.display = 'none';
188
180
  submitLoading.style.display = 'inline-flex';
189
181
 
190
182
  try {
191
- // First, identify the contact with collected info
192
183
  if (this.options.onIdentifyContact) {
193
184
  await this.options.onIdentifyContact({ name, email });
194
185
  }
195
186
 
196
- // Update state with user info
197
187
  if (!this.state.userContext) {
198
188
  this.state.userContext = {};
199
189
  }
@@ -202,13 +192,11 @@ export class PreChatFormView {
202
192
 
203
193
  this._isSubmitting = false;
204
194
 
205
- // Go to chat after collecting contact info
206
195
  this.state.setView('chat');
207
196
  } catch (error) {
208
197
  console.error('[PreChatFormView] Error submitting form:', error);
209
198
  this._showError('messenger-email-error', 'Something went wrong. Please try again.');
210
199
 
211
- // Reset button state
212
200
  this._isSubmitting = false;
213
201
  submitBtn.disabled = false;
214
202
  submitText.style.display = 'inline';