ajaxter-chat 3.0.9 → 3.0.11
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/components/ChatScreen/index.js +256 -34
- package/dist/components/ChatWidget.js +21 -3
- package/dist/components/HomeScreen/index.d.ts +5 -1
- package/dist/components/HomeScreen/index.js +6 -4
- package/dist/components/RecentChatsScreen/index.d.ts +1 -0
- package/dist/components/RecentChatsScreen/index.js +28 -6
- package/dist/components/TicketFormScreen/index.js +19 -13
- package/dist/components/TicketScreen/index.d.ts +1 -0
- package/dist/components/TicketScreen/index.js +31 -9
- package/dist/components/UserListScreen/index.d.ts +4 -0
- package/dist/components/UserListScreen/index.js +40 -12
- package/dist/types/index.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/ChatScreen/index.tsx +365 -62
- package/src/components/ChatWidget.tsx +28 -6
- package/src/components/HomeScreen/index.tsx +12 -5
- package/src/components/RecentChatsScreen/index.tsx +97 -44
- package/src/components/TicketFormScreen/index.tsx +17 -6
- package/src/components/TicketScreen/index.tsx +63 -11
- package/src/components/UserListScreen/index.tsx +87 -15
- package/src/types/index.ts +2 -0
|
@@ -23,7 +23,9 @@ export const HomeScreen = ({ config, onNavigate, onOpenTicket, tickets }) => {
|
|
|
23
23
|
return;
|
|
24
24
|
window.location.href = `tel:${raw.replace(/\s/g, '')}`;
|
|
25
25
|
};
|
|
26
|
-
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', position: 'relative', overflow: 'hidden', background: '#fafbfc' }, children: [_jsx(SlideNavMenu, { open: menuOpen, onClose: () => setMenuOpen(false), primaryColor: config.primaryColor, chatType: config.chatType, viewerType: (_d = config.viewerType) !== null && _d !== void 0 ? _d : 'user', onSelect:
|
|
26
|
+
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', position: 'relative', overflow: 'hidden', background: '#fafbfc' }, children: [_jsx(SlideNavMenu, { open: menuOpen, onClose: () => setMenuOpen(false), primaryColor: config.primaryColor, chatType: config.chatType, viewerType: (_d = config.viewerType) !== null && _d !== void 0 ? _d : 'user', onSelect: ctx => {
|
|
27
|
+
onNavigate(ctx, { fromMenu: true });
|
|
28
|
+
} }), _jsx("div", { style: {
|
|
27
29
|
flexShrink: 0,
|
|
28
30
|
padding: '14px 16px 10px',
|
|
29
31
|
display: 'flex',
|
|
@@ -51,7 +53,7 @@ export const HomeScreen = ({ config, onNavigate, onOpenTicket, tickets }) => {
|
|
|
51
53
|
color: '#0f172a',
|
|
52
54
|
letterSpacing: '-0.03em',
|
|
53
55
|
lineHeight: 1.2,
|
|
54
|
-
}, children: config.welcomeTitle }), _jsx("p", { style: { margin: '0 0 28px', fontSize: 14, color: '#64748b', lineHeight: 1.55 }, children: config.welcomeSubtitle }), _jsx("h2", { style: { margin: '0 0 12px', fontSize: 15, fontWeight: 800, color: '#0f172a' }, children: "Continue
|
|
56
|
+
}, children: config.welcomeTitle }), _jsx("p", { style: { margin: '0 0 28px', fontSize: 14, color: '#64748b', lineHeight: 1.55 }, children: config.welcomeSubtitle }), _jsx("h2", { style: { margin: '0 0 12px', fontSize: 15, fontWeight: 800, color: '#0f172a' }, children: "Continue with tickets" }), _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 10, marginBottom: 28 }, children: pendingTickets.length > 0 ? (pendingTickets.map(t => (_jsxs("button", { type: "button", onClick: () => onOpenTicket(t.id), style: {
|
|
55
57
|
width: '100%',
|
|
56
58
|
textAlign: 'left',
|
|
57
59
|
padding: '14px 16px',
|
|
@@ -75,7 +77,7 @@ export const HomeScreen = ({ config, onNavigate, onOpenTicket, tickets }) => {
|
|
|
75
77
|
color: '#64748b',
|
|
76
78
|
fontSize: 14,
|
|
77
79
|
fontWeight: 500,
|
|
78
|
-
}, children: "Start via Raise ticket below" })] })) }), _jsx("h2", { style: { margin: '0 0 12px', fontSize: 15, fontWeight: 800, color: '#0f172a' }, children: viewerIsDev ? 'Support tools' : 'Talk to
|
|
80
|
+
}, children: "Start via Raise ticket below" })] })) }), _jsx("h2", { style: { margin: '0 0 12px', fontSize: 15, fontWeight: 800, color: '#0f172a' }, children: viewerIsDev ? 'Support tools' : 'Talk to support experts' }), showSupport && (_jsxs("button", { type: "button", onClick: () => onNavigate('support'), style: {
|
|
79
81
|
width: '100%',
|
|
80
82
|
display: 'flex',
|
|
81
83
|
alignItems: 'center',
|
|
@@ -149,5 +151,5 @@ export const HomeScreen = ({ config, onNavigate, onOpenTicket, tickets }) => {
|
|
|
149
151
|
fontSize: 14,
|
|
150
152
|
fontWeight: 700,
|
|
151
153
|
cursor: config.supportPhone ? 'pointer' : 'not-allowed',
|
|
152
|
-
}, children: [_jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07A19.5 19.5 0 013.07 10.8a19.79 19.79 0 01-3.07-8.68A2 2 0 012 0h3a2 2 0 012 1.72c.127.96.361 1.903.7 2.81a2 2 0 01-.45 2.11L6.09 7.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0122 14.92v2z", fill: "#fff" }) }), "
|
|
154
|
+
}, children: [_jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07A19.5 19.5 0 013.07 10.8a19.79 19.79 0 01-3.07-8.68A2 2 0 012 0h3a2 2 0 012 1.72c.127.96.361 1.903.7 2.81a2 2 0 01-.45 2.11L6.09 7.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0122 14.92v2z", fill: "#fff" }) }), "Get Free Widget"] })] })] })] })] }));
|
|
153
155
|
};
|
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useMemo, useRef, useEffect } from 'react';
|
|
2
3
|
import { avatarColor, initials, formatTime } from '../../utils/chat';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
function matchesChat(chat, q) {
|
|
5
|
+
if (!q.trim())
|
|
6
|
+
return true;
|
|
7
|
+
const s = q.trim().toLowerCase();
|
|
8
|
+
return (chat.user.name.toLowerCase().includes(s) ||
|
|
9
|
+
chat.lastMessage.toLowerCase().includes(s));
|
|
10
|
+
}
|
|
11
|
+
export const RecentChatsScreen = ({ chats, config, onSelectChat, animateEntrance = false, }) => {
|
|
12
|
+
const [query, setQuery] = useState('');
|
|
13
|
+
const searchRef = useRef(null);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
var _a;
|
|
16
|
+
(_a = searchRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
17
|
+
}, []);
|
|
18
|
+
const filtered = useMemo(() => chats.filter(c => matchesChat(c, query)), [chats, query]);
|
|
19
|
+
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%' }, children: [_jsxs("div", { style: { background: `linear-gradient(135deg,${config.primaryColor},${config.primaryColor}cc)`, padding: '18px 18px 14px', flexShrink: 0 }, children: [_jsx("h2", { style: { margin: 0, fontSize: 20, fontWeight: 800, color: '#fff', letterSpacing: '-0.02em' }, children: "Recent Chats" }), _jsx("p", { style: { margin: '3px 0 0', fontSize: 12, color: 'rgba(255,255,255,0.8)' }, children: "Your conversation history" })] }), _jsx("div", { style: { padding: '10px 14px', background: '#fff', borderBottom: '1px solid #eef0f5', flexShrink: 0 }, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, padding: '0 12px', borderRadius: 10, border: '1.5px solid #e5e7eb', background: '#f8fafc' }, children: [_jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0, opacity: 0.55 }, children: [_jsx("circle", { cx: "11", cy: "11", r: "7", stroke: "#64748b", strokeWidth: "2" }), _jsx("path", { d: "M20 20l-4-4", stroke: "#64748b", strokeWidth: "2", strokeLinecap: "round" })] }), _jsx("input", { ref: searchRef, type: "search", value: query, onChange: e => setQuery(e.target.value), placeholder: "Search chats\u2026", autoComplete: "off", "aria-label": "Search chats", style: {
|
|
20
|
+
flex: 1,
|
|
21
|
+
minWidth: 0,
|
|
22
|
+
border: 'none',
|
|
23
|
+
outline: 'none',
|
|
24
|
+
background: 'transparent',
|
|
25
|
+
fontSize: 14,
|
|
26
|
+
padding: '10px 0',
|
|
27
|
+
fontFamily: 'inherit',
|
|
28
|
+
color: '#1a2332',
|
|
29
|
+
} })] }) }), _jsx("div", { style: { flex: 1, overflowY: 'auto' }, children: filtered.length === 0 ? (_jsxs("div", { style: { padding: '50px 24px', textAlign: 'center' }, children: [_jsx("div", { style: { fontSize: 36, marginBottom: 10 }, children: query.trim() ? '🔍' : '💬' }), _jsx("div", { style: { fontWeight: 700, color: '#1a2332', marginBottom: 6 }, children: query.trim() ? 'No matches' : 'No chats yet' }), _jsx("div", { style: { fontSize: 13, color: '#7b8fa1' }, children: query.trim() ? 'Try a different search' : 'Start a conversation from home' })] })) : filtered.map((chat, i) => (_jsxs("button", { onClick: () => onSelectChat(chat.user), style: Object.assign(Object.assign({ width: '100%', padding: '13px 16px', display: 'flex', alignItems: 'center', gap: 13, background: 'transparent', border: 'none', borderBottom: '1px solid #f0f2f5', cursor: 'pointer', textAlign: 'left' }, (animateEntrance ? { animation: `cw-fadeUp 0.28s ease both`, animationDelay: `${i * 0.05}s` } : {})), { transition: 'background 0.14s' }), onMouseEnter: e => e.currentTarget.style.background = '#f8faff', onMouseLeave: e => e.currentTarget.style.background = 'transparent', children: [_jsxs("div", { style: { position: 'relative', flexShrink: 0 }, children: [_jsx("div", { style: { width: 46, height: 46, borderRadius: '50%', backgroundColor: avatarColor(chat.user.name), display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontWeight: 700, fontSize: 15 }, children: initials(chat.user.name) }), chat.unread > 0 && (_jsx("span", { style: { position: 'absolute', top: -2, right: -2, width: 18, height: 18, borderRadius: '50%', background: '#ef4444', color: '#fff', fontSize: 10, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center', border: '2px solid #fff' }, children: chat.unread }))] }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', marginBottom: 3 }, children: [_jsx("span", { style: { fontWeight: 700, fontSize: 14, color: '#1a2332' }, children: chat.user.name }), _jsx("span", { style: { fontSize: 11, color: '#b0bec5' }, children: formatTime(chat.lastTime) })] }), _jsxs("div", { style: { fontSize: 13, color: '#7b8fa1', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'flex', alignItems: 'center', gap: 5 }, children: [chat.isPaused && _jsx("span", { style: { fontSize: 10, background: '#fef3c7', color: '#92400e', padding: '1px 5px', borderRadius: 4, fontWeight: 700 }, children: "PAUSED" }), chat.lastMessage] })] })] }, chat.id))) })] }));
|
|
30
|
+
};
|
|
@@ -28,7 +28,7 @@ export const TicketFormScreen = ({ config, onSubmit, onCancel }) => {
|
|
|
28
28
|
return;
|
|
29
29
|
onSubmit(title.trim(), desc.trim(), priority);
|
|
30
30
|
};
|
|
31
|
-
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', background: '#fff' }, children: [_jsxs("div", { style: {
|
|
31
|
+
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', background: '#fff', minHeight: 0 }, children: [_jsxs("div", { style: {
|
|
32
32
|
background: `linear-gradient(135deg,${config.primaryColor},${config.primaryColor}cc)`,
|
|
33
33
|
padding: '14px 18px',
|
|
34
34
|
display: 'flex',
|
|
@@ -45,7 +45,7 @@ export const TicketFormScreen = ({ config, onSubmit, onCancel }) => {
|
|
|
45
45
|
alignItems: 'center',
|
|
46
46
|
justifyContent: 'center',
|
|
47
47
|
cursor: 'pointer',
|
|
48
|
-
}, children: _jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M19 12H5M5 12L12 19M5 12L12 5", stroke: "#fff", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), _jsxs("div", { children: [_jsx("h2", { style: { margin: 0, fontSize: 18, fontWeight: 800, color: '#fff' }, children: "
|
|
48
|
+
}, children: _jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M19 12H5M5 12L12 19M5 12L12 5", stroke: "#fff", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), _jsxs("div", { children: [_jsx("h2", { style: { margin: 0, fontSize: 18, fontWeight: 800, color: '#fff' }, children: "Raise a ticket" }), _jsx("p", { style: { margin: '4px 0 0', fontSize: 12, color: 'rgba(255,255,255,0.85)' }, children: "Please fill out the ticket form below and we will get back to you as soon as possible." })] })] }), _jsxs("div", { className: "cw-scroll", style: { flex: 1, overflowY: 'auto', padding: '20px 18px', minHeight: 0 }, children: [_jsx("input", { placeholder: "Title *", value: title, onChange: e => setTitle(e.target.value), style: inputStyle(config.primaryColor), onFocus: e => (e.target.style.borderColor = config.primaryColor), onBlur: e => (e.target.style.borderColor = '#e5e7eb') }), _jsx("textarea", { placeholder: "Describe the issue\u2026", value: desc, onChange: e => setDesc(e.target.value), rows: 5, style: Object.assign(Object.assign({}, inputStyle(config.primaryColor)), { resize: 'none', marginTop: 12 }), onFocus: e => (e.target.style.borderColor = config.primaryColor), onBlur: e => (e.target.style.borderColor = '#e5e7eb') }), _jsx("div", { style: { display: 'flex', gap: 8, marginTop: 12, paddingBottom: 8 }, children: ['low', 'medium', 'high'].map(p => (_jsx("button", { type: "button", onClick: () => setPriority(p), style: {
|
|
49
49
|
flex: 1,
|
|
50
50
|
padding: '8px',
|
|
51
51
|
border: `1.5px solid ${priority === p ? pm[p].color : '#e5e7eb'}`,
|
|
@@ -56,15 +56,21 @@ export const TicketFormScreen = ({ config, onSubmit, onCancel }) => {
|
|
|
56
56
|
fontSize: 12,
|
|
57
57
|
cursor: 'pointer',
|
|
58
58
|
textTransform: 'capitalize',
|
|
59
|
-
}, children: pm[p].label }, p))) }), _jsx("
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
}, children: pm[p].label }, p))) })] }), _jsx("div", { style: {
|
|
60
|
+
flexShrink: 0,
|
|
61
|
+
padding: '12px 18px 18px',
|
|
62
|
+
borderTop: '1px solid #eef0f5',
|
|
63
|
+
background: '#fff',
|
|
64
|
+
boxShadow: '0 -4px 20px rgba(15,23,42,0.06)',
|
|
65
|
+
}, children: _jsx("button", { type: "button", onClick: handleSubmit, disabled: !title.trim(), style: {
|
|
66
|
+
width: '100%',
|
|
67
|
+
padding: '14px',
|
|
68
|
+
borderRadius: 10,
|
|
69
|
+
border: 'none',
|
|
70
|
+
background: title.trim() ? config.primaryColor : '#e5e7eb',
|
|
71
|
+
color: title.trim() ? '#fff' : '#9ca3af',
|
|
72
|
+
fontWeight: 700,
|
|
73
|
+
fontSize: 15,
|
|
74
|
+
cursor: title.trim() ? 'pointer' : 'not-allowed',
|
|
75
|
+
}, children: "Submit ticket" }) })] }));
|
|
70
76
|
};
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
|
|
2
|
+
import { useState, useMemo, useRef, useEffect } from 'react';
|
|
3
|
+
function matchesTicket(t, q) {
|
|
4
|
+
if (!q.trim())
|
|
5
|
+
return true;
|
|
6
|
+
const s = q.trim().toLowerCase();
|
|
7
|
+
return (t.title.toLowerCase().includes(s) ||
|
|
8
|
+
t.description.toLowerCase().includes(s) ||
|
|
9
|
+
t.id.toLowerCase().includes(s));
|
|
10
|
+
}
|
|
11
|
+
export const TicketScreen = ({ tickets, config, onNewTicket, onSelectTicket, animateEntrance = false, }) => {
|
|
12
|
+
const [query, setQuery] = useState('');
|
|
13
|
+
const searchRef = useRef(null);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
var _a;
|
|
16
|
+
(_a = searchRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
17
|
+
}, []);
|
|
18
|
+
const filtered = useMemo(() => tickets.filter(t => matchesTicket(t, query)), [tickets, query]);
|
|
3
19
|
const sm = {
|
|
4
20
|
open: { label: 'Open', bg: `${config.primaryColor}14`, color: config.primaryColor },
|
|
5
21
|
'in-progress': { label: 'In Progress', bg: '#fef3c7', color: '#d97706' },
|
|
@@ -13,15 +29,21 @@ export const TicketScreen = ({ tickets, config, onNewTicket, onSelectTicket }) =
|
|
|
13
29
|
};
|
|
14
30
|
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%' }, children: [_jsx("div", { style: {
|
|
15
31
|
background: `linear-gradient(135deg,${config.primaryColor},${config.primaryColor}cc)`,
|
|
16
|
-
padding: '18px 18px
|
|
17
|
-
}, children: _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }, children: [_jsxs("div", { children: [_jsx("h2", { style: { margin: 0, fontSize: 20, fontWeight: 800, color: '#fff', letterSpacing: '-0.02em' }, children: "Tickets" }), _jsxs("p", { style: { margin: '3px 0 0', fontSize: 12, color: 'rgba(255,255,255,0.8)' }, children: [tickets.length, " ticket", tickets.length !== 1 ? 's' : '', " raised"] })] }), _jsx("button", { type: "button", onClick: onNewTicket, style: {
|
|
32
|
+
padding: '18px 18px 14px', flexShrink: 0, position: 'relative',
|
|
33
|
+
}, children: _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12 }, children: [_jsxs("div", { style: { minWidth: 0 }, children: [_jsx("h2", { style: { margin: 0, fontSize: 20, fontWeight: 800, color: '#fff', letterSpacing: '-0.02em' }, children: "Tickets" }), _jsxs("p", { style: { margin: '3px 0 0', fontSize: 12, color: 'rgba(255,255,255,0.8)' }, children: [tickets.length, " ticket", tickets.length !== 1 ? 's' : '', " raised"] })] }), _jsx("button", { type: "button", onClick: onNewTicket, style: {
|
|
18
34
|
background: 'rgba(255,255,255,0.22)', border: 'none', borderRadius: 20,
|
|
19
35
|
padding: '7px 14px', color: '#fff', fontWeight: 700, fontSize: 13,
|
|
20
36
|
cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 5,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
flexShrink: 0,
|
|
38
|
+
}, children: "+ New" })] }) }), _jsx("div", { style: { padding: '10px 14px', background: '#fff', borderBottom: '1px solid #eef0f5', flexShrink: 0 }, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, padding: '0 12px', borderRadius: 10, border: '1.5px solid #e5e7eb', background: '#f8fafc' }, children: [_jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0, opacity: 0.55 }, children: [_jsx("circle", { cx: "11", cy: "11", r: "7", stroke: "#64748b", strokeWidth: "2" }), _jsx("path", { d: "M20 20l-4-4", stroke: "#64748b", strokeWidth: "2", strokeLinecap: "round" })] }), _jsx("input", { ref: searchRef, type: "search", value: query, onChange: e => setQuery(e.target.value), placeholder: "Search tickets\u2026", autoComplete: "off", "aria-label": "Search tickets", style: {
|
|
39
|
+
flex: 1,
|
|
40
|
+
minWidth: 0,
|
|
41
|
+
border: 'none',
|
|
42
|
+
outline: 'none',
|
|
43
|
+
background: 'transparent',
|
|
44
|
+
fontSize: 14,
|
|
45
|
+
padding: '10px 0',
|
|
46
|
+
fontFamily: 'inherit',
|
|
47
|
+
color: '#1a2332',
|
|
48
|
+
} })] }) }), _jsx("div", { style: { flex: 1, overflowY: 'auto' }, children: filtered.length === 0 ? (_jsxs("div", { style: { padding: '50px 24px', textAlign: 'center' }, children: [_jsx("div", { style: { fontSize: 36, marginBottom: 10 }, children: query.trim() ? '🔍' : '🎫' }), _jsx("div", { style: { fontWeight: 700, color: '#1a2332', marginBottom: 6 }, children: query.trim() ? 'No matches' : 'No tickets yet' }), _jsx("div", { style: { fontSize: 13, color: '#7b8fa1' }, children: query.trim() ? 'Try a different search' : 'Raise a ticket for major issues' })] })) : filtered.map((t, i) => (_jsxs("button", { type: "button", onClick: () => onSelectTicket(t.id), style: Object.assign(Object.assign({ width: '100%', padding: '14px 16px', borderBottom: '1px solid #f0f2f5' }, (animateEntrance ? { animation: `cw-fadeUp 0.3s ease both`, animationDelay: `${i * 0.05}s` } : {})), { background: 'transparent', borderLeft: 'none', borderRight: 'none', borderTop: 'none', cursor: 'pointer', textAlign: 'left', fontFamily: 'inherit' }), children: [_jsxs("div", { style: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 5 }, children: [_jsx("span", { style: { fontWeight: 700, fontSize: 14, color: '#1a2332', flex: 1, paddingRight: 10 }, children: t.title }), _jsx("span", { style: { fontSize: 10, fontWeight: 700, padding: '3px 9px', borderRadius: 20, backgroundColor: sm[t.status].bg, color: sm[t.status].color, whiteSpace: 'nowrap', textTransform: 'uppercase', letterSpacing: '0.04em', flexShrink: 0 }, children: sm[t.status].label })] }), t.description && _jsx("p", { style: { margin: '0 0 7px', fontSize: 13, color: '#7b8fa1', lineHeight: 1.5 }, children: t.description }), _jsxs("div", { style: { display: 'flex', gap: 10, fontSize: 11, color: '#b0bec5' }, children: [_jsxs("span", { style: { color: pm[t.priority].color, fontWeight: 700 }, children: ["\u25CF ", pm[t.priority].label] }), _jsxs("span", { children: ["#", t.id] }), _jsx("span", { children: new Date(t.createdAt).toLocaleDateString([], { month: 'short', day: 'numeric' }) })] })] }, t.id))) })] }));
|
|
27
49
|
};
|
|
@@ -10,6 +10,10 @@ interface UserListScreenProps {
|
|
|
10
10
|
onSelectUser: (user: ChatUser) => void;
|
|
11
11
|
/** Shown on “New Conversation” list — opens block list */
|
|
12
12
|
onBlockList?: () => void;
|
|
13
|
+
/** “Need Support” (user → agents): show home icon instead of back arrow */
|
|
14
|
+
useHomeHeader?: boolean;
|
|
15
|
+
/** Stagger animation — only when opening from home burger menu */
|
|
16
|
+
animateEntrance?: boolean;
|
|
13
17
|
}
|
|
14
18
|
export declare const UserListScreen: React.FC<UserListScreenProps>;
|
|
15
19
|
export {};
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useMemo, useRef, useEffect } from 'react';
|
|
2
3
|
import { avatarColor, initials } from '../../utils/chat';
|
|
3
|
-
|
|
4
|
+
function matchesUser(u, q) {
|
|
5
|
+
if (!q.trim())
|
|
6
|
+
return true;
|
|
7
|
+
const s = q.trim().toLowerCase();
|
|
8
|
+
return (u.name.toLowerCase().includes(s) ||
|
|
9
|
+
u.email.toLowerCase().includes(s) ||
|
|
10
|
+
u.designation.toLowerCase().includes(s) ||
|
|
11
|
+
u.project.toLowerCase().includes(s));
|
|
12
|
+
}
|
|
13
|
+
export const UserListScreen = ({ context, users, primaryColor, viewerType = 'user', onBack, onSelectUser, onBlockList, useHomeHeader = false, animateEntrance = false, }) => {
|
|
14
|
+
const [query, setQuery] = useState('');
|
|
15
|
+
const searchRef = useRef(null);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
var _a;
|
|
18
|
+
(_a = searchRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
19
|
+
}, []);
|
|
20
|
+
const filtered = useMemo(() => users.filter(u => matchesUser(u, query)), [users, query]);
|
|
4
21
|
const isStaff = viewerType === 'developer';
|
|
5
22
|
const title = context === 'support'
|
|
6
23
|
? (isStaff ? 'Provide Support' : 'Need Support')
|
|
@@ -8,7 +25,8 @@ export const UserListScreen = ({ context, users, primaryColor, viewerType = 'use
|
|
|
8
25
|
const subtitle = context === 'support'
|
|
9
26
|
? (isStaff ? 'All chat users — choose who to help' : 'Choose a support agent')
|
|
10
27
|
: (isStaff ? 'Chat with another developer or coordinate handoff' : 'Choose a colleague');
|
|
11
|
-
|
|
28
|
+
const rootAnim = animateEntrance ? 'cw-slideIn 0.22s ease' : undefined;
|
|
29
|
+
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', animation: rootAnim }, children: [_jsxs("div", { style: { background: `linear-gradient(135deg,${primaryColor},${primaryColor}cc)`, padding: '14px 18px', display: 'flex', alignItems: 'center', gap: 12, flexShrink: 0, position: 'relative' }, children: [useHomeHeader ? _jsx(HomeBtn, { onClick: onBack }) : _jsx(BackBtn, { onClick: onBack }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsx("div", { style: { fontWeight: 700, fontSize: 16, color: '#fff' }, children: title }), _jsx("div", { style: { fontSize: 12, color: 'rgba(255,255,255,0.8)' }, children: subtitle })] }), context === 'conversation' && onBlockList && (_jsxs("button", { type: "button", onClick: onBlockList, style: {
|
|
12
30
|
flexShrink: 0,
|
|
13
31
|
background: 'rgba(255,255,255,0.2)',
|
|
14
32
|
border: 'none',
|
|
@@ -21,14 +39,19 @@ export const UserListScreen = ({ context, users, primaryColor, viewerType = 'use
|
|
|
21
39
|
display: 'flex',
|
|
22
40
|
alignItems: 'center',
|
|
23
41
|
gap: 6,
|
|
24
|
-
}, title: "Blocked users", children: [_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [_jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "1.8" }), _jsx("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })] }), "Blocked"] }))] }), _jsx("div", { style: {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
42
|
+
}, title: "Blocked users", children: [_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [_jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "1.8" }), _jsx("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })] }), "Blocked"] }))] }), _jsx("div", { style: { padding: '10px 14px', background: '#fff', borderBottom: '1px solid #eef0f5', flexShrink: 0 }, children: _jsxs("label", { style: { display: 'block', margin: 0 }, children: [_jsx("span", { style: { position: 'absolute', width: 1, height: 1, padding: 0, overflow: 'hidden', clip: 'rect(0,0,0,0)' }, children: "Search" }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, padding: '0 12px', borderRadius: 10, border: '1.5px solid #e5e7eb', background: '#f8fafc' }, children: [_jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0, opacity: 0.55 }, children: [_jsx("circle", { cx: "11", cy: "11", r: "7", stroke: "#64748b", strokeWidth: "2" }), _jsx("path", { d: "M20 20l-4-4", stroke: "#64748b", strokeWidth: "2", strokeLinecap: "round" })] }), _jsx("input", { ref: searchRef, type: "search", value: query, onChange: e => setQuery(e.target.value), placeholder: "Search by name\u2026", autoComplete: "off", style: {
|
|
43
|
+
flex: 1,
|
|
44
|
+
minWidth: 0,
|
|
45
|
+
border: 'none',
|
|
46
|
+
outline: 'none',
|
|
47
|
+
background: 'transparent',
|
|
48
|
+
fontSize: 14,
|
|
49
|
+
padding: '10px 0',
|
|
50
|
+
fontFamily: 'inherit',
|
|
51
|
+
color: '#1a2332',
|
|
52
|
+
} })] })] }) }), _jsx("div", { style: { flex: 1, overflowY: 'auto' }, children: filtered.length === 0 ? (_jsx(Empty, { hasQuery: !!query.trim() })) : filtered.map((u, i) => (_jsxs("button", { onClick: () => onSelectUser(u), style: Object.assign(Object.assign({ width: '100%', padding: '13px 18px', display: 'flex', alignItems: 'center', gap: 13, background: 'transparent', border: 'none', borderBottom: '1px solid #f0f2f5', cursor: 'pointer', textAlign: 'left' }, (animateEntrance
|
|
53
|
+
? { animation: `cw-fadeUp 0.28s ease both`, animationDelay: `${i * 0.05}s` }
|
|
54
|
+
: {})), { transition: 'background 0.14s' }), onMouseEnter: e => e.currentTarget.style.background = '#f8faff', onMouseLeave: e => e.currentTarget.style.background = 'transparent', children: [_jsxs("div", { style: { position: 'relative', flexShrink: 0 }, children: [_jsx("div", { style: {
|
|
32
55
|
width: 44, height: 44, borderRadius: '50%',
|
|
33
56
|
backgroundColor: avatarColor(u.name),
|
|
34
57
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
@@ -45,9 +68,14 @@ export const UserListScreen = ({ context, users, primaryColor, viewerType = 'use
|
|
|
45
68
|
border: `1px solid ${u.type === 'developer' ? primaryColor + '30' : '#16a34a30'}`,
|
|
46
69
|
}, children: u.type === 'developer' ? 'Dev' : 'User' })] }, u.uid))) })] }));
|
|
47
70
|
};
|
|
48
|
-
const BackBtn = ({ onClick }) => (_jsx("button", { onClick: onClick, style: {
|
|
71
|
+
const BackBtn = ({ onClick }) => (_jsx("button", { type: "button", onClick: onClick, style: {
|
|
49
72
|
background: 'rgba(255,255,255,0.22)', border: 'none', borderRadius: '50%',
|
|
50
73
|
width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
51
74
|
cursor: 'pointer', flexShrink: 0,
|
|
52
75
|
}, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M19 12H5M5 12L12 19M5 12L12 5", stroke: "#fff", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
|
|
53
|
-
const
|
|
76
|
+
const HomeBtn = ({ onClick }) => (_jsx("button", { type: "button", onClick: onClick, title: "Home", "aria-label": "Home", style: {
|
|
77
|
+
background: 'rgba(255,255,255,0.22)', border: 'none', borderRadius: '50%',
|
|
78
|
+
width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
79
|
+
cursor: 'pointer', flexShrink: 0,
|
|
80
|
+
}, children: _jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: [_jsx("path", { d: "M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H4a1 1 0 01-1-1V9.5z", stroke: "#fff", strokeWidth: "2.2", fill: "none", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M9 21V12h6v9", stroke: "#fff", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" })] }) }));
|
|
81
|
+
const Empty = ({ hasQuery }) => (_jsxs("div", { style: { padding: '50px 24px', textAlign: 'center' }, children: [_jsx("div", { style: { fontSize: 36, marginBottom: 10 }, children: hasQuery ? '🔍' : '👥' }), _jsx("div", { style: { fontWeight: 700, color: '#1a2332', marginBottom: 6 }, children: hasQuery ? 'No matches' : 'No users available' }), _jsx("div", { style: { fontSize: 13, color: '#7b8fa1' }, children: hasQuery ? 'Try a different search' : 'Check back later' })] }));
|
package/dist/types/index.d.ts
CHANGED
|
@@ -81,6 +81,8 @@ export interface ChatMessage {
|
|
|
81
81
|
attachmentSize?: string;
|
|
82
82
|
/** Blob URL for attachment download (local send) */
|
|
83
83
|
attachmentUrl?: string;
|
|
84
|
+
/** e.g. image/png — used for inline image preview in bubbles */
|
|
85
|
+
attachmentMime?: string;
|
|
84
86
|
voiceDuration?: number;
|
|
85
87
|
/** Blob URL for in-bubble audio playback (local recording) */
|
|
86
88
|
voiceUrl?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ajaxter-chat",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.11",
|
|
4
4
|
"description": "Drawer-based chat widget with support chat, tickets, WebRTC calling, voice messages, block list, and transcript download.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|