@product7/product7-js 0.6.7 → 0.6.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/dist/product7-js.js +280 -12
- package/dist/product7-js.js.map +1 -1
- package/dist/product7-js.min.js +1 -1
- package/dist/product7-js.min.js.map +1 -1
- package/package.json +1 -1
- package/src/styles/liveChat-components.js +159 -0
- package/src/styles/liveChat-core.js +4 -0
- package/src/widgets/LiveChatWidget.js +2 -0
- package/src/widgets/liveChat/components/LiveChatPanel.js +3 -2
- package/src/widgets/liveChat/views/FeedbackFormView.js +104 -0
- package/src/widgets/liveChat/views/HomeView.js +8 -10
package/package.json
CHANGED
|
@@ -839,4 +839,163 @@
|
|
|
839
839
|
opacity: 0.7;
|
|
840
840
|
cursor: not-allowed;
|
|
841
841
|
}
|
|
842
|
+
|
|
843
|
+
/* ========================================
|
|
844
|
+
FEEDBACK FORM VIEW
|
|
845
|
+
======================================== */
|
|
846
|
+
|
|
847
|
+
.liveChat-feedback-view {
|
|
848
|
+
display: flex;
|
|
849
|
+
flex-direction: column;
|
|
850
|
+
height: 100%;
|
|
851
|
+
overflow: hidden;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.liveChat-feedback-header {
|
|
855
|
+
display: flex;
|
|
856
|
+
align-items: center;
|
|
857
|
+
gap: var(--spacing-3);
|
|
858
|
+
padding: var(--spacing-4) var(--spacing-4);
|
|
859
|
+
border-bottom: 1px solid var(--border-color);
|
|
860
|
+
flex-shrink: 0;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
.liveChat-feedback-title {
|
|
864
|
+
font-size: var(--font-size-base);
|
|
865
|
+
font-weight: var(--font-weight-semibold);
|
|
866
|
+
color: var(--text-primary);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
.liveChat-feedback-body {
|
|
870
|
+
display: flex;
|
|
871
|
+
flex-direction: column;
|
|
872
|
+
gap: var(--spacing-4);
|
|
873
|
+
padding: var(--spacing-5) var(--spacing-4);
|
|
874
|
+
flex: 1;
|
|
875
|
+
overflow-y: auto;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
.liveChat-feedback-prompt {
|
|
879
|
+
margin: 0;
|
|
880
|
+
font-size: var(--font-size-sm);
|
|
881
|
+
color: var(--text-secondary);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
.liveChat-feedback-input {
|
|
886
|
+
width: 100%;
|
|
887
|
+
border: 1px solid var(--border-color);
|
|
888
|
+
border-radius: var(--radius-md);
|
|
889
|
+
padding: var(--spacing-3);
|
|
890
|
+
font-size: var(--font-size-sm);
|
|
891
|
+
font-family: inherit;
|
|
892
|
+
color: var(--text-primary);
|
|
893
|
+
background: var(--msg-bg);
|
|
894
|
+
box-sizing: border-box;
|
|
895
|
+
transition: border-color var(--transition-fast);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
.liveChat-feedback-input::placeholder {
|
|
899
|
+
color: var(--msg-text-secondary);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
.liveChat-feedback-input:focus {
|
|
903
|
+
outline: none;
|
|
904
|
+
border-color: var(--color-primary);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
.liveChat-feedback-textarea {
|
|
908
|
+
width: 100%;
|
|
909
|
+
resize: none;
|
|
910
|
+
border: 1px solid var(--border-color);
|
|
911
|
+
border-radius: var(--radius-md);
|
|
912
|
+
padding: var(--spacing-3);
|
|
913
|
+
font-size: var(--font-size-sm);
|
|
914
|
+
font-family: inherit;
|
|
915
|
+
color: var(--text-primary);
|
|
916
|
+
background: var(--msg-bg);
|
|
917
|
+
box-sizing: border-box;
|
|
918
|
+
transition: border-color var(--transition-fast);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
.liveChat-feedback-textarea::placeholder {
|
|
922
|
+
color: var(--msg-text-secondary);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
.liveChat-feedback-textarea:focus {
|
|
926
|
+
outline: none;
|
|
927
|
+
border-color: var(--color-primary);
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
.liveChat-feedback-submit {
|
|
931
|
+
display: flex;
|
|
932
|
+
align-items: center;
|
|
933
|
+
justify-content: center;
|
|
934
|
+
padding: var(--spacing-3);
|
|
935
|
+
border-radius: var(--radius-md);
|
|
936
|
+
font-size: var(--font-size-sm);
|
|
937
|
+
font-weight: var(--font-weight-medium);
|
|
938
|
+
font-family: inherit;
|
|
939
|
+
cursor: pointer;
|
|
940
|
+
border: none;
|
|
941
|
+
background: var(--color-primary);
|
|
942
|
+
color: #ffffff;
|
|
943
|
+
transition: all var(--transition-fast);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
.liveChat-feedback-submit:hover:not(:disabled) {
|
|
947
|
+
background: var(--color-primary-hover);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
.liveChat-feedback-submit:disabled {
|
|
951
|
+
opacity: 0.5;
|
|
952
|
+
cursor: not-allowed;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
.liveChat-feedback-thankyou {
|
|
956
|
+
display: flex;
|
|
957
|
+
flex-direction: column;
|
|
958
|
+
align-items: center;
|
|
959
|
+
justify-content: center;
|
|
960
|
+
flex: 1;
|
|
961
|
+
padding: var(--spacing-6) var(--spacing-4);
|
|
962
|
+
text-align: center;
|
|
963
|
+
gap: var(--spacing-3);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
.liveChat-feedback-thankyou-emoji {
|
|
967
|
+
font-size: 48px;
|
|
968
|
+
line-height: 1;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
.liveChat-feedback-thankyou h3 {
|
|
972
|
+
margin: 0;
|
|
973
|
+
font-size: var(--font-size-lg);
|
|
974
|
+
font-weight: var(--font-weight-semibold);
|
|
975
|
+
color: var(--text-primary);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
.liveChat-feedback-thankyou p {
|
|
979
|
+
margin: 0;
|
|
980
|
+
font-size: var(--font-size-sm);
|
|
981
|
+
color: var(--text-secondary);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
.liveChat-feedback-done-btn {
|
|
985
|
+
margin-top: var(--spacing-2);
|
|
986
|
+
padding: var(--spacing-2) var(--spacing-5);
|
|
987
|
+
border-radius: var(--radius-md);
|
|
988
|
+
font-size: var(--font-size-sm);
|
|
989
|
+
font-weight: var(--font-weight-medium);
|
|
990
|
+
font-family: inherit;
|
|
991
|
+
cursor: pointer;
|
|
992
|
+
border: 1px solid var(--border-color);
|
|
993
|
+
background: transparent;
|
|
994
|
+
color: var(--text-primary);
|
|
995
|
+
transition: all var(--transition-fast);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
.liveChat-feedback-done-btn:hover {
|
|
999
|
+
background: var(--bg-secondary);
|
|
1000
|
+
}
|
|
842
1001
|
`;
|
|
@@ -13,6 +13,7 @@ import { ChatView } from './liveChat/views/ChatView.js';
|
|
|
13
13
|
import { ConversationsView } from './liveChat/views/ConversationsView.js';
|
|
14
14
|
import { HelpView } from './liveChat/views/HelpView.js';
|
|
15
15
|
import { HomeView } from './liveChat/views/HomeView.js';
|
|
16
|
+
import { FeedbackFormView } from './liveChat/views/FeedbackFormView.js';
|
|
16
17
|
import { PreChatFormView } from './liveChat/views/PreChatFormView.js';
|
|
17
18
|
|
|
18
19
|
export class LiveChatWidget extends BaseWidget {
|
|
@@ -208,6 +209,7 @@ export class LiveChatWidget extends BaseWidget {
|
|
|
208
209
|
this.panel.registerView('messages', ConversationsView);
|
|
209
210
|
this.panel.registerView('chat', ChatView);
|
|
210
211
|
this.panel.registerView('prechat', PreChatFormView);
|
|
212
|
+
this.panel.registerView('feedback', FeedbackFormView);
|
|
211
213
|
this.panel.registerView('help', HelpView);
|
|
212
214
|
this.panel.registerView('changelog', ChangelogView);
|
|
213
215
|
|
|
@@ -95,11 +95,12 @@ export class LiveChatPanel {
|
|
|
95
95
|
</div>`;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
// Hide nav in chat and
|
|
98
|
+
// Hide nav in chat, prechat and feedback views
|
|
99
99
|
if (navContainer) {
|
|
100
100
|
const hideNav =
|
|
101
101
|
this.state.currentView === 'chat' ||
|
|
102
|
-
this.state.currentView === 'prechat'
|
|
102
|
+
this.state.currentView === 'prechat' ||
|
|
103
|
+
this.state.currentView === 'feedback';
|
|
103
104
|
navContainer.style.display = hideNav ? 'none' : '';
|
|
104
105
|
}
|
|
105
106
|
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export class FeedbackFormView {
|
|
2
|
+
constructor(state, options = {}) {
|
|
3
|
+
this.state = state;
|
|
4
|
+
this.options = options;
|
|
5
|
+
this.element = null;
|
|
6
|
+
this._isSubmitting = false;
|
|
7
|
+
this._selectedRating = null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
render() {
|
|
11
|
+
this.element = document.createElement('div');
|
|
12
|
+
this.element.className = 'liveChat-view liveChat-feedback-view';
|
|
13
|
+
this._renderForm();
|
|
14
|
+
return this.element;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_renderForm() {
|
|
18
|
+
this.element.innerHTML = `
|
|
19
|
+
<div class="liveChat-feedback-header">
|
|
20
|
+
<button class="sdk-btn-icon liveChat-feedback-back-btn">
|
|
21
|
+
<iconify-icon icon="ph:arrow-left" width="20" height="20"></iconify-icon>
|
|
22
|
+
</button>
|
|
23
|
+
<span class="liveChat-feedback-title">Leave us feedback</span>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="liveChat-feedback-body">
|
|
26
|
+
<p class="liveChat-feedback-prompt">Share your thoughts with us. We read every message.</p>
|
|
27
|
+
<input
|
|
28
|
+
type="text"
|
|
29
|
+
class="liveChat-feedback-input"
|
|
30
|
+
placeholder="Title"
|
|
31
|
+
/>
|
|
32
|
+
<textarea
|
|
33
|
+
class="liveChat-feedback-textarea"
|
|
34
|
+
placeholder="Your feedback..."
|
|
35
|
+
rows="5"
|
|
36
|
+
></textarea>
|
|
37
|
+
<button class="liveChat-feedback-submit">Send feedback</button>
|
|
38
|
+
</div>
|
|
39
|
+
`;
|
|
40
|
+
this._attachEvents();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
_renderThankYou() {
|
|
44
|
+
this.element.innerHTML = `
|
|
45
|
+
<div class="liveChat-feedback-header">
|
|
46
|
+
<button class="sdk-btn-icon liveChat-feedback-back-btn">
|
|
47
|
+
<iconify-icon icon="ph:arrow-left" width="20" height="20"></iconify-icon>
|
|
48
|
+
</button>
|
|
49
|
+
<span class="liveChat-feedback-title">Leave us feedback</span>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="liveChat-feedback-thankyou">
|
|
52
|
+
<span class="liveChat-feedback-thankyou-emoji">🙏</span>
|
|
53
|
+
<h3>Thanks for your feedback!</h3>
|
|
54
|
+
<p>We appreciate you taking the time to share your thoughts.</p>
|
|
55
|
+
<button class="liveChat-feedback-done-btn">Done</button>
|
|
56
|
+
</div>
|
|
57
|
+
`;
|
|
58
|
+
this.element.querySelector('.liveChat-feedback-back-btn').addEventListener('click', () => {
|
|
59
|
+
this.state.setView('home');
|
|
60
|
+
});
|
|
61
|
+
this.element.querySelector('.liveChat-feedback-done-btn').addEventListener('click', () => {
|
|
62
|
+
this.state.setView('home');
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
_attachEvents() {
|
|
67
|
+
this.element.querySelector('.liveChat-feedback-back-btn').addEventListener('click', () => {
|
|
68
|
+
this.state.setView('home');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const submitBtn = this.element.querySelector('.liveChat-feedback-submit');
|
|
72
|
+
submitBtn.addEventListener('click', async () => {
|
|
73
|
+
if (this._isSubmitting) return;
|
|
74
|
+
const title = this.element.querySelector('.liveChat-feedback-input').value.trim();
|
|
75
|
+
const message = this.element.querySelector('.liveChat-feedback-textarea').value.trim();
|
|
76
|
+
await this._submit(title, message);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async _submit(title, message) {
|
|
81
|
+
this._isSubmitting = true;
|
|
82
|
+
const submitBtn = this.element.querySelector('.liveChat-feedback-submit');
|
|
83
|
+
if (submitBtn) {
|
|
84
|
+
submitBtn.disabled = true;
|
|
85
|
+
submitBtn.textContent = 'Sending...';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
if (this.options.onSubmitFeedback) {
|
|
90
|
+
await this.options.onSubmitFeedback({ title, message });
|
|
91
|
+
}
|
|
92
|
+
} catch (e) {
|
|
93
|
+
console.warn('[FeedbackFormView] Submit error:', e);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this._renderThankYou();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
destroy() {
|
|
100
|
+
if (this.element && this.element.parentNode) {
|
|
101
|
+
this.element.parentNode.removeChild(this.element);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -136,8 +136,11 @@
|
|
|
136
136
|
const sendIcon = `<iconify-icon icon="ph:paper-plane-right" width="20" height="20" style="flex-shrink: 0;"></iconify-icon>`;
|
|
137
137
|
const caretIcon = `<iconify-icon icon="ph:caret-right" width="20" height="20" style="flex-shrink: 0;"></iconify-icon>`;
|
|
138
138
|
|
|
139
|
-
const
|
|
140
|
-
|
|
139
|
+
const isUnavailable = this.state.businessHoursState === 'offline' || this.state.businessHoursState === 'away';
|
|
140
|
+
const buttonLabel = isUnavailable ? 'Leave us a message' : this.state.startButtonText;
|
|
141
|
+
const buttonSubtext = isUnavailable
|
|
142
|
+
? "We'll get back to you when we're back"
|
|
143
|
+
: (this.state.responseTime || 'We typically reply within a few minutes');
|
|
141
144
|
|
|
142
145
|
const recentCardHtml = openConversation
|
|
143
146
|
? this._renderRecentMessageCard(openConversation)
|
|
@@ -147,8 +150,8 @@
|
|
|
147
150
|
${recentCardHtml}
|
|
148
151
|
<button class="liveChat-home-message-btn">
|
|
149
152
|
<div class="liveChat-home-continue-info">
|
|
150
|
-
<span class="liveChat-home-continue-label">${
|
|
151
|
-
<span class="liveChat-home-message-subtext">${
|
|
153
|
+
<span class="liveChat-home-continue-label">${buttonLabel}</span>
|
|
154
|
+
<span class="liveChat-home-message-subtext">${buttonSubtext}</span>
|
|
152
155
|
</div>
|
|
153
156
|
${sendIcon}
|
|
154
157
|
</button>
|
|
@@ -312,12 +315,7 @@
|
|
|
312
315
|
const feedbackBtn = this.element.querySelector('.liveChat-feedback-btn');
|
|
313
316
|
if (feedbackBtn) {
|
|
314
317
|
feedbackBtn.addEventListener('click', () => {
|
|
315
|
-
|
|
316
|
-
this.state.setOpen(false);
|
|
317
|
-
this.options.onFeedbackClick();
|
|
318
|
-
} else if (this.state.urls?.feedback) {
|
|
319
|
-
window.open(this.state.urls.feedback, '_blank');
|
|
320
|
-
}
|
|
318
|
+
this.state.setView('feedback');
|
|
321
319
|
});
|
|
322
320
|
}
|
|
323
321
|
|