shopify-chatbot-widget 0.0.4 → 0.0.7

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 (46) hide show
  1. package/dist/jaweb-chatbot.css +1 -0
  2. package/dist/jaweb-chatbot.iife.js +685 -0
  3. package/dist/vite.svg +1 -0
  4. package/package.json +1 -1
  5. package/src/App.css +0 -42
  6. package/src/App.tsx +0 -13
  7. package/src/Chatbot/Chatbot.css +0 -154
  8. package/src/Chatbot/Chatbot.tsx +0 -207
  9. package/src/Chatbot/components/ChatInput.css +0 -127
  10. package/src/Chatbot/components/ChatInput.tsx +0 -262
  11. package/src/Chatbot/components/Messages/Addcart.tsx +0 -70
  12. package/src/Chatbot/components/Messages/AgentStatus.tsx +0 -37
  13. package/src/Chatbot/components/Messages/AssistantMesage.tsx +0 -316
  14. package/src/Chatbot/components/Messages/AudioMessage.tsx +0 -123
  15. package/src/Chatbot/components/Messages/CartWidget.tsx +0 -116
  16. package/src/Chatbot/components/Messages/ChatImage.tsx +0 -46
  17. package/src/Chatbot/components/Messages/ChatImageText.tsx +0 -74
  18. package/src/Chatbot/components/Messages/ChatImageTextAssis.tsx +0 -72
  19. package/src/Chatbot/components/Messages/ChatMessages.css +0 -5
  20. package/src/Chatbot/components/Messages/ChatMessages.tsx +0 -284
  21. package/src/Chatbot/components/Messages/Support.tsx +0 -177
  22. package/src/Chatbot/components/Messages/Typing.css +0 -27
  23. package/src/Chatbot/components/Messages/Typing.tsx +0 -14
  24. package/src/Chatbot/components/Messages/ZidAssistantMesage.tsx +0 -142
  25. package/src/Chatbot/components/Messenger/Messenger.tsx +0 -521
  26. package/src/Chatbot/components/Notification.tsx +0 -27
  27. package/src/Chatbot/components/Powered.css +0 -16
  28. package/src/Chatbot/components/Powered.tsx +0 -13
  29. package/src/Chatbot/components/Sessions/CreateSession.tsx +0 -139
  30. package/src/Chatbot/components/Sessions/RenderList.tsx +0 -202
  31. package/src/Chatbot/components/Suggestions.css +0 -34
  32. package/src/Chatbot/components/Suggestions.tsx +0 -28
  33. package/src/assets/react.svg +0 -1
  34. package/src/chatbot-widget/index.tsx +0 -14
  35. package/src/hooks/config.tsx +0 -13
  36. package/src/hooks/useCart.tsx +0 -99
  37. package/src/hooks/useChatbotAPI.tsx +0 -160
  38. package/src/hooks/useChatbotData.tsx +0 -129
  39. package/src/hooks/useSessionMessages.tsx +0 -51
  40. package/src/hooks/useWebsocke.tsx +0 -45
  41. package/src/i18n.tsx +0 -30
  42. package/src/index.css +0 -1
  43. package/src/main.tsx +0 -10
  44. package/src/types/chatbot.ts +0 -38
  45. package/src/utils/cookies.tsx +0 -14
  46. package/src/vite-env.d.ts +0 -1
