@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/dist/feedback-sdk.js +115 -125
- package/dist/feedback-sdk.js.map +1 -1
- package/dist/feedback-sdk.min.js +1 -1
- package/dist/feedback-sdk.min.js.map +1 -1
- package/package.json +1 -1
- package/src/styles/styles.js +68 -86
- package/src/widgets/ButtonWidget.js +47 -40
package/package.json
CHANGED
package/src/styles/styles.js
CHANGED
|
@@ -43,12 +43,12 @@ export const CSS_STYLES = `
|
|
|
43
43
|
display: flex;
|
|
44
44
|
align-items: center;
|
|
45
45
|
justify-content: center;
|
|
46
|
-
gap:
|
|
47
|
-
height:
|
|
48
|
-
overflow:
|
|
49
|
-
border-radius:
|
|
46
|
+
gap: 8px;
|
|
47
|
+
height: 48px;
|
|
48
|
+
overflow: visible;
|
|
49
|
+
border-radius: 9999px;
|
|
50
50
|
border: none;
|
|
51
|
-
padding:
|
|
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
|
|
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
|
-
|
|
64
|
-
box-shadow: 0
|
|
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-
|
|
78
|
+
.feedback-icon {
|
|
79
|
+
flex-shrink: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.feedback-minimize-icon,
|
|
83
|
+
.feedback-expand-icon {
|
|
78
84
|
position: absolute;
|
|
79
|
-
top: -
|
|
80
|
-
right: -
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
|
124
|
-
|
|
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-
|
|
129
|
-
|
|
129
|
+
.feedback-widget-button.minimized .feedback-minimize-icon {
|
|
130
|
+
display: none;
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
|
|
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(
|
|
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(
|
|
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: #
|
|
387
|
+
background: #4338ca;
|
|
392
388
|
}
|
|
393
389
|
|
|
394
390
|
.feedback-btn-submit:active:not(:disabled) {
|
|
395
|
-
background: #
|
|
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
|
|
15
|
-
<path d="
|
|
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
|
|
41
|
+
const minimizeIcon = this.element.querySelector('.feedback-minimize-icon');
|
|
42
|
+
const expandIcon = this.element.querySelector('.feedback-expand-icon');
|
|
37
43
|
|
|
38
|
-
button.addEventListener('click',
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
68
|
+
if (!this.isMinimized) {
|
|
69
|
+
button.style.transform = 'translateY(0)';
|
|
70
|
+
}
|
|
53
71
|
});
|
|
54
72
|
}
|
|
55
73
|
|
|
56
|
-
|
|
57
|
-
this.isMinimized =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
|
80
|
-
if (
|
|
81
|
-
|
|
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
|
|