@product7/feedback-sdk 1.2.0 → 1.2.2

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.2.0",
3
+ "version": "1.2.2",
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",
@@ -43,12 +43,12 @@ export const CSS_STYLES = `
43
43
  display: flex;
44
44
  align-items: center;
45
45
  justify-content: center;
46
- gap: 12px;
47
- height: 44px;
48
- overflow: hidden;
49
- border-radius: 0.5rem;
46
+ gap: 8px;
47
+ height: 48px;
48
+ overflow: visible;
49
+ border-radius: 9999px;
50
50
  border: none;
51
- padding: 10px 16px;
51
+ padding: 12px 20px;
52
52
  font-size: 14px;
53
53
  font-weight: 500;
54
54
  font-family: inherit;
@@ -56,12 +56,13 @@ export const CSS_STYLES = `
56
56
  transition: all 0.3s ease;
57
57
  color: white;
58
58
  background: #155EEF;
59
- box-shadow: 0 1px 2px 0 rgba(16, 24, 40, 0.05);
59
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
60
+ width: fit-content;
60
61
  }
61
62
 
62
63
  .feedback-trigger-btn:hover:not(:disabled) {
63
- background: #004EEB;
64
- box-shadow: 0 1px 2px 0 rgba(16, 24, 40, 0.1);
64
+ transform: translateY(-2px);
65
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
65
66
  }
66
67
 