@@ -1,284 +0,0 @@
1
- import React from 'react';
2
- import { Spin } from 'antd';
3
- import { LoadingOutlined ,CheckCircleOutlined,CloseCircleOutlined} from '@ant-design/icons';
4
- import Typing from './Typing';
5
- import AssistantMessage from './AssistantMesage';
6
- import ChatImage from './ChatImage';
7
- import './ChatMessages.css'
8
- import ChatImageText from './ChatImageText';
9
- import AudioVisualizer from './AudioMessage';
10
- import AgentStatusBanner from './AgentStatus';
11
- import AddToCartConfirmation from './Addcart';
12
- import SupportConnect from './Support';
13
- import ChatImageTextAssist from './ChatImageTextAssis';
14
- import ZidAssistantChatMessage from './ZidAssistantMesage';
15
- interface Message {
16
- role?: string;
17
- content?: any;
18
- text?: string;
19
- typing?: boolean;
20
- image_url?:string;
21
- status?:string;
22
- audio_url?:string;
23
- isConnect?:boolean;
24
- }
25
-
26
- interface ChatMessagesProps {
27
- messages: Message[];
28
- colorCode: string;
29
- isLoading: boolean;
30
- handleAddToCart: (
31
- variantId: string,
32
- name: string,
33
- qty?: number
34
- ) => Promise<void>;
35
- handleRemoveFromCart: (variantId: string, qty?: number) => Promise<void>;
36
- sessionId:string;
37
- isBusiness?: boolean;
38
- agentStatus?: {
39
- status?: string;
40
- user?: string;
41
- };
42
- userType:string;
43
- }
44
-
45
-
46
-
47
-
48
- const spinIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
49
-
50
- const ChatMessages: React.FC<ChatMessagesProps> = ({
51
- messages,
52
- colorCode,
53
- handleAddToCart,
54
- handleRemoveFromCart,
55
- isLoading,
56
- agentStatus,
57
- sessionId,
58
- userType
59
-
60
- }) => {
61
-
62
-
63
- const handleAddToCartZid = () => {
64
- // Your logic goes here
65
- };
66
-
67
-
68
- if (isLoading || !messages) {
69
- return (
70
- <div
71
- className="loader-wrapper"
72
- style={{
73
- display: 'flex',
74
- alignItems: 'center',
75
- justifyContent: 'center',
76
- height: '100%',
77
- }}
78
- >
79
- <Spin indicator={spinIcon} />
80
- </div>
81
- );
82
- }
83
-
84
- return (
85
- <div className="chatbot-messages space-y-4">
86
- {messages.map((msg, i) => {
87
- if (msg.typing) {
88
- return (
89
- <div key={i} className="chat-msg typing">
90
- <Typing />
91
- </div>
92
- );
93
- }
94
-
95
- if (msg.isConnect){
96
- return(
97
- <SupportConnect sessionId={sessionId}/>
98
- )
99
- }
100
-
101
-
102
-
103
-
104
- if (msg.role === 'assistant') {
105
- // Handle array content separately
106
- if (Array.isArray(msg.content)) {
107
- return (
108
- <div key={i} className="chat-msg assistant" style={{ backgroundColor: 'transparent', padding: 0 }}>
109
- {msg.image_url && (
110
- <img
111
- src={msg.image_url}
112
- alt="Chat image"
113
- style={{ width: 200 }}
114
- className="rounded-md mt-2 max-w-xs border border-green-400 shadow-sm"
115
- />
116
- )}
117
- <ChatImage message={msg.content} />
118
- <div className="flex justify-start">
119
- <ChatImageTextAssist message={msg.content} />
120
- </div>
121
- </div>
122
- );
123
- }
124
-
125
- return (
126
- <div key={i} className="chat-msg assistant">
127
- {msg.image_url && (
128
- <img
129
- src={msg.image_url}
130
- alt="Chat image"
131
- style={{ width: 200 }}
132
- className="rounded-md mt-2 max-w-xs border border-green-400 shadow-sm"
133
- />
134
- )}
135
-
136
- {userType==="shopify"?(
137
- <AssistantMessage
138
- message={msg.content || msg.text || ''}
139
- colorCode={colorCode}
140
- handleAddToCart={handleAddToCart}
141
- handleRemoveFromCart={handleRemoveFromCart}
142
- />
143
- )
144
- :(
145
-
146
- <ZidAssistantChatMessage
147
- message={msg.content || msg.text || ''}
148
- colorCode={colorCode}
149
- handleAddToCart={handleAddToCartZid}
150
- />
151
- )
152
-
153
- }
154
-
155
-
156
- </div>
157
- );
158
- }
159
-
160
-
161
-
162
- if(msg?.audio_url){
163
-
164
- return(
165
- <div
166
- className={`chat-msg user`}
167
- style={{
168
- backgroundColor:'transparent',
169
- padding:0
170
- }}
171
- >
172
-
173
- <div style={{
174
- borderRadius:12
175
- }}>
176
-
177
- <AudioVisualizer link={msg.audio_url} transcription={msg.content} colorCode={colorCode} />
178
-
179
- {/* Upload/Delivery Status */}
180
-
181
- </div>
182
-
183
- <div className="mt-1 mr-2 flex items-end justify-end">
184
- {msg.status === 'uploading' ? (
185
- <Spin indicator={<LoadingOutlined spin />} size="small" />
186
- ) : msg.status === 'delivered' ? (
187
- <CheckCircleOutlined style={{ color: 'green' }} />
188
- ) : msg.status === 'failed' ? (
189
- <CloseCircleOutlined style={{ color: 'red' }} />
190
- ) : null}
191
- </div>
192
- </div>
193
- )
194
- }
195
-
196
-
197
- // ✅ IMAGE MESSAGE (non-assistant)
198
- if (msg.image_url) {
199
- return (
200
- <div key={i} className="chat-msg user" style={{ backgroundColor: 'transparent' }}>
201
- <img
202
- src={msg.image_url}
203
- alt="Chat image"
204
- style={{ width: 200 }}
205
- className={`rounded-md mt-2 max-w-xs ${
206
- msg.content === 'user'
207
- ? 'border border-gray-300 shadow-sm'
208
- : 'border border-green-400 shadow-sm'
209
- }`}
210
- />
211
-
212
- <div className="mt-1 mr-2 flex items-end justify-end">
213
- {msg.status === 'uploading' ? (
214
- <Spin indicator={<LoadingOutlined spin />} size="small" />
215
- ) : msg.status === 'delivered' ? (
216
- <CheckCircleOutlined style={{ color: 'green' }} />
217
- ) : msg.status === 'failed' ? (
218
- <CloseCircleOutlined style={{ color: 'red' }} />
219
- ) : null}
220
- </div>
221
-
222
- {msg.content && (
223
- <div className="flex justify-end mt-2">
224
- <div
225
- style={{
226
- color: 'white',
227
- border: 1,
228
- backgroundColor: colorCode,
229
- paddingTop: 10,
230
- paddingBottom: 10,
231
- paddingInline: 14,
232
- maxWidth: '85%',
233
- lineHeight: 1.4,
234
- borderRadius: '16px',
235
- wordBreak: 'break-word',
236
- }}
237
- >
238
- <span>{msg.content}</span>
239
- </div>
240
- </div>
241
- )}
242
- </div>
243
- );
244
- }
245
-
246
-
247
- // ✅ MULTIPLE IMAGES (array)
248
- if (Array.isArray(msg.content)) {
249
- return (
250
- <div key={i} className='chat-msg user' style={{backgroundColor:'transparent',padding:0}}>
251
- <div style={{backgroundColor:'transparent',padding:0}}>
252
- <ChatImage message={msg.content} />
253
- </div>
254
- <div key={i} className='flex justify-end'>
255
- <ChatImageText message={msg.content} colorCode={colorCode} />
256
- </div>
257
-
258
- </div>
259
- );
260
- }
261
-
262
-
263
- return (
264
- <div
265
- key={i}
266
- className={`chat-msg ${msg.role}`}
267
- style={
268
- msg.role === 'user'
269
- ? { backgroundColor: colorCode, color: '#fff' }
270
- : {}
271
- }
272
- >
273
-
274
- <AddToCartConfirmation message={msg.content} colorCode={colorCode}/>
275
-
276
- </div>
277
- );
278
- })}
279
- <AgentStatusBanner status={agentStatus?.status} user={agentStatus?.user} />
280
- </div>
281
- );
282
- };
283
-
284
- export default ChatMessages;
@@ -1,177 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { motion, AnimatePresence } from 'framer-motion';
3
- import { Mail } from 'lucide-react';
4
- import config from '../../../hooks/config';
5
-
6
- interface SupportConnectProps {
7
- sessionId?: string;
8
- colorCode?: string;
9
- }
10
-
11
- type Stage = 'email_sent' | 'connecting' | 'auto';
12
-
13
- interface SupportData {
14
- userImage?: string;
15
- agentName?: string;
16
- companyImage?: string;
17
- agentAvatar?: string;
18
- }
19
-
20
- const SupportConnect: React.FC<SupportConnectProps> = ({
21
- sessionId,
22
- colorCode = '#000',
23
- }) => {
24
- const [stage, setStage] = useState<Stage | null>(null);
25
- const [data, setData] = useState<SupportData>({});
26
- const [progress, setProgress] = useState<number>(0);
27
- const dots = [0, 1, 2];
28
-
29
- useEffect(() => {
30
- if (!sessionId) return;
31
- const ws = new WebSocket(
32
- `${config.websocketUrl}/support/${sessionId}/`
33
- );
34
-
35
- ws.onmessage = ({ data: text }) => {
36
- const msg = JSON.parse(text);
37
- setStage(msg.stage as Stage);
38
- setData(msg.data || {});
39
- };
40
- ws.onclose = () => console.log('Support socket closed');
41
- return () => ws.close();
42
- }, [sessionId]);
43
-
44
- useEffect(() => {
45
- let timerId: number;
46
- let start: number;
47
-
48
- if (stage === 'connecting') {
49
- start = Date.now();
50
- setProgress(100);
51
-
52
- timerId = window.setInterval(() => {
53
- const elapsed = (Date.now() - start) / 1000; // seconds
54
- const pct = Math.max(100 - (elapsed / 7) * 100, 0);
55
- setProgress(pct);
56
- if (pct <= 0) window.clearInterval(timerId);
57
- }, 100);
58
- }
59
-
60
- return () => {
61
- if (timerId) window.clearInterval(timerId);
62
- };
63
- }, [stage]);
64
-
65
- if (!stage) return null;
66
-
67
- return (
68
- <div className="bg-opacity-50 flex items-center justify-center z-50">
69
- <AnimatePresence>
70
- {stage === 'email_sent' && (
71
- <motion.div
72
- key="email"
73
- className="bg-white rounded-2xl shadow-xl p-6 flex flex-col items-center"
74
- initial={{ scale: 0.9, opacity: 0 }}
75
- animate={{ scale: 1, opacity: 1 }}
76
- exit={{ scale: 0.8, opacity: 0 }}
77
- >
78
- <Mail size={32} className="mb-2" style={{ color: colorCode }} />
79
- <p className="text-lg font-semibold">
80
- Sending your request to support…
81
- </p>
82
- <div className="flex space-x-2 mt-2">
83
- {dots.map((_, i) => (
84
- <motion.span
85
- key={i}
86
- className="text-2xl"
87
- style={{ color: colorCode }}
88
- animate={{ scale: [0.7, 1.3, 0.7] }}
89
- transition={{ delay: i * 0.2, repeat: Infinity, duration: 0.8 }}
90
- >
91
-
92
- </motion.span>
93
- ))}
94
- </div>
95
- </motion.div>
96
- )}
97
-
98
- {stage === 'connecting' && (
99
- <motion.div
100
- key="connecting"
101
- className="bg-white rounded-2xl shadow-xl p-6 flex flex-col items-center"
102
- initial={{ scale: 0.9, opacity: 0 }}
103
- animate={{ scale: 1, opacity: 1 }}
104
- exit={{ scale: 0.8, opacity: 0 }}
105
- >
106
- <div className="flex items-center space-x-4">
107
- <img
108
- src={data.userImage}
109
- alt="User"
110
- className="w-12 h-12 rounded-full border-2"
111
- style={{ borderColor: colorCode }}
112
- />
113
- <p className="text-lg">
114
- Connecting you to{' '}
115
- <span className="text-indigo-600">
116
- {data.agentName || 'Support Agent'}
117
- </span>
118
- </p>
119
- <img
120
- src={data.companyImage}
121
- alt="Company"
122
- className="w-12 h-12 rounded-full border"
123
- />
124
- </div>
125
- <div className="flex space-x-2 mt-3">
126
- {dots.map((_, i) => (
127
- <motion.span
128
- key={i}
129
- className="text-2xl"
130
- style={{ color: colorCode }}
131
- animate={{ scale: [0.7, 1.3, 0.7] }}
132
- transition={{ delay: i * 0.2, repeat: Infinity, duration: 0.8 }}
133
- >
134
-
135
- </motion.span>
136
- ))}
137
- </div>
138
- <div className="w-full bg-gray-200 h-1 rounded-full mt-4 overflow-hidden">
139
- <motion.div
140
- className="h-full"
141
- style={{ width: `${progress}%`, backgroundColor: colorCode }}
142
- transition={{ ease: 'linear', duration: 1 }}
143
- />
144
- </div>
145
- </motion.div>
146
- )}
147
-
148
- {stage === 'auto' && (
149
- <motion.div
150
- key="auto"
151
- className="bg-white rounded-2xl shadow-xl p-6 flex items-center space-x-4"
152
- initial={{ y: 50, opacity: 0 }}
153
- animate={{ y: 0, opacity: 1 }}
154
- exit={{ y: -50, opacity: 0 }}
155
- >
156
- <img
157
- src={
158
- data.agentAvatar ||
159
- 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSaC0jamaBcOGTbS86459UezKUs2Wo0lPU_mw&s'
160
- }
161
- alt="Auto Support"
162
- className="w-12 h-12 rounded-2xl"
163
- />
164
- <p className="text-lg">
165
- You’re now connected to{' '}
166
- <span style={{ color: colorCode }}>
167
- {data.agentName || 'Auto-Support'}
168
- </span>
169
- </p>
170
- </motion.div>
171
- )}
172
- </AnimatePresence>
173
- </div>
174
- );
175
- };
176
-
177
- export default SupportConnect;
@@ -1,27 +0,0 @@
1
- .typing-animation span {
2
- display: inline-block;
3
- animation: blink 1.4s infinite;
4
- font-size: 20px;
5
- margin: 0 2px;
6
- color: #555;
7
- }
8
-
9
- .typing-animation span:nth-child(2) {
10
- animation-delay: 0.2s;
11
- }
12
- .typing-animation span:nth-child(3) {
13
- animation-delay: 0.4s;
14
- }
15
-
16
- @keyframes blink {
17
- 0% {
18
- opacity: 0.2;
19
- }
20
- 20% {
21
- opacity: 1;
22
- }
23
- 100% {
24
- opacity: 0.2;
25
- }
26
- }
27
-
@@ -1,14 +0,0 @@
1
- import React from 'react';
2
- import './Typing.css'; // make sure this file contains the animation
3
-
4
- const Typing: React.FC = () => {
5
- return (
6
- <div className="typing-animation">
7
- <span>.</span>
8
- <span>.</span>
9
- <span>.</span>
10
- </div>
11
- );
12
- };
13
-
14
- export default Typing;
@@ -1,142 +0,0 @@
1
- import React from 'react';
2
- import { ShoppingCartOutlined } from '@ant-design/icons';
3
-
4
- interface ChatMessageProps {
5
- message: string;
6
- colorCode: string;
7
- isBusiness?: boolean;
8
- handleAddToCart: (info: string) => void;
9
- }
10
-
11
- interface ProductDetails {
12
- name: string;
13
- price: string;
14
- link: string;
15
- image: string;
16
- variant_id: string;
17
- }
18
-
19
- const ZidAssistantChatMessage: React.FC<ChatMessageProps> = ({
20
- message,
21
- colorCode,
22
- handleAddToCart,
23
- }) => {
24
- if (!message) return null;
25
-
26
- // 1. Rejoin the message and split into logical product blocks
27
- const combinedMessage = message.split('|||').join('\n');
28
- const segments = combinedMessage
29
- .split(/(?=Name\s*[:\-])/g)
30
- .map((seg) => seg.trim())
31
- .filter(Boolean);
32
-
33
- // 2. Extract product details
34
- const extractProductDetails = (text: string): ProductDetails | null => {
35
- const normalized = text.trim();
36
-
37
- if (!normalized.startsWith('Name:')) return null;
38
-
39
- if (
40
- !normalized.includes('Price:') ||
41
- !normalized.includes('Link:') ||
42
- (!normalized.includes('img -') && !normalized.includes('img:'))
43
- ) {
44
- return null;
45
- }
46
-
47
- const nameMatch = normalized.match(/Name\s*[:\-]\s*(.+)/i);
48
- const priceMatch = normalized.match(/Price\s*[:\-]\s*(.+)/i);
49
- const linkMatch = normalized.match(/Link\s*[:\-]\s*(https?:\/\/[^\s]+)/i);
50
- const imgMatch = normalized.match(/img\s*[:\-]\s*(https?:\/\/[^\s]+)/i);
51
- const variantMatch = normalized.match(/VariantId\s*[:\-]\s*(.+)/i);
52
-
53
- if (!nameMatch || !priceMatch || !linkMatch || !imgMatch) return null;
54
-
55
- return {
56
- name: nameMatch[1].trim(),
57
- price: priceMatch[1].trim(),
58
- link: linkMatch[1].trim(),
59
- image: imgMatch[1].trim(),
60
- variant_id: variantMatch?.[1]?.trim() || '',
61
- };
62
- };
63
-
64
- // 3. Linkify plain text
65
- const formatTextWithLinks = (text: string): React.ReactNode[] => {
66
- const urlRegex = /(https?:\/\/[^\s]+)/g;
67
- return text?.split(urlRegex).map((part, i) =>
68
- urlRegex.test(part) ? (
69
- <a
70
- key={i}
71
- href={part.trim()}
72
- style={{ color: colorCode }}
73
- target="_blank"
74
- rel="noopener noreferrer"
75
- className="underline break-words"
76
- >
77
- {part}
78
- </a>
79
- ) : (
80
- <span key={i}>{part}</span>
81
- )
82
- );
83
- };
84
-
85
- // 4. Render UI
86
- return (
87
- <div className="space-y-4">
88
- {segments.map((part, idx) => {
89
- const product = extractProductDetails(part);
90
-
91
- if (product) {
92
- return (
93
- <div
94
- key={idx}
95
- className="flex items-center bg-white shadow-lg rounded-2xl p-4 space-x-4"
96
- >
97
- <div className="w-32 h-32 sm:w-40 sm:h-40 relative">
98
- <img
99
- src={product.image}
100
- alt={product.name}
101
- className="w-full h-full object-cover rounded-xl cursor-pointer"
102
- onClick={() => window.open(product.link, '_blank')}
103
- />
104
- </div>
105
- <div className="flex-1">
106
- <a
107
- href={product.link}
108
- target="_blank"
109
- rel="noopener noreferrer"
110
- className="text-lg font-semibold text-gray-900"
111
- >
112
- {product.name}
113
- </a>
114
- <p className="text-md font-medium text-gray-700">{product.price}</p>
115
- <button
116
- className="mt-3 flex items-center gap-2 px-4 py-2 rounded-lg font-semibold transition hover:opacity-90"
117
- style={{ backgroundColor: colorCode, color: '#fff' }}
118
- onClick={() =>
119
- handleAddToCart(
120
- `name:${product.name},variantId:${product.variant_id},Link:${product.link}`
121
- )
122
- }
123
- >
124
- <ShoppingCartOutlined />
125
- <span>+</span>
126
- </button>
127
- </div>
128
- </div>
129
- );
130
- }
131
-
132
- return (
133
- <p key={idx} className="whitespace-pre-wrap break-words">
134
- {formatTextWithLinks(part)}
135
- </p>
136
- );
137
- })}
138
- </div>
139
- );
140
- };
141
-
142
- export default ZidAssistantChatMessage;