shopify-chatbot-widget 0.7.9 → 0.8.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.
Files changed (58) hide show
  1. package/dist/jaweb-chatbot.css +1 -1
  2. package/dist/jaweb-chatbot.iife.js +3 -3
  3. package/package.json +1 -1
  4. package/src/App.css +42 -0
  5. package/src/App.tsx +13 -0
  6. package/src/Chatbot/Chatbot.css +270 -0
  7. package/src/Chatbot/Chatbot.tsx +214 -0
  8. package/src/Chatbot/ChatbotTransition.css +19 -0
  9. package/src/Chatbot/OLDCHAT.tsx +259 -0
  10. package/src/Chatbot/components/ChatInput.css +127 -0
  11. package/src/Chatbot/components/ChatInput.tsx +354 -0
  12. package/src/Chatbot/components/Messages/Addcart.tsx +70 -0
  13. package/src/Chatbot/components/Messages/AgentStatus.tsx +37 -0
  14. package/src/Chatbot/components/Messages/AssistantMesage.tsx +206 -0
  15. package/src/Chatbot/components/Messages/AudioMessage.tsx +123 -0
  16. package/src/Chatbot/components/Messages/CalendlyEmbeds.tsx +66 -0
  17. package/src/Chatbot/components/Messages/CardSwiper.tsx +194 -0
  18. package/src/Chatbot/components/Messages/Carousel/CardSwiper.tsx +264 -0
  19. package/src/Chatbot/components/Messages/Carousel/CardSwiperSalla.tsx +208 -0
  20. package/src/Chatbot/components/Messages/Carousel/CardSwiperZid.tsx +208 -0
  21. package/src/Chatbot/components/Messages/Carousel/SallaSwiper.css +245 -0
  22. package/src/Chatbot/components/Messages/Carousel/TryOn.tsx +111 -0
  23. package/src/Chatbot/components/Messages/CartWidget.tsx +151 -0
  24. package/src/Chatbot/components/Messages/ChatImage.tsx +46 -0
  25. package/src/Chatbot/components/Messages/ChatImageText.tsx +74 -0
  26. package/src/Chatbot/components/Messages/ChatImageTextAssis.tsx +72 -0
  27. package/src/Chatbot/components/Messages/ChatMessages.css +31 -0
  28. package/src/Chatbot/components/Messages/ChatMessages.tsx +334 -0
  29. package/src/Chatbot/components/Messages/ProductCard.css +149 -0
  30. package/src/Chatbot/components/Messages/SallaAssistantMessage.tsx +196 -0
  31. package/src/Chatbot/components/Messages/Support.tsx +177 -0
  32. package/src/Chatbot/components/Messages/Typing.css +31 -0
  33. package/src/Chatbot/components/Messages/Typing.tsx +19 -0
  34. package/src/Chatbot/components/Messages/ZidAssistantMesage.tsx +196 -0
  35. package/src/Chatbot/components/Messages/cartwidget.css +123 -0
  36. package/src/Chatbot/components/Messenger/Messenger.tsx +531 -0
  37. package/src/Chatbot/components/Notification.tsx +28 -0
  38. package/src/Chatbot/components/Powered.css +29 -0
  39. package/src/Chatbot/components/Powered.tsx +12 -0
  40. package/src/Chatbot/components/Sessions/CreateSession.tsx +201 -0
  41. package/src/Chatbot/components/Sessions/RenderList.tsx +212 -0
  42. package/src/Chatbot/components/Suggestions.css +35 -0
  43. package/src/Chatbot/components/Suggestions.tsx +57 -0
  44. package/src/Chatbot/notification.css +17 -0
  45. package/src/assets/react.svg +1 -0
  46. package/src/chatbot-widget/index.tsx +14 -0
  47. package/src/hooks/config.tsx +13 -0
  48. package/src/hooks/useCart.tsx +107 -0
  49. package/src/hooks/useChatbotAPI.tsx +167 -0
  50. package/src/hooks/useChatbotData.tsx +132 -0
  51. package/src/hooks/useSessionMessages.tsx +50 -0
  52. package/src/hooks/useWebsocke.tsx +45 -0
  53. package/src/i18n.tsx +30 -0
  54. package/src/index.css +2 -0
  55. package/src/main.tsx +10 -0
  56. package/src/types/chatbot.ts +40 -0
  57. package/src/utils/cookies.tsx +14 -0
  58. package/src/vite-env.d.ts +1 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shopify-chatbot-widget",