67
68
  .feedback-trigger-btn:disabled {
@@ -74,69 +75,64 @@ export const CSS_STYLES = `
74
75
  outline-offset: 2px;
75
76
  }
76
77
 
77
- .feedback-close-btn {
78
+ .feedback-icon {
79
+ flex-shrink: 0;
80
+ }
81
+
82
+ .feedback-minimize-icon,
83
+ .feedback-expand-icon {
78
84
  position: absolute;
79
- top: -8px;
80
- right: -8px;
85
+ top: -6px;
86
+ right: -6px;
81
87
  width: 24px;
82
88
  height: 24px;
89
+ padding: 4px;
90
+ display: flex;
91
+ align-items: center;
92
+ justify-content: center;
93
+ background: white;
83
94
  border-radius: 50%;
84
- background: #EF4444;
85
- border: 2px solid white;
86
- color: white;
95
+ opacity: 0;
96
+ transition: opacity 0.2s ease;
97
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
87
98
  cursor: pointer;
88
99
  display: flex;
89
100
  align-items: center;
90
101
  justify-content: center;
91
- opacity: 0;
92
- transition: all 0.2s ease;
93
- z-index: 10;
94
- padding: 0;
95
- }
96
-
97
- .feedback-widget-button:hover .feedback-close-btn {
98
- opacity: 1;
99
102
  }
100
103
 
101
- .feedback-close-btn:hover {
102
- background: #DC2626;
103
- transform: scale(1.1);
104
- }
105
-
106
- .feedback-close-btn:focus-visible {
107
- outline: 2px solid #155EEF;
108
- outline-offset: 2px;
104
+ .feedback-minimize-icon svg,
105
+ .feedback-expand-icon svg {
106
+ width: 16px;
107
+ height: 16px;
108
+ display: block;
109
+ fill: #155EEF;
109
110
  }
110
111
 
111
- .feedback-close-btn svg {
112
- width: 10px;
113
- height: 10px;
112
+ /* Show minimize icon on hover when expanded */
113
+ .feedback-widget-button:not(.minimized) .feedback-trigger-btn:hover .feedback-minimize-icon {
114
+ opacity: 1;
114
115
  }
115
116
 
116
- /* Minimized state */
117
- .feedback-widget-button.minimized {
118
- transform: scale(0.4);
119
- opacity: 0.3;
120
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
117
+ /* Minimized state - just icon */
118
+ .feedback-widget-button.minimized .feedback-trigger-btn {
119
+ padding: 12px;
120
+ width: 48px;
121
+ height: 48px;
122
+ justify-content: center;
121
123
  }
122
124
 
123
- .feedback-widget-button.minimized:hover {
124
- opacity: 0.6;
125
- transform: scale(0.5);
125
+ .feedback-widget-button.minimized .feedback-text {
126
+ display: none;
126
127
  }
127
128
 
128
- .feedback-widget-button.minimized .feedback-trigger-btn {
129
- pointer-events: none;
129
+ .feedback-widget-button.minimized .feedback-minimize-icon {
130
+ display: none;
130
131
  }
131
132
 
132
- .feedback-widget-button.minimized .feedback-close-btn {
133
+ /* Show expand icon on hover when minimized */
134
+ .feedback-widget-button.minimized .feedback-trigger-btn:hover .feedback-expand-icon {
133
135
  opacity: 1;
134
- background: #10B981;
135
- pointer-events: auto;
136
- }
137
-
138
- .feedback-widget-button.minimized .feedback-close-btn:hover {
139
- background: #059669;
140
136
  }
141
137
 
142
138
  /* Side Panel Styles */
@@ -305,7 +301,7 @@ export const CSS_STYLES = `
305
301
 
306
302
  .feedback-form-group input:focus {
307
303
  border-color: #155EEF;
308
- box-shadow: 0 0 0 3px rgba(21, 94, 239, 0.1);
304
+ box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
309
305
  }
310
306
 
311
307
  .feedback-form-group input:focus-visible {
@@ -335,7 +331,7 @@ export const CSS_STYLES = `
335
331
 
336
332
  .feedback-form-group textarea:focus {
337
333
  border-color: #155EEF;
338
- box-shadow: 0 0 0 3px rgba(21, 94, 239, 0.1);
334
+ box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
339
335
  }
340
336
 
341
337
  .feedback-form-group textarea:focus-visible {
@@ -388,11 +384,11 @@ export const CSS_STYLES = `
388
384
  }
389
385
 
390
386
  .feedback-btn-submit:hover:not(:disabled) {
391
- background: #1A56DB;
387
+ background: #4338ca;
392
388
  }
393
389
 
394
390
  .feedback-btn-submit:active:not(:disabled) {
395
- background: #1E429F;
391
+ background: #3730a3;
396
392
  }
397
393
 
398
394
  .feedback-btn-cancel {
@@ -599,6 +595,20 @@ export const CSS_STYLES = `
599
595
  left: 16px;
600
596
  min-width: auto;
601
597
  }
598
+
599
+ .feedback-minimize-icon,
600
+ .feedback-expand-icon {
601
+ top: -4px;
602
+ right: -4px;
603
+ width: 20px;
604
+ height: 20px;
605
+ }
606
+
607
+ .feedback-minimize-icon svg,
608
+ .feedback-expand-icon svg {
609
+ width: 14px;
610
+ height: 14px;
611
+ }
602
612
  }
603
613
 
604
614
  @media (prefers-reduced-motion: reduce) {
@@ -606,7 +616,9 @@ export const CSS_STYLES = `
606
616
  .feedback-btn,
607
617
  .feedback-panel,
608
618
  .feedback-panel-backdrop,
609
- .feedback-success-notification {
619
+ .feedback-success-notification,
620
+ .feedback-minimize-icon,
621
+ .feedback-expand-icon {
610
622
  transition: none;
611
623
  animation: none;
612
624
  }
@@ -619,35 +631,5 @@ export const CSS_STYLES = `
619
631
  .feedback-success-notification {
620
632
  display: none !important;
621
633
  }
622
-
623
- @media (max-width: 768px) {
624
- .feedback-close-btn {
625
- top: -6px;
626
- right: -6px;
627
- width: 20px;
628
- height: 20px;
629
- }
630
-
631
- .feedback-close-btn svg {
632
- width: 8px;
633
- height: 8px;
634
- }
635
-
636
- .feedback-widget-button.minimized {
637
- transform: scale(0.5);
638
- }
639
-
640
- .feedback-widget-button.minimized:hover {
641
- transform: scale(0.6);
642
- }
643
- }
644
-
645
- /* Reduced motion support */
646
- @media (prefers-reduced-motion: reduce) {
647
- .feedback-close-btn,
648
- .feedback-widget-button.minimized {
649
- transition: none;
650
- }
651
- }
652
634
  }
653
- `;
635
+ `;
@@ -1,5 +1,4 @@
1
1
  import { BaseWidget } from './BaseWidget.js';
2
-
3
2
  export class ButtonWidget extends BaseWidget {
4
3
  constructor(options) {
5
4
  super({ ...options, type: 'button' });
@@ -11,16 +10,22 @@ export class ButtonWidget extends BaseWidget {
11
10
  button.className = `feedback-widget feedback-widget-button theme-${this.options.theme} position-${this.options.position}`;
12
11
  button.innerHTML = `
13
12
  <button class="feedback-trigger-btn" type="button">
14
- <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
15
- <path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"/>
16
- <path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"/>
17
- </svg>
18
- Feedback
19
- </button>
20
- <button class="feedback-close-btn" type="button" title="Hide feedback button">
21
- <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor">
22
- <path d="M14 1.41L12.59 0L7 5.59L1.41 0L0 1.41L5.59 7L0 12.59L1.41 14L7 8.41L12.59 14L14 12.59L8.41 7L14 1.41Z"/>
13
+ <svg class="feedback-icon" width="20" height="20" viewBox="0 0 256 256" fill="currentColor">
14
+ <path d="M216,80H184V48a16,16,0,0,0-16-16H40A16,16,0,0,0,24,48V176a8,8,0,0,0,13,6.22L72,154V184a16,16,0,0,0,16,16h93.59L219,230.22a8,8,0,0,0,5,1.78,8,8,0,0,0,8-8V96A16,16,0,0,0,216,80ZM66.55,137.78,40,159.25V48H168v88H71.58A8,8,0,0,0,66.55,137.78ZM216,207.25l-26.55-21.47a8,8,0,0,0-5-1.78H88V152h80a16,16,0,0,0,16-16V96h32Z"/>
23
15
  </svg>
16
+ <span class="feedback-text">Feedback</span>
17
+
18
+ <div class="feedback-minimize-icon">
19
+ <svg viewBox="0 0 256 256">
20
+ <path d="M213.66,53.66,163.31,104H192a8,8,0,0,1,0,16H144a8,8,0,0,1-8-8V64a8,8,0,0,1,16,0V92.69l50.34-50.35a8,8,0,0,1,11.32,11.32ZM112,136H64a8,8,0,0,0,0,16H92.69L42.34,202.34a8,8,0,0,0,11.32,11.32L104,163.31V192a8,8,0,0,0,16,0V144A8,8,0,0,0,112,136Z"/>
21
+ </svg>
22
+ </div>
23
+
24
+ <div class="feedback-expand-icon">
25
+ <svg viewBox="0 0 256 256">
26
+ <path d="M112,40V64.69L61.66,14.34A8,8,0,0,0,50.34,25.66L100.69,76H72a8,8,0,0,0,0,16h48a8,8,0,0,0,8-8V36A8,8,0,0,0,112,40Zm131.06,70.61a8,8,0,0,0-8.72,1.73L184,162.69V136a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8h48a8,8,0,0,0,0-16H195.31l50.35-50.34A8,8,0,0,0,243.06,110.61Z"/>
27
+ </svg>
28
+ </div>
24
29
  </button>
25
30
  `;
26
31
 
@@ -33,55 +38,57 @@ export class ButtonWidget extends BaseWidget {
33
38
 
34
39
  _attachEvents() {
35
40
  const button = this.element.querySelector('.feedback-trigger-btn');
36
- const closeBtn = this.element.querySelector('.feedback-close-btn');
41
+ const minimizeIcon = this.element.querySelector('.feedback-minimize-icon');
42
+ const expandIcon = this.element.querySelector('.feedback-expand-icon');
37
43
 
38
- button.addEventListener('click', this.openPanel);
39
-
40
- closeBtn.addEventListener('click', (e) => {
41
- e.stopPropagation();
42
- this.toggleMinimize();
44
+ button.addEventListener('click', (e) => {
45
+ const clickedMinimize = e.target.closest('.feedback-minimize-icon');
46
+ const clickedExpand = e.target.closest('.feedback-expand-icon');
47
+
48
+ if (clickedMinimize) {
49
+ e.stopPropagation();
50
+ this.minimize();
51
+ } else if (clickedExpand) {
52
+ e.stopPropagation();
53
+ this.restore();
54
+ } else {
55
+ if (!this.isMinimized) {
56
+ this.openPanel();
57
+ }
58
+ }
43
59
  });
44
60
 
45
61
  button.addEventListener('mouseenter', () => {
46
- if (!this.state.isSubmitting) {
62
+ if (!this.state.isSubmitting && !this.isMinimized) {
47
63
  button.style.transform = 'translateY(-2px)';
48
64
  }
49
65
  });
50
66
 
51
67
  button.addEventListener('mouseleave', () => {
52
- button.style.transform = 'translateY(0)';
68
+ if (!this.isMinimized) {
69
+ button.style.transform = 'translateY(0)';
70
+ }
53
71
  });
54
72
  }
55
73
 
56
- toggleMinimize() {
57
- this.isMinimized = !this.isMinimized;
58
-
59
- if (this.isMinimized) {
60
- this.element.classList.add('minimized');
61
- localStorage.setItem('feedback-widget-minimized', 'true');
62
- } else {
63
- this.element.classList.remove('minimized');
64
- localStorage.removeItem('feedback-widget-minimized');
65
- }
74
+ minimize() {
75
+ this.isMinimized = true;
76
+ this.element.classList.add('minimized');
77
+ }
78
+
79
+ restore() {
80
+ this.isMinimized = false;
81
+ this.element.classList.remove('minimized');
66
82
  }
67
83
 
68
84
  mount(container) {
69
85
  super.mount(container);
70
-
71
- // Check if it was previously minimized
72
- if (localStorage.getItem('feedback-widget-minimized') === 'true') {
73
- this.isMinimized = true;
74
- this.element.classList.add('minimized');
75
- }
76
86
  }
77
87
 
78
88
  updateText(text) {
79
- const button = this.element?.querySelector('.feedback-trigger-btn');
80
- if (button) {
81
- const textNode = button.childNodes[button.childNodes.length - 1];
82
- if (textNode && textNode.nodeType === Node.TEXT_NODE) {
83
- textNode.textContent = text;
84
- }
89
+ const textEl = this.element?.querySelector('.feedback-text');
90
+ if (textEl) {
91
+ textEl.textContent = text;
85
92
  }
86
93
  }
87
94