@product7/feedback-sdk 1.5.7 → 1.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@product7/feedback-sdk",
3
- "version": "1.5.7",
3
+ "version": "1.5.8",
4
4
  "description": "JavaScript SDK for integrating Product7 feedback widgets into any website",
5
5
  "main": "dist/feedback-sdk.js",
6
6
  "module": "src/index.js",
@@ -4,17 +4,6 @@ export class HelpView {
4
4
  this.options = options;
5
5
  this.element = null;
6
6
  this._unsubscribe = null;
7
-
8
- this._avatarColors = [
9
- { bg: '#EF4444', text: '#FFFFFF' },
10
- { bg: '#F97316', text: '#FFFFFF' },
11
- { bg: '#F59E0B', text: '#FFFFFF' },
12
- { bg: '#10B981', text: '#FFFFFF' },
13
- { bg: '#06B6D4', text: '#FFFFFF' },
14
- { bg: '#3B82F6', text: '#FFFFFF' },
15
- { bg: '#8B5CF6', text: '#FFFFFF' },
16
- { bg: '#EC4899', text: '#FFFFFF' },
17
- ];
18
7
  }
19
8
 
20
9
  render() {
@@ -40,10 +29,8 @@ export class HelpView {
40
29
  <div class="messenger-help-header-top">
41
30
  <h2>Help</h2>
42
31
  <button class="sdk-close-btn" aria-label="Close">
43
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" width="18" height="18">
44
- <rect width="256" height="256" fill="none"/>
45
- <line x1="200" y1="56" x2="56" y2="200" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
46
- <line x1="200" y1="200" x2="56" y2="56" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
32
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 256 256">
33
+ <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>
47
34
  </svg>
48
35
  </button>
49
36
  </div>
@@ -71,7 +58,7 @@ export class HelpView {
71
58
  const collections = this.state.helpArticles || [];
72
59
  const searchQuery = (this.state.helpSearchQuery || '').toLowerCase();
73
60
 
74
- const filtered = searchQuery
61
+ const filteredCollections = searchQuery
75
62
  ? collections.filter(
76
63
  (c) =>
77
64
  c.title.toLowerCase().includes(searchQuery) ||
@@ -79,119 +66,41 @@ export class HelpView {
79
66
  )
80
67
  : collections;
81
68
 
82
- if (filtered.length === 0) {
69
+ const headerEl = this.element.querySelector(
70
+ '.messenger-help-collections-header'
71
+ );
72
+ if (headerEl) {
73
+ headerEl.textContent = `${filteredCollections.length} collections`;
74
+ }
75
+
76
+ if (filteredCollections.length === 0) {
83
77
  collectionsContainer.innerHTML = this._renderEmptyState();
84
78
  return;
85
79
  }
86
80
 
87
- collectionsContainer.innerHTML = filtered
88
- .map((c) => this._renderCollectionItem(c))
81
+ collectionsContainer.innerHTML = filteredCollections
82
+ .map((collection) => this._renderCollectionItem(collection))
89
83
  .join('');
90
84
 
91
- // Resolve Phosphor icons async after render
92
- filtered.forEach((c) => {
93
- if (c.icon && !c.icon.startsWith('<svg')) {
94
- const item = collectionsContainer.querySelector(
95
- `[data-collection-id="${c.id}"] .messenger-help-collection-icon`
96
- );
97
- if (item) this._resolvePhosphorIcon(item, c.icon);
98
- }
99
- });
100
-
101
85
  this._attachCollectionEvents();
102
86
  }
103
87
 
104
88
  _renderCollectionItem(collection) {
105
- const count = collection.article_count || collection.articleCount || 0;
106
- const icon = this._renderIcon(collection.icon);
107
- const avatar = this._renderAuthorAvatar(collection);
108
-
89
+ const articleCount = collection.articleCount || 0;
109
90
  return `
110
91
  <div class="messenger-help-collection" data-collection-id="${collection.id}">
111
- <div class="messenger-help-collection-header">
112
- <div class="messenger-help-collection-icon">${icon}</div>
92
+ <div class="messenger-help-collection-content">
113
93
  <h3 class="messenger-help-collection-title">${collection.title}</h3>
94
+ <p class="messenger-help-collection-desc">${collection.description || ''}</p>
95
+ <span class="messenger-help-collection-count">${articleCount} articles</span>
114
96
  </div>
115
- ${
116
- collection.description
117
- ? `<p class="messenger-help-collection-desc">${collection.description}</p>`
118
- : ''
119
- }
120
- <div class="messenger-help-collection-footer">
121
- ${avatar}
122
- <span>${count} ${count === 1 ? 'article' : 'articles'}</span>
123
- </div>
124
- </div>
125
- `;
126
- }
127
-
128
- _renderIcon(icon) {
129
- if (!icon) return this._getFolderIcon();
130
- if (icon.startsWith('<svg')) return icon;
131
- // Iconify string — render placeholder, then fetch async
132
- return this._getFolderIcon();
133
- }
134
-
135
- async _resolvePhosphorIcon(el, iconStr) {
136
- // iconStr e.g. "ph:house-line-duotone"
137
- const [set, name] = iconStr.split(':');
138
- if (!set || !name) return;
139
- try {
140
- const res = await fetch(`https://api.iconify.design/${set}/${name}.svg`);
141
- if (!res.ok) return;
142
- const svg = await res.text();
143
- if (svg && svg.startsWith('<svg')) {
144
- el.innerHTML = svg;
145
- const s = el.querySelector('svg');
146
- if (s) {
147
- s.setAttribute('width', '16');
148
- s.setAttribute('height', '16');
149
- }
150
- }
151
- } catch (e) {
152
- // keep fallback folder icon
153
- }
154
- }
155
-
156
- _getFolderIcon() {
157
- return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" width="20" height="20">
158
- <rect width="256" height="256" fill="none"/>
159
- <path d="M216,208H40a8,8,0,0,1-8-8V64a8,8,0,0,1,8-8H93.33a8,8,0,0,1,4.8,1.6l27.74,20.8a8,8,0,0,0,4.8,1.6H216a8,8,0,0,1,8,8V200A8,8,0,0,1,216,208Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
160
- </svg>`;
161
- }
162
-
163
- _renderAuthorAvatar(collection) {
164
- const author = collection.author;
165
- if (!author) return '';
166
-
167
- if (author.picture) {
168
- return `<img class="messenger-help-author-avatar" src="${author.picture}" alt="${author.name}" />`;
169
- }
170
-
171
- const color = this._getAvatarColor(collection.id);
172
- const initials = this._getInitials(author.name);
173
- return `
174
- <div class="messenger-help-author-avatar messenger-help-author-initials"
175
- style="background:${color.bg};color:${color.text}">
176
- ${initials}
97
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256" class="messenger-help-collection-arrow">
98
+ <path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"></path>
99
+ </svg>
177
100
  </div>
178
101
  `;
179
102
  }
180
103
 
181
- _getAvatarColor(id) {
182
- const hash = id.split('').reduce((acc, ch) => acc + ch.charCodeAt(0), 0);
183
- return this._avatarColors[hash % this._avatarColors.length];
184
- }
185
-
186
- _getInitials(name) {
187
- return name
188
- .split(' ')
189
- .map((n) => n[0])
190
- .join('')
191
- .toUpperCase()
192
- .slice(0, 2);
193
- }
194
-
195
104
  _renderEmptyState() {
196
105
  const isSearching = this.state.helpSearchQuery;
197
106
 
@@ -262,7 +171,9 @@ export class HelpView {
262
171
  }
263
172
 
264
173
  destroy() {
265
- if (this._unsubscribe) this._unsubscribe();
174
+ if (this._unsubscribe) {
175
+ this._unsubscribe();
176
+ }
266
177
  if (this.element && this.element.parentNode) {
267
178
  this.element.parentNode.removeChild(this.element);
268
179
  }