3
3
  "private": false,
4
- "version": "0.7.9",
4
+ "version": "0.8.2",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
package/src/App.css ADDED
@@ -0,0 +1,42 @@
1
+ #root {
2
+ max-width: 1280px;
3
+ margin: 0 auto;
4
+ padding: 2rem;
5
+ text-align: center;
6
+ }
7
+
8
+ .logo {
9
+ height: 6em;
10
+ padding: 1.5em;
11
+ will-change: filter;
12
+ transition: filter 300ms;
13
+ }
14
+ .logo:hover {
15
+ filter: drop-shadow(0 0 2em #646cffaa);
16
+ }
17
+ .logo.react:hover {
18
+ filter: drop-shadow(0 0 2em #61dafbaa);
19
+ }
20
+
21
+ @keyframes logo-spin {
22
+ from {
23
+ transform: rotate(0deg);
24
+ }
25
+ to {
26
+ transform: rotate(360deg);
27
+ }
28
+ }
29
+
30
+ @media (prefers-reduced-motion: no-preference) {
31
+ a:nth-of-type(2) .logo {
32
+ animation: logo-spin infinite 20s linear;
33
+ }
34
+ }
35
+
36
+ .card {
37
+ padding: 2em;
38
+ }
39
+
40
+ .read-the-docs {
41
+ color: #888;
42
+ }
package/src/App.tsx ADDED
@@ -0,0 +1,13 @@
1
+ import Chatbot from './Chatbot/Chatbot';
2
+ import 'antd/dist/reset.css'; // global AntD styles
3
+
4
+ function App() {
5
+ return (
6
+ <div className='jaweb-reset'>
7
+
8
+ <Chatbot />
9
+ </div>
10
+ );
11
+ }
12
+
13
+ export default App;
@@ -0,0 +1,270 @@
1
+ .jaweb-chatbot-container {
2
+ position: fixed;
3
+ bottom: 20px;
4
+ right: 20px;
5
+ z-index: 9999;
6
+
7
+ }
8
+
9
+ /* Tailwind global CSS file */
10
+ .scrollbar-hide::-webkit-scrollbar {
11
+ display: none;
12
+ }
13
+ .scrollbar-hide {
14
+ -ms-overflow-style: none;
15
+ scrollbar-width: none;
16
+ }
17
+
18
+
19
+ .chatbot-box {
20
+ position: fixed;
21
+ bottom: 5%;
22
+ right: 10px;
23
+ width: 28%;
24
+ top: 2%;
25
+ z-index: 9999;
26
+ height: 86%;
27
+ background: #ffffff;
28
+ color: #000000;
29
+ border-radius: 12px;
30
+ overflow: hidden;
31
+ display: flex;
32
+ flex-direction: column;
33
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
34
+ font-family: 'Inter', sans-serif;
35
+ }
36
+
37
+
38
+
39
+
40
+ /* Mobile responsiveness */
41
+
42
+ .chatbot-header {
43
+ background: #f7f7f7;
44
+ padding: 16px;
45
+ display: flex;
46
+ align-items: center;
47
+ height: 8%;
48
+ gap: 12px;
49
+ font-size: 16px;
50
+ font-weight: bold;
51
+ border-bottom: 1px solid #e0e0e0;
52
+ }
53
+
54
+ .chatbot-title {
55
+ flex-grow: 1;
56
+ }
57
+
58
+ .chatbot-close {
59
+ cursor: pointer;
60
+ font-size: 16px;
61
+ color: #888;
62
+ }
63
+
64
+ .chatbot-messages {
65
+ flex: 1;
66
+ padding: 16px;
67
+ overflow-y: auto;
68
+ display: flex;
69
+ flex-direction: column;
70
+ height: 70%;
71
+ gap: 12px;
72
+ background-color: #fafafa;
73
+ min-height: 70%;
74
+
75
+ /* Hide scrollbar for all browsers */
76
+ scrollbar-width: none; /* Firefox */
77
+ -ms-overflow-style: none; /* Internet Explorer 10+ */
78
+ }
79
+
80
+ /* Hide scrollbar for WebKit-based browsers (Chrome, Safari) */
81
+ .chatbot-messages::-webkit-scrollbar {
82
+ display: none;
83
+ }
84
+
85
+
86
+ .chat-msg {
87
+ max-width: 85%;
88
+ padding: 10px 14px;
89
+ border-radius: 16px;
90
+ font-size: 14px;
91
+ line-height: 1.4;
92
+ word-break: break-word;
93
+ }
94
+
95
+ .chat-msg.assistant {
96
+ background: #f0f0f0;
97
+ align-self: flex-start;
98
+ color: #000;
99
+ }
100
+
101
+ .chat-msg.user {
102
+ background: #7f28f8;
103
+ align-self: flex-end;
104
+ color: white;
105
+ }
106
+
107
+ .chatbot-input-area {
108
+ width: 100%;
109
+ display: flex;
110
+ flex-direction: column;
111
+ height:22%;
112
+ align-items: center;
113
+ background: #ffffff;
114
+ border-top: 1px solid #e0e0e0;
115
+
116
+ }
117
+
118
+ .typing-animation span {
119
+ display: inline-block;
120
+ animation: blink 1.2s infinite;
121
+ font-size: 18px;
122
+ margin: 0 2px;
123
+ }
124
+
125
+ .typing-animation span:nth-child(2) {
126
+ animation-delay: 0.2s;
127
+ }
128
+ .typing-animation span:nth-child(3) {
129
+ animation-delay: 0.4s;
130
+ }
131
+
132
+ @keyframes blink {
133
+ 0% { opacity: 0.2; }
134
+ 20% { opacity: 1; }
135
+ 100% { opacity: 0.2; }
136
+ }
137
+
138
+ /* brand color hook (optional) */
139
+ .jaweb-chatbot-container { --jaweb-color: #7f28f8; }
140
+
141
+ /* ===== NUDGE BUBBLE ===== */
142
+ .jaweb-nudge-bubble{
143
+ position:absolute;
144
+ right:6px; /* nudge in from the edge */
145
+ bottom:84px;
146
+ width: 100px; /* sits above the 60px launcher */
147
+ max-width:210px;
148
+ background:#ffffff;
149
+ color:#111;
150
+ border-radius:18px;
151
+ padding:12px 14px;
152
+ box-shadow:
153
+ 0 18px 50px rgba(0,0,0,.18),
154
+ 0 6px 18px rgba(0,0,0,.08);
155
+ border:1px solid rgba(17,17,17,.06);
156
+ cursor:pointer;
157
+ /* entrance */
158
+ opacity:0;
159
+ transform:translateY(8px) scale(.98);
160
+ animation:jb-in .32s cubic-bezier(.22,1,.36,1) forwards,
161
+ jb-float 6s ease-in-out 1.2s infinite;
162
+ z-index:10001;
163
+ }
164
+
165
+ /* “tail” pointing to the launcher */
166
+ .jaweb-nudge-caret{
167
+ position:absolute;
168
+ left:50%;
169
+ transform:translateX(-50%) rotate(45deg);
170
+ bottom:-8px;
171
+ width:14px;height:14px;
172
+ background:#ffffff;
173
+ border-right:1px solid rgba(17,17,17,.06);
174
+ border-bottom:1px solid rgba(17,17,17,.06);
175
+ filter: drop-shadow(0 2px 3px rgba(0,0,0,.08));
176
+ }
177
+
178
+ /* content: three dots on top + stacked text */
179
+ .jaweb-nudge-text{
180
+ display:block;
181
+ word-wrap:normal;
182
+ word-break:normal;
183
+ font-size:15.5px;
184
+ line-height:1.25;
185
+ font-weight:600;
186
+ letter-spacing:.2px;
187
+ }
188
+
189
+ /* typing dots row */
190
+ .jaweb-nudge-text .jaweb-typing-dot{
191
+ display:inline-block;
192
+ width:6px;height:6px;
193
+ margin-right:6px;
194
+ border-radius:9999px;
195
+ background:linear-gradient(180deg,#c8c8c8,#bdbdbd);
196
+ animation:jb-typing 1.2s infinite ease-in-out;
197
+ vertical-align:middle;
198
+ }
199
+ .jaweb-nudge-text .jaweb-typing-dot:nth-child(1){ animation-delay:0s; }
200
+ .jaweb-nudge-text .jaweb-typing-dot:nth-child(2){ animation-delay:.15s; }
201
+ .jaweb-nudge-text .jaweb-typing-dot:nth-child(3){ animation-delay:.3s; }
202
+
203
+ /* subtle gradient ring on bubble edges (premium vibe) */
204
+ .jaweb-nudge-bubble::before{
205
+ content:"";
206
+ position:absolute; inset:0;
207
+ border-radius:inherit;
208
+ pointer-events:none;
209
+ background:
210
+ radial-gradient(120% 120% at 50% -10%,
211
+ color-mix(in oklab, var(--jaweb-color, #7f28f8) 14%, transparent) 0%,
212
+ transparent 60%);
213
+ }
214
+
215
+ /* dark mode */
216
+ @media (prefers-color-scheme: dark){
217
+ .jaweb-nudge-bubble{
218
+ background: #1f1f21;
219
+ color:#f5f5f7;
220
+ border:1px solid rgba(255,255,255,.06);
221
+ box-shadow:
222
+ 0 22px 60px rgba(0,0,0,.55),
223
+ 0 0 0 1px rgba(255,255,255,.04) inset;
224
+ }
225
+ .jaweb-nudge-caret{
226
+ background:#1f1f21;
227
+ border-right:1px solid rgba(255,255,255,.06);
228
+ border-bottom:1px solid rgba(255,255,255,.06);
229
+ }
230
+ .jaweb-nudge-text .jaweb-typing-dot{
231
+ background:linear-gradient(180deg,#bfbfbf,#a8a8a8);
232
+ }
233
+ }
234
+
235
+ /* reduced motion */
236
+ @media (prefers-reduced-motion: reduce){
237
+ .jaweb-nudge-bubble{ animation:none; }
238
+ .jaweb-nudge-text .jaweb-typing-dot{ animation:none; }
239
+ }
240
+
241
+ /* keyframes */
242
+ @keyframes jb-in{
243
+ to{ opacity:1; transform:translateY(0) scale(1); }
244
+ }
245
+ @keyframes jb-typing{
246
+ 0%, 60%, 100%{ transform:translateY(0); opacity:.55; }
247
+ 30%{ transform:translateY(-3px); opacity:1; }
248
+ }
249
+ @keyframes jb-float{
250
+ 0%,100%{ transform:translateY(0); }
251
+ 50%{ transform:translateY(-2px); }
252
+ }
253
+
254
+
255
+
256
+ @media (max-width: 600px) {
257
+ .chatbot-box {
258
+ position: fixed;
259
+ width: 100%;
260
+ height: 100%;
261
+ right: 0;
262
+ bottom: 0;
263
+ top: 0;
264
+
265
+
266
+ }
267
+ .chat-launcher.chatbot-open {
268
+ display: none;
269
+ }
270
+ }
@@ -0,0 +1,214 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { useChatbotData } from '../hooks/useChatbotData';
3
+ import ChatSessions from './components/Sessions/RenderList';
4
+ import CreateSession from './components/Sessions/CreateSession';
5
+ import Messenger from './components/Messenger/Messenger';
6
+ import './Chatbot.css';
7
+ import config from '../hooks/config';
8
+ import FingerprintJS from '@fingerprintjs/fingerprintjs';
9
+ import { LoadingOutlined } from '@ant-design/icons';
10
+ import { Spin } from 'antd';
11
+ import { motion, AnimatePresence } from 'framer-motion';
12
+
13
+ const Chatbot: React.FC = () => {
14
+ const [open, setOpen] = useState(false);
15
+ const [viewMode, setViewMode] = useState<'sessions' | 'create' | 'messenger'>('sessions');
16
+ const [activeSessionId, setActiveSessionId] = useState<string | null>(null);
17
+ const [HasInfo, setHasInfo] = useState(false);
18
+ const [activeAgentName, setActiveAgentName] = useState('');
19
+ const [activeAgentImage, setActiveAgentImage] = useState('');
20
+ const [newSession, setNewSession] = useState(false);
21
+
22
+
23
+ const {
24
+ chatbotLogo,
25
+ colorCode,
26
+ messagesSuggestions,
27
+ disableForm,
28
+ merchantPhone,
29
+ userType,
30
+ isFetchingDetails,
31
+ calendly,
32
+ disbleCheckout,
33
+ } = useChatbotData();
34
+
35
+ const [visitorData, setVisitorData] = useState<{ visitorId: string; country: string } | null>(null);
36
+ const antIcon = <LoadingOutlined style={{ fontSize: 24, color: colorCode||'#7F28F8' }} spin />;
37
+
38
+ const handleNewSessionClick = () => {
39
+ if (!disableForm && !HasInfo) {
40
+ setViewMode('create');
41
+ return;
42
+ } else {
43
+ const newSessionId = crypto.randomUUID();
44
+ setActiveSessionId(newSessionId);
45
+ setActiveAgentImage(chatbotLogo);
46
+ setActiveAgentName('Ai Agent');
47
+ setNewSession(true);
48
+ setViewMode('messenger');
49
+ }
50
+ };
51
+
52
+ useEffect(() => {
53
+ const fetchVisitorInfo = async () => {
54
+ try {
55
+ let visitorId = localStorage.getItem('visitor_id');
56
+
57
+ if (!visitorId) {
58
+ const fp = await FingerprintJS.load();
59
+ const result = await fp.get();
60
+ visitorId = result.visitorId;
61
+ localStorage.setItem('visitor_id', visitorId);
62
+ }
63
+
64
+ const backendRes = await fetch(`${config.apiUrl}register-ip/`, {
65
+ method: 'POST',
66
+ headers: { 'Content-Type': 'application/json' },
67
+ credentials: 'include',
68
+ body: JSON.stringify({ visitor_id: visitorId }),
69
+ });
70
+
71
+ const result = await backendRes.json();
72
+
73
+ if (result.visitor && result.country) {
74
+ localStorage.setItem('country', result.country);
75
+ setVisitorData({ visitorId: result.visitor, country: result.country });
76
+ setHasInfo(result.has_user_info || false);
77
+ } else {
78
+ console.warn('Backend did not return country');
79
+ }
80
+ } catch (err) {
81
+ console.error('Failed to fetch or send visitor info', err);
82
+ }
83
+ };
84
+
85
+ fetchVisitorInfo();
86
+ }, []);
87
+
88
+ const handleSessionSelect = (sessionId: string, agentName: string, agentImage: string) => {
89
+ setActiveSessionId(sessionId);
90
+ setActiveAgentName(agentName);
91
+ setActiveAgentImage(agentImage);
92
+ setNewSession(false);
93
+ setViewMode('messenger');
94
+ };
95
+
96
+ useEffect(() => {
97
+ const onMessage = (e: MessageEvent) => {
98
+ const msg = (e.data || {}) as any;
99
+ if (msg.type !== 'JAWEB_CHAT') return;
100
+
101
+ if (msg.action === 'open-ready') {
102
+ setOpen(true);
103
+ } else if (msg.action === 'closed') {
104
+ setOpen(false);
105
+ }
106
+ };
107
+ window.addEventListener('message', onMessage);
108
+ return () => window.removeEventListener('message', onMessage);
109
+ }, []);
110
+
111
+ const requestOpen = () => {
112
+ window.parent?.postMessage({ type: 'JAWEB_CHAT', action: 'open' }, '*');
113
+ };
114
+ const requestClose = () => {
115
+ window.parent?.postMessage({ type: 'JAWEB_CHAT', action: 'close' }, '*');
116
+ };
117
+
118
+ useEffect(() => {
119
+ if (!isFetchingDetails) {
120
+ window.parent?.postMessage({ type: 'JAWEB_CHAT', action: 'ready-confirm' }, '*');
121
+ }
122
+ }, [isFetchingDetails]);
123
+
124
+ return (
125
+ <div>
126
+ {open && (
127
+ <div className="chatbot-box">
128
+ {isFetchingDetails ? (
129
+ <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: 300 }}>
130
+ <Spin indicator={antIcon} tip="..." />
131
+ </div>
132
+ ) : (
133
+ <AnimatePresence mode="sync">
134
+ {viewMode === 'sessions' && (
135
+ <motion.div
136
+ key="sessions"
137
+ initial={{ opacity: 0, x: -30 }}
138
+ animate={{ opacity: 1, x: 0 }}
139
+ exit={{ opacity: 0, x: 30 }}
140
+ transition={{ duration: 0.3 }}
141
+ style={{height:'100%'}}
142
+ >
143
+ <ChatSessions
144
+ chatbotLogo={chatbotLogo}
145
+ Phone={merchantPhone || ''}
146
+ colorCode={colorCode}
147
+ visitorId={visitorData?.visitorId || ''}
148
+ Opened={open}
149
+ setOpen={(v: boolean) => (v ? requestOpen() : requestClose())}
150
+ onNewSession={handleNewSessionClick}
151
+ onSessionSelect={handleSessionSelect}
152
+ />
153
+ </motion.div>
154
+ )}
155
+
156
+ {viewMode === 'create' && (
157
+ <motion.div
158
+ key="create"
159
+ initial={{ opacity: 0, y: 30 }}
160
+ animate={{ opacity: 1, y: 0 }}
161
+ exit={{ opacity: 0, y: -30 }}
162
+ transition={{ duration: 0.3 }}
163
+
164
+ >
165
+ <CreateSession
166
+ colorCode={colorCode}
167
+ visitorId={visitorData?.visitorId || ''}
168
+ country={visitorData?.country || ''}
169
+ onBack={() => setViewMode('sessions')}
170
+ onCreate={(userData) => {
171
+ setActiveSessionId(userData.session_id);
172
+ setHasInfo(userData.hasInfo);
173
+ setViewMode('messenger');
174
+ }}
175
+ />
176
+ </motion.div>
177
+ )}
178
+
179
+ {viewMode === 'messenger' && activeSessionId && (
180
+ <motion.div
181
+ key="messenger"
182
+ initial={{ scale: 0.95, opacity: 0 }}
183
+ animate={{ scale: 1, opacity: 1 }}
184
+ exit={{ scale: 0.95, opacity: 0 }}
185
+ transition={{ duration: 0.3 }}
186
+
187
+ >
188
+ <Messenger
189
+ sessionId={activeSessionId}
190
+ chatbotLogo={activeAgentImage || chatbotLogo}
191
+ agentName={activeAgentName || 'Ai Assistant'}
192
+ colorCode={colorCode}
193
+ messagesSuggestions={messagesSuggestions}
194
+ newSession={newSession}
195
+ disableForm={disableForm}
196
+ calendly={calendly ?? ''}
197
+ setOpen={(v: boolean) => (v ? requestOpen() : requestClose())}
198
+ setNewSession={setNewSession}
199
+ Opened={open}
200
+ setView={() => setViewMode('sessions')}
201
+ userType={userType}
202
+ disbleCheckout={disbleCheckout}
203
+ />
204
+ </motion.div>
205
+ )}
206
+ </AnimatePresence>
207
+ )}
208
+ </div>
209
+ )}
210
+ </div>
211
+ );
212
+ };
213
+
214
+ export default Chatbot;
@@ -0,0 +1,19 @@
1
+ .fade-slide-enter {
2
+ opacity: 0;
3
+ transform: translateX(40px);
4
+ }
5
+ .fade-slide-enter-active {
6
+ opacity: 1;
7
+ transform: translateX(0);
8
+ transition: all 300ms ease;
9
+ }
10
+ .fade-slide-exit {
11
+ opacity: 1;
12
+ transform: translateX(0);
13
+ }
14
+ .fade-slide-exit-active {
15
+ opacity: 0;
16
+ transform: translateX(-40px);
17
+ transition: all 300ms ease;
18
+ }
19
+