@v-tilt/browser 1.4.0 → 1.4.1
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/array.full.js +1 -1
- package/dist/array.full.js.map +1 -1
- package/dist/array.js +1 -1
- package/dist/array.js.map +1 -1
- package/dist/array.no-external.js.map +1 -1
- package/dist/chat.js.map +1 -1
- package/dist/external-scripts-loader.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/dist/module.no-external.js.map +1 -1
- package/lib/entrypoints/external-scripts-loader.js +1 -1
- package/lib/extensions/chat/chat-wrapper.js +19 -19
- package/lib/extensions/chat/chat.js +194 -188
- package/package.json +66 -66
|
@@ -367,26 +367,26 @@ class ChatWrapper {
|
|
|
367
367
|
const color = mergedConfig.color || "#6366f1";
|
|
368
368
|
const bubble = document.createElement("div");
|
|
369
369
|
bubble.id = "vtilt-chat-bubble";
|
|
370
|
-
bubble.setAttribute("style", `
|
|
371
|
-
position: fixed;
|
|
372
|
-
bottom: 20px;
|
|
373
|
-
${position === "bottom-right" ? "right: 20px;" : "left: 20px;"}
|
|
374
|
-
width: 60px;
|
|
375
|
-
height: 60px;
|
|
376
|
-
border-radius: 50%;
|
|
377
|
-
background: ${color};
|
|
378
|
-
cursor: pointer;
|
|
379
|
-
display: flex;
|
|
380
|
-
align-items: center;
|
|
381
|
-
justify-content: center;
|
|
382
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
383
|
-
transition: transform 0.2s, box-shadow 0.2s;
|
|
384
|
-
z-index: 999999;
|
|
370
|
+
bubble.setAttribute("style", `
|
|
371
|
+
position: fixed;
|
|
372
|
+
bottom: 20px;
|
|
373
|
+
${position === "bottom-right" ? "right: 20px;" : "left: 20px;"}
|
|
374
|
+
width: 60px;
|
|
375
|
+
height: 60px;
|
|
376
|
+
border-radius: 50%;
|
|
377
|
+
background: ${color};
|
|
378
|
+
cursor: pointer;
|
|
379
|
+
display: flex;
|
|
380
|
+
align-items: center;
|
|
381
|
+
justify-content: center;
|
|
382
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
383
|
+
transition: transform 0.2s, box-shadow 0.2s;
|
|
384
|
+
z-index: 999999;
|
|
385
385
|
`.trim());
|
|
386
|
-
bubble.innerHTML = `
|
|
387
|
-
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
|
|
388
|
-
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
|
|
389
|
-
</svg>
|
|
386
|
+
bubble.innerHTML = `
|
|
387
|
+
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
|
|
388
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
|
|
389
|
+
</svg>
|
|
390
390
|
`;
|
|
391
391
|
// Hover effect
|
|
392
392
|
bubble.addEventListener("mouseenter", () => {
|
|
@@ -136,8 +136,7 @@ class LazyLoadedChat {
|
|
|
136
136
|
this._updateUI();
|
|
137
137
|
this._trackEvent(types_1.CHAT_EVENTS.WIDGET_CLOSED, {
|
|
138
138
|
$time_open_seconds: timeOpen,
|
|
139
|
-
$messages_sent: this._state.messages.filter((m) => m.sender_type === "user")
|
|
140
|
-
.length,
|
|
139
|
+
$messages_sent: this._state.messages.filter((m) => m.sender_type === "user").length,
|
|
141
140
|
});
|
|
142
141
|
}
|
|
143
142
|
toggle() {
|
|
@@ -239,7 +238,8 @@ class LazyLoadedChat {
|
|
|
239
238
|
if (!latestMessage)
|
|
240
239
|
return;
|
|
241
240
|
// Check if there are unread agent messages
|
|
242
|
-
const hasUnreadAgentMessages = this._state.messages.some((m) => (m.sender_type === "agent" || m.sender_type === "ai") &&
|
|
241
|
+
const hasUnreadAgentMessages = this._state.messages.some((m) => (m.sender_type === "agent" || m.sender_type === "ai") &&
|
|
242
|
+
!this._isMessageReadByUser(m.created_at));
|
|
243
243
|
if (!hasUnreadAgentMessages)
|
|
244
244
|
return;
|
|
245
245
|
this._state.unreadCount = 0;
|
|
@@ -342,7 +342,8 @@ class LazyLoadedChat {
|
|
|
342
342
|
this._state.channel = response.channel;
|
|
343
343
|
this._state.messages = response.messages || [];
|
|
344
344
|
// Initialize read cursors from channel
|
|
345
|
-
this._state.agentLastReadAt =
|
|
345
|
+
this._state.agentLastReadAt =
|
|
346
|
+
response.channel.agent_last_read_at || null;
|
|
346
347
|
this._initialUserReadAt = response.channel.user_last_read_at || null;
|
|
347
348
|
// Track channel started (only if new)
|
|
348
349
|
if (response.messages.length === 0 || response.messages.length === 1) {
|
|
@@ -493,9 +494,12 @@ class LazyLoadedChat {
|
|
|
493
494
|
return;
|
|
494
495
|
// Skip user's own messages - we already have them from optimistic updates
|
|
495
496
|
// The sender_id for user messages is the distinct_id
|
|
496
|
-
if (message.sender_type === "user" &&
|
|
497
|
+
if (message.sender_type === "user" &&
|
|
498
|
+
message.sender_id === this._instance.getDistinctId()) {
|
|
497
499
|
// But DO replace temp message with real one if present
|
|
498
|
-
const tempIndex = this._state.messages.findIndex((m) => m.id.startsWith("temp-") &&
|
|
500
|
+
const tempIndex = this._state.messages.findIndex((m) => m.id.startsWith("temp-") &&
|
|
501
|
+
m.content === message.content &&
|
|
502
|
+
m.sender_type === "user");
|
|
499
503
|
if (tempIndex !== -1) {
|
|
500
504
|
this._state.messages[tempIndex] = message;
|
|
501
505
|
this._updateUI();
|
|
@@ -533,7 +537,8 @@ class LazyLoadedChat {
|
|
|
533
537
|
// Only show typing for non-user senders
|
|
534
538
|
if (event.sender_type === "user")
|
|
535
539
|
return;
|
|
536
|
-
const senderName = event.sender_name ||
|
|
540
|
+
const senderName = event.sender_name ||
|
|
541
|
+
(event.sender_type === "ai" ? "AI Assistant" : "Agent");
|
|
537
542
|
this._state.isTyping = event.is_typing;
|
|
538
543
|
this._state.typingSender = event.is_typing ? senderName : null;
|
|
539
544
|
// Notify callbacks
|
|
@@ -696,19 +701,20 @@ class LazyLoadedChat {
|
|
|
696
701
|
return;
|
|
697
702
|
const theme = this._config.theme || DEFAULT_THEME;
|
|
698
703
|
// Find first unread agent message index
|
|
699
|
-
const firstUnreadIndex = this._state.messages.findIndex((m) => (m.sender_type === "agent" || m.sender_type === "ai") &&
|
|
704
|
+
const firstUnreadIndex = this._state.messages.findIndex((m) => (m.sender_type === "agent" || m.sender_type === "ai") &&
|
|
705
|
+
!this._isMessageReadByUser(m.created_at));
|
|
700
706
|
// Build HTML with unread divider
|
|
701
707
|
const messagesHtml = this._state.messages
|
|
702
708
|
.map((msg, index) => {
|
|
703
709
|
let html = "";
|
|
704
710
|
// Add unread divider before first unread message
|
|
705
711
|
if (index === firstUnreadIndex && firstUnreadIndex > 0) {
|
|
706
|
-
html += `
|
|
707
|
-
<div style="display: flex; align-items: center; gap: 12px; margin: 8px 0;">
|
|
708
|
-
<div style="flex: 1; height: 1px; background: ${theme.primaryColor}40;"></div>
|
|
709
|
-
<span style="font-size: 11px; font-weight: 500; color: ${theme.primaryColor}; padding: 0 8px;">New messages</span>
|
|
710
|
-
<div style="flex: 1; height: 1px; background: ${theme.primaryColor}40;"></div>
|
|
711
|
-
</div>
|
|
712
|
+
html += `
|
|
713
|
+
<div style="display: flex; align-items: center; gap: 12px; margin: 8px 0;">
|
|
714
|
+
<div style="flex: 1; height: 1px; background: ${theme.primaryColor}40;"></div>
|
|
715
|
+
<span style="font-size: 11px; font-weight: 500; color: ${theme.primaryColor}; padding: 0 8px;">New messages</span>
|
|
716
|
+
<div style="flex: 1; height: 1px; background: ${theme.primaryColor}40;"></div>
|
|
717
|
+
</div>
|
|
712
718
|
`;
|
|
713
719
|
}
|
|
714
720
|
html += this._getMessageHTML(msg);
|
|
@@ -726,179 +732,179 @@ class LazyLoadedChat {
|
|
|
726
732
|
var _a;
|
|
727
733
|
const position = this._config.position || DEFAULT_POSITION;
|
|
728
734
|
const isRight = position === "bottom-right";
|
|
729
|
-
return `
|
|
730
|
-
position: fixed;
|
|
731
|
-
bottom: 20px;
|
|
732
|
-
${isRight ? "right: 20px;" : "left: 20px;"}
|
|
733
|
-
z-index: 999999;
|
|
734
|
-
font-family: ${((_a = this._config.theme) === null || _a === void 0 ? void 0 : _a.fontFamily) || DEFAULT_THEME.fontFamily};
|
|
735
|
+
return `
|
|
736
|
+
position: fixed;
|
|
737
|
+
bottom: 20px;
|
|
738
|
+
${isRight ? "right: 20px;" : "left: 20px;"}
|
|
739
|
+
z-index: 999999;
|
|
740
|
+
font-family: ${((_a = this._config.theme) === null || _a === void 0 ? void 0 : _a.fontFamily) || DEFAULT_THEME.fontFamily};
|
|
735
741
|
`;
|
|
736
742
|
}
|
|
737
743
|
_getBubbleStyles() {
|
|
738
744
|
const theme = this._config.theme || DEFAULT_THEME;
|
|
739
|
-
return `
|
|
740
|
-
width: 60px;
|
|
741
|
-
height: 60px;
|
|
742
|
-
border-radius: 50%;
|
|
743
|
-
background: ${theme.primaryColor};
|
|
744
|
-
cursor: pointer;
|
|
745
|
-
display: flex;
|
|
746
|
-
align-items: center;
|
|
747
|
-
justify-content: center;
|
|
748
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
749
|
-
transition: transform 0.2s, box-shadow 0.2s;
|
|
750
|
-
position: relative;
|
|
745
|
+
return `
|
|
746
|
+
width: 60px;
|
|
747
|
+
height: 60px;
|
|
748
|
+
border-radius: 50%;
|
|
749
|
+
background: ${theme.primaryColor};
|
|
750
|
+
cursor: pointer;
|
|
751
|
+
display: flex;
|
|
752
|
+
align-items: center;
|
|
753
|
+
justify-content: center;
|
|
754
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
755
|
+
transition: transform 0.2s, box-shadow 0.2s;
|
|
756
|
+
position: relative;
|
|
751
757
|
`;
|
|
752
758
|
}
|
|
753
759
|
_getBubbleHTML() {
|
|
754
|
-
return `
|
|
755
|
-
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
|
|
756
|
-
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
|
|
757
|
-
</svg>
|
|
758
|
-
<div class="vtilt-chat-badge" style="
|
|
759
|
-
display: none;
|
|
760
|
-
position: absolute;
|
|
761
|
-
top: -5px;
|
|
762
|
-
right: -5px;
|
|
763
|
-
background: #ef4444;
|
|
764
|
-
color: white;
|
|
765
|
-
font-size: 12px;
|
|
766
|
-
font-weight: 600;
|
|
767
|
-
min-width: 20px;
|
|
768
|
-
height: 20px;
|
|
769
|
-
border-radius: 10px;
|
|
770
|
-
align-items: center;
|
|
771
|
-
justify-content: center;
|
|
772
|
-
">0</div>
|
|
760
|
+
return `
|
|
761
|
+
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
|
|
762
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
|
|
763
|
+
</svg>
|
|
764
|
+
<div class="vtilt-chat-badge" style="
|
|
765
|
+
display: none;
|
|
766
|
+
position: absolute;
|
|
767
|
+
top: -5px;
|
|
768
|
+
right: -5px;
|
|
769
|
+
background: #ef4444;
|
|
770
|
+
color: white;
|
|
771
|
+
font-size: 12px;
|
|
772
|
+
font-weight: 600;
|
|
773
|
+
min-width: 20px;
|
|
774
|
+
height: 20px;
|
|
775
|
+
border-radius: 10px;
|
|
776
|
+
align-items: center;
|
|
777
|
+
justify-content: center;
|
|
778
|
+
">0</div>
|
|
773
779
|
`;
|
|
774
780
|
}
|
|
775
781
|
_getWidgetStyles() {
|
|
776
782
|
const theme = this._config.theme || DEFAULT_THEME;
|
|
777
|
-
return `
|
|
778
|
-
display: none;
|
|
779
|
-
flex-direction: column;
|
|
780
|
-
position: absolute;
|
|
781
|
-
bottom: 80px;
|
|
782
|
-
right: 0;
|
|
783
|
-
width: 380px;
|
|
784
|
-
height: 520px;
|
|
785
|
-
background: white;
|
|
786
|
-
border-radius: ${theme.borderRadius};
|
|
787
|
-
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
|
|
788
|
-
overflow: hidden;
|
|
783
|
+
return `
|
|
784
|
+
display: none;
|
|
785
|
+
flex-direction: column;
|
|
786
|
+
position: absolute;
|
|
787
|
+
bottom: 80px;
|
|
788
|
+
right: 0;
|
|
789
|
+
width: 380px;
|
|
790
|
+
height: 520px;
|
|
791
|
+
background: white;
|
|
792
|
+
border-radius: ${theme.borderRadius};
|
|
793
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
|
|
794
|
+
overflow: hidden;
|
|
789
795
|
`;
|
|
790
796
|
}
|
|
791
797
|
_getWidgetHTML() {
|
|
792
798
|
const theme = this._config.theme || DEFAULT_THEME;
|
|
793
799
|
const greeting = this._config.greeting || "How can we help you?";
|
|
794
|
-
return `
|
|
795
|
-
<div class="vtilt-chat-header" style="
|
|
796
|
-
background: ${theme.headerBgColor};
|
|
797
|
-
color: white;
|
|
798
|
-
padding: 16px;
|
|
799
|
-
display: flex;
|
|
800
|
-
align-items: center;
|
|
801
|
-
justify-content: space-between;
|
|
802
|
-
">
|
|
803
|
-
<div style="font-weight: 600; font-size: 16px;">${greeting}</div>
|
|
804
|
-
<button class="vtilt-chat-close" style="
|
|
805
|
-
background: none;
|
|
806
|
-
border: none;
|
|
807
|
-
color: white;
|
|
808
|
-
cursor: pointer;
|
|
809
|
-
padding: 4px;
|
|
810
|
-
">
|
|
811
|
-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
812
|
-
<path d="M18 6L6 18M6 6l12 12"></path>
|
|
813
|
-
</svg>
|
|
814
|
-
</button>
|
|
815
|
-
</div>
|
|
816
|
-
|
|
817
|
-
<div class="vtilt-chat-messages" style="
|
|
818
|
-
flex: 1;
|
|
819
|
-
overflow-y: auto;
|
|
820
|
-
padding: 16px;
|
|
821
|
-
display: flex;
|
|
822
|
-
flex-direction: column;
|
|
823
|
-
gap: 12px;
|
|
824
|
-
"></div>
|
|
825
|
-
|
|
826
|
-
<div class="vtilt-chat-loader" style="
|
|
827
|
-
display: none;
|
|
828
|
-
align-items: center;
|
|
829
|
-
justify-content: center;
|
|
830
|
-
padding: 20px;
|
|
831
|
-
">
|
|
832
|
-
<div style="
|
|
833
|
-
width: 24px;
|
|
834
|
-
height: 24px;
|
|
835
|
-
border: 2px solid #e5e7eb;
|
|
836
|
-
border-top-color: ${theme.primaryColor};
|
|
837
|
-
border-radius: 50%;
|
|
838
|
-
animation: vtilt-spin 0.8s linear infinite;
|
|
839
|
-
"></div>
|
|
840
|
-
</div>
|
|
841
|
-
|
|
842
|
-
<div class="vtilt-chat-typing" style="
|
|
843
|
-
display: none;
|
|
844
|
-
padding: 8px 16px;
|
|
845
|
-
color: #6b7280;
|
|
846
|
-
font-size: 14px;
|
|
847
|
-
">
|
|
848
|
-
<span style="animation: vtilt-pulse 1.5s infinite;">Agent is typing...</span>
|
|
849
|
-
</div>
|
|
850
|
-
|
|
851
|
-
<div class="vtilt-chat-input-container" style="
|
|
852
|
-
padding: 16px;
|
|
853
|
-
border-top: 1px solid #e5e7eb;
|
|
854
|
-
display: flex;
|
|
855
|
-
gap: 8px;
|
|
856
|
-
">
|
|
857
|
-
<input
|
|
858
|
-
type="text"
|
|
859
|
-
class="vtilt-chat-input"
|
|
860
|
-
placeholder="Type a message..."
|
|
861
|
-
style="
|
|
862
|
-
flex: 1;
|
|
863
|
-
border: 1px solid #e5e7eb;
|
|
864
|
-
border-radius: 8px;
|
|
865
|
-
padding: 10px 14px;
|
|
866
|
-
font-size: 14px;
|
|
867
|
-
outline: none;
|
|
868
|
-
transition: border-color 0.2s;
|
|
869
|
-
"
|
|
870
|
-
/>
|
|
871
|
-
<button class="vtilt-chat-send" style="
|
|
872
|
-
background: ${theme.primaryColor};
|
|
873
|
-
color: white;
|
|
874
|
-
border: none;
|
|
875
|
-
border-radius: 8px;
|
|
876
|
-
padding: 10px 16px;
|
|
877
|
-
cursor: pointer;
|
|
878
|
-
font-weight: 500;
|
|
879
|
-
transition: opacity 0.2s;
|
|
880
|
-
">Send</button>
|
|
881
|
-
</div>
|
|
882
|
-
|
|
883
|
-
<style>
|
|
884
|
-
@keyframes vtilt-spin {
|
|
885
|
-
to { transform: rotate(360deg); }
|
|
886
|
-
}
|
|
887
|
-
@keyframes vtilt-pulse {
|
|
888
|
-
0%, 100% { opacity: 1; }
|
|
889
|
-
50% { opacity: 0.5; }
|
|
890
|
-
}
|
|
891
|
-
#vtilt-chat-bubble:hover {
|
|
892
|
-
transform: scale(1.05);
|
|
893
|
-
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
|
|
894
|
-
}
|
|
895
|
-
.vtilt-chat-input:focus {
|
|
896
|
-
border-color: ${theme.primaryColor} !important;
|
|
897
|
-
}
|
|
898
|
-
.vtilt-chat-send:hover {
|
|
899
|
-
opacity: 0.9;
|
|
900
|
-
}
|
|
901
|
-
</style>
|
|
800
|
+
return `
|
|
801
|
+
<div class="vtilt-chat-header" style="
|
|
802
|
+
background: ${theme.headerBgColor};
|
|
803
|
+
color: white;
|
|
804
|
+
padding: 16px;
|
|
805
|
+
display: flex;
|
|
806
|
+
align-items: center;
|
|
807
|
+
justify-content: space-between;
|
|
808
|
+
">
|
|
809
|
+
<div style="font-weight: 600; font-size: 16px;">${greeting}</div>
|
|
810
|
+
<button class="vtilt-chat-close" style="
|
|
811
|
+
background: none;
|
|
812
|
+
border: none;
|
|
813
|
+
color: white;
|
|
814
|
+
cursor: pointer;
|
|
815
|
+
padding: 4px;
|
|
816
|
+
">
|
|
817
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
818
|
+
<path d="M18 6L6 18M6 6l12 12"></path>
|
|
819
|
+
</svg>
|
|
820
|
+
</button>
|
|
821
|
+
</div>
|
|
822
|
+
|
|
823
|
+
<div class="vtilt-chat-messages" style="
|
|
824
|
+
flex: 1;
|
|
825
|
+
overflow-y: auto;
|
|
826
|
+
padding: 16px;
|
|
827
|
+
display: flex;
|
|
828
|
+
flex-direction: column;
|
|
829
|
+
gap: 12px;
|
|
830
|
+
"></div>
|
|
831
|
+
|
|
832
|
+
<div class="vtilt-chat-loader" style="
|
|
833
|
+
display: none;
|
|
834
|
+
align-items: center;
|
|
835
|
+
justify-content: center;
|
|
836
|
+
padding: 20px;
|
|
837
|
+
">
|
|
838
|
+
<div style="
|
|
839
|
+
width: 24px;
|
|
840
|
+
height: 24px;
|
|
841
|
+
border: 2px solid #e5e7eb;
|
|
842
|
+
border-top-color: ${theme.primaryColor};
|
|
843
|
+
border-radius: 50%;
|
|
844
|
+
animation: vtilt-spin 0.8s linear infinite;
|
|
845
|
+
"></div>
|
|
846
|
+
</div>
|
|
847
|
+
|
|
848
|
+
<div class="vtilt-chat-typing" style="
|
|
849
|
+
display: none;
|
|
850
|
+
padding: 8px 16px;
|
|
851
|
+
color: #6b7280;
|
|
852
|
+
font-size: 14px;
|
|
853
|
+
">
|
|
854
|
+
<span style="animation: vtilt-pulse 1.5s infinite;">Agent is typing...</span>
|
|
855
|
+
</div>
|
|
856
|
+
|
|
857
|
+
<div class="vtilt-chat-input-container" style="
|
|
858
|
+
padding: 16px;
|
|
859
|
+
border-top: 1px solid #e5e7eb;
|
|
860
|
+
display: flex;
|
|
861
|
+
gap: 8px;
|
|
862
|
+
">
|
|
863
|
+
<input
|
|
864
|
+
type="text"
|
|
865
|
+
class="vtilt-chat-input"
|
|
866
|
+
placeholder="Type a message..."
|
|
867
|
+
style="
|
|
868
|
+
flex: 1;
|
|
869
|
+
border: 1px solid #e5e7eb;
|
|
870
|
+
border-radius: 8px;
|
|
871
|
+
padding: 10px 14px;
|
|
872
|
+
font-size: 14px;
|
|
873
|
+
outline: none;
|
|
874
|
+
transition: border-color 0.2s;
|
|
875
|
+
"
|
|
876
|
+
/>
|
|
877
|
+
<button class="vtilt-chat-send" style="
|
|
878
|
+
background: ${theme.primaryColor};
|
|
879
|
+
color: white;
|
|
880
|
+
border: none;
|
|
881
|
+
border-radius: 8px;
|
|
882
|
+
padding: 10px 16px;
|
|
883
|
+
cursor: pointer;
|
|
884
|
+
font-weight: 500;
|
|
885
|
+
transition: opacity 0.2s;
|
|
886
|
+
">Send</button>
|
|
887
|
+
</div>
|
|
888
|
+
|
|
889
|
+
<style>
|
|
890
|
+
@keyframes vtilt-spin {
|
|
891
|
+
to { transform: rotate(360deg); }
|
|
892
|
+
}
|
|
893
|
+
@keyframes vtilt-pulse {
|
|
894
|
+
0%, 100% { opacity: 1; }
|
|
895
|
+
50% { opacity: 0.5; }
|
|
896
|
+
}
|
|
897
|
+
#vtilt-chat-bubble:hover {
|
|
898
|
+
transform: scale(1.05);
|
|
899
|
+
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
|
|
900
|
+
}
|
|
901
|
+
.vtilt-chat-input:focus {
|
|
902
|
+
border-color: ${theme.primaryColor} !important;
|
|
903
|
+
}
|
|
904
|
+
.vtilt-chat-send:hover {
|
|
905
|
+
opacity: 0.9;
|
|
906
|
+
}
|
|
907
|
+
</style>
|
|
902
908
|
`;
|
|
903
909
|
}
|
|
904
910
|
_getMessageHTML(message) {
|
|
@@ -923,23 +929,23 @@ class LazyLoadedChat {
|
|
|
923
929
|
const unreadBadge = isUnread && !this._isMarkingRead
|
|
924
930
|
? `<span style="font-size: 10px; font-weight: 600; color: ${theme.primaryColor}; background: ${theme.primaryColor}20; padding: 2px 6px; border-radius: 9999px;">NEW</span>`
|
|
925
931
|
: "";
|
|
926
|
-
return `
|
|
927
|
-
<div style="display: flex; flex-direction: column; ${isUser ? "align-items: flex-end;" : "align-items: flex-start;"}${isUnread && !this._isMarkingRead ? " position: relative;" : ""}">
|
|
928
|
-
${!isUser && senderLabel ? `<div style="font-size: 12px; color: #6b7280; margin-bottom: 4px;">${senderLabel}</div>` : ""}
|
|
929
|
-
<div style="
|
|
930
|
-
max-width: 80%;
|
|
931
|
-
padding: 10px 14px;
|
|
932
|
-
border-radius: 12px;
|
|
933
|
-
font-size: 14px;
|
|
934
|
-
line-height: 1.4;
|
|
935
|
-
transition: opacity 0.3s, box-shadow 0.3s;
|
|
936
|
-
${bubbleStyle}${this._isMarkingRead && isUnread ? " opacity: 0.7;" : ""}
|
|
937
|
-
">${this._escapeHTML(message.content)}</div>
|
|
938
|
-
<div style="font-size: 11px; color: #9ca3af; margin-top: 4px; display: flex; align-items: center; gap: 4px;">
|
|
939
|
-
${this._formatTime(message.created_at)}
|
|
940
|
-
${isUser ? (isReadByAgent ? doubleCheckSvg : singleCheckSvg) : unreadBadge}
|
|
941
|
-
</div>
|
|
942
|
-
</div>
|
|
932
|
+
return `
|
|
933
|
+
<div style="display: flex; flex-direction: column; ${isUser ? "align-items: flex-end;" : "align-items: flex-start;"}${isUnread && !this._isMarkingRead ? " position: relative;" : ""}">
|
|
934
|
+
${!isUser && senderLabel ? `<div style="font-size: 12px; color: #6b7280; margin-bottom: 4px;">${senderLabel}</div>` : ""}
|
|
935
|
+
<div style="
|
|
936
|
+
max-width: 80%;
|
|
937
|
+
padding: 10px 14px;
|
|
938
|
+
border-radius: 12px;
|
|
939
|
+
font-size: 14px;
|
|
940
|
+
line-height: 1.4;
|
|
941
|
+
transition: opacity 0.3s, box-shadow 0.3s;
|
|
942
|
+
${bubbleStyle}${this._isMarkingRead && isUnread ? " opacity: 0.7;" : ""}
|
|
943
|
+
">${this._escapeHTML(message.content)}</div>
|
|
944
|
+
<div style="font-size: 11px; color: #9ca3af; margin-top: 4px; display: flex; align-items: center; gap: 4px;">
|
|
945
|
+
${this._formatTime(message.created_at)}
|
|
946
|
+
${isUser ? (isReadByAgent ? doubleCheckSvg : singleCheckSvg) : unreadBadge}
|
|
947
|
+
</div>
|
|
948
|
+
</div>
|
|
943
949
|
`;
|
|
944
950
|
}
|
|
945
951
|
/**
|
package/package.json
CHANGED
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@v-tilt/browser",
|
|
3
|
-
"version": "1.4.
|
|
4
|
-
"description": "vTilt browser tracking library",
|
|
5
|
-
"main": "dist/main.js",
|
|
6
|
-
"module": "dist/module.js",
|
|
7
|
-
"types": "dist/module.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"lib/*",
|
|
10
|
-
"dist/*"
|
|
11
|
-
],
|
|
12
|
-
"publishConfig": {
|
|
13
|
-
"access": "public"
|
|
14
|
-
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "tsc -b && rollup -c",
|
|
17
|
-
"dev": "rollup -c -w",
|
|
18
|
-
"type-check": "tsc --noEmit",
|
|
19
|
-
"lint": "eslint src --ext .ts",
|
|
20
|
-
"lint:fix": "eslint src --ext .ts --fix",
|
|
21
|
-
"clean": "rimraf lib dist",
|
|
22
|
-
"prepublishOnly": "pnpm run build"
|
|
23
|
-
},
|
|
24
|
-
"keywords": [
|
|
25
|
-
"analytics",
|
|
26
|
-
"tracking",
|
|
27
|
-
"web-vitals",
|
|
28
|
-
"performance"
|
|
29
|
-
],
|
|
30
|
-
"author": "vTilt",
|
|
31
|
-
"license": "MIT",
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"@babel/preset-env": "^7.28.3",
|
|
34
|
-
"@rollup/plugin-babel": "^6.0.4",
|
|
35
|
-
"@rollup/plugin-commonjs": "^25.0.8",
|
|
36
|
-
"@rollup/plugin-json": "^6.1.0",
|
|
37
|
-
"@rollup/plugin-node-resolve": "^15.3.1",
|
|
38
|
-
"@rollup/plugin-terser": "^0.4.4",
|
|
39
|
-
"@rollup/plugin-typescript": "^11.1.6",
|
|
40
|
-
"@types/node": "^20.10.5",
|
|
41
|
-
"@v-tilt/eslint-config": "workspace:*",
|
|
42
|
-
"eslint": "^9.0.0",
|
|
43
|
-
"rimraf": "^5.0.5",
|
|
44
|
-
"rollup": "^4.9.1",
|
|
45
|
-
"rollup-plugin-dts": "^6.2.3",
|
|
46
|
-
"rollup-plugin-terser": "^7.0.2",
|
|
47
|
-
"rollup-plugin-visualizer": "^6.0.3",
|
|
48
|
-
"typescript": "^5.3.3"
|
|
49
|
-
},
|
|
50
|
-
"dependencies": {
|
|
51
|
-
"@rrweb/record": "2.0.0-alpha.17",
|
|
52
|
-
"@rrweb/rrweb-plugin-console-record": "2.0.0-alpha.17",
|
|
53
|
-
"@rrweb/types": "2.0.0-alpha.17",
|
|
54
|
-
"ably": "^2.4.0",
|
|
55
|
-
"fflate": "^0.8.2",
|
|
56
|
-
"web-vitals": "^3.5.0"
|
|
57
|
-
},
|
|
58
|
-
"peerDependencies": {
|
|
59
|
-
"web-vitals": "^3.0.0"
|
|
60
|
-
},
|
|
61
|
-
"peerDependenciesMeta": {
|
|
62
|
-
"web-vitals": {
|
|
63
|
-
"optional": true
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@v-tilt/browser",
|
|
3
|
+
"version": "1.4.1",
|
|
4
|
+
"description": "vTilt browser tracking library",
|
|
5
|
+
"main": "dist/main.js",
|
|
6
|
+
"module": "dist/module.js",
|
|
7
|
+
"types": "dist/module.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"lib/*",
|
|
10
|
+
"dist/*"
|
|
11
|
+
],
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc -b && rollup -c",
|
|
17
|
+
"dev": "rollup -c -w",
|
|
18
|
+
"type-check": "tsc --noEmit",
|
|
19
|
+
"lint": "eslint src --ext .ts",
|
|
20
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
21
|
+
"clean": "rimraf lib dist",
|
|
22
|
+
"prepublishOnly": "pnpm run build"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"analytics",
|
|
26
|
+
"tracking",
|
|
27
|
+
"web-vitals",
|
|
28
|
+
"performance"
|
|
29
|
+
],
|
|
30
|
+
"author": "vTilt",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@babel/preset-env": "^7.28.3",
|
|
34
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
35
|
+
"@rollup/plugin-commonjs": "^25.0.8",
|
|
36
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
37
|
+
"@rollup/plugin-node-resolve": "^15.3.1",
|
|
38
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
39
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
40
|
+
"@types/node": "^20.10.5",
|
|
41
|
+
"@v-tilt/eslint-config": "workspace:*",
|
|
42
|
+
"eslint": "^9.0.0",
|
|
43
|
+
"rimraf": "^5.0.5",
|
|
44
|
+
"rollup": "^4.9.1",
|
|
45
|
+
"rollup-plugin-dts": "^6.2.3",
|
|
46
|
+
"rollup-plugin-terser": "^7.0.2",
|
|
47
|
+
"rollup-plugin-visualizer": "^6.0.3",
|
|
48
|
+
"typescript": "^5.3.3"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@rrweb/record": "2.0.0-alpha.17",
|
|
52
|
+
"@rrweb/rrweb-plugin-console-record": "2.0.0-alpha.17",
|
|
53
|
+
"@rrweb/types": "2.0.0-alpha.17",
|
|
54
|
+
"ably": "^2.4.0",
|
|
55
|
+
"fflate": "^0.8.2",
|
|
56
|
+
"web-vitals": "^3.5.0"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"web-vitals": "^3.0.0"
|
|
60
|
+
},
|
|
61
|
+
"peerDependenciesMeta": {
|
|
62
|
+
"web-vitals": {
|
|
63
|
+
"optional": true
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|