@banbox/chat 1.0.8 → 1.0.10
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/index.cjs +1203 -265
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +1127 -190
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/chat/InboxPopup.tsx +38 -35
- package/src/chat/SinglePopup.tsx +81 -40
- package/src/icons/index.tsx +55 -0
- package/src/index.ts +14 -12
- package/src/modals/ChatAddressModal.tsx +844 -0
- package/src/modals/{chat/ChatConfirmModal.tsx → ChatConfirmModal.tsx} +2 -2
- package/src/modals/ChatTranslateSettingsModal.tsx +182 -0
- package/src/styles/index.build.css +15 -0
- package/src/styles/index.css +10 -2
- package/src/ui/{chat/AttachmentPreviewStrip.tsx → AttachmentPreviewStrip.tsx} +2 -2
- package/src/ui/{chat/ChatComposerBar.tsx → ChatComposerBar.tsx} +2 -2
- package/src/ui/{chat/ChatFooter.tsx → ChatFooter.tsx} +102 -8
- package/src/ui/{chat/ChatIdentity.tsx → ChatIdentity.tsx} +2 -2
- package/src/ui/{chat/ChatInquiryBar.tsx → ChatInquiryBar.tsx} +1 -1
- package/src/ui/ChatKebabMenu.tsx +125 -0
- package/src/ui/{chat/ChatListHeader.tsx → ChatListHeader.tsx} +1 -1
- package/src/ui/{chat/ChatMessageItem.tsx → ChatMessageItem.tsx} +10 -32
- package/src/ui/{chat/ChatScroll.tsx → ChatScroll.tsx} +1 -1
- package/src/ui/{chat/ChatSpinner.tsx → ChatSpinner.tsx} +1 -1
- package/src/ui/{chat/ChatThreadItem.tsx → ChatThreadItem.tsx} +1 -1
- package/src/ui/{chat/MessageHoverActions.tsx → MessageHoverActions.tsx} +2 -2
- package/src/ui/{chat/ReplyCard.tsx → ReplyCard.tsx} +2 -2
- package/src/ui/{chat/TypingIndicator.tsx → TypingIndicator.tsx} +1 -1
- package/src/ui/{chat/drop-up → drop-up}/BusinessCardDropup.tsx +15 -3
- package/src/ui/{chat/drop-up → drop-up}/EmojiDropup.tsx +1 -1
- package/src/ui/{chat/message-items → message-items}/ChatAddressCard.tsx +4 -4
- package/src/ui/{chat/message-items → message-items}/ChatBubbleFiles.tsx +1 -1
- package/src/ui/{chat/message-items → message-items}/ChatBubbleImages.tsx +2 -2
- package/src/ui/{chat/message-items → message-items}/ChatBusinessCard.tsx +1 -1
- package/src/ui/{chat/scrollToMessage.ts → scrollToMessage.ts} +1 -1
- package/src/ui/{chat/types.ts → types.ts} +2 -2
- package/src/utils/theme.ts +37 -0
- package/src/modals/chat/ChatTranslateSettingsModal.tsx +0 -180
- /package/src/ui/{chat/ChatHeader.tsx → ChatHeader.tsx} +0 -0
- /package/src/ui/{chat/message-items → message-items}/ChatBubbleAudio.tsx +0 -0
- /package/src/ui/{chat/message-items → message-items}/ChatBubbleText.tsx +0 -0
package/package.json
CHANGED
package/src/chat/InboxPopup.tsx
CHANGED
|
@@ -6,19 +6,21 @@ import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
|
6
6
|
|
|
7
7
|
import { useChatUI } from "../contexts/ChatUIContext";
|
|
8
8
|
import { useGallery } from "../contexts/GalleryContext";
|
|
9
|
-
import ChatConfirmModal from "../modals/
|
|
10
|
-
import ChatFooter from "../ui/
|
|
11
|
-
import ChatHeader from "../ui/
|
|
12
|
-
import ChatIdentity from "../ui/
|
|
13
|
-
import ChatInquiryBar from "../ui/
|
|
14
|
-
import ChatListHeader from "../ui/
|
|
15
|
-
import ChatMessageItem from "../ui/
|
|
16
|
-
import ChatScroll from "../ui/
|
|
17
|
-
import type { ChatThreadStatus } from "../ui/
|
|
18
|
-
import ChatThreadItem from "../ui/
|
|
19
|
-
import TypingIndicator from "../ui/
|
|
9
|
+
import ChatConfirmModal from "../modals/ChatConfirmModal";
|
|
10
|
+
import ChatFooter from "../ui/ChatFooter";
|
|
11
|
+
import ChatHeader from "../ui/ChatHeader";
|
|
12
|
+
import ChatIdentity from "../ui/ChatIdentity";
|
|
13
|
+
import ChatInquiryBar from "../ui/ChatInquiryBar";
|
|
14
|
+
import ChatListHeader from "../ui/ChatListHeader";
|
|
15
|
+
import ChatMessageItem from "../ui/ChatMessageItem";
|
|
16
|
+
import ChatScroll from "../ui/ChatScroll";
|
|
17
|
+
import type { ChatThreadStatus } from "../ui/ChatThreadItem";
|
|
18
|
+
import ChatThreadItem from "../ui/ChatThreadItem";
|
|
19
|
+
import TypingIndicator from "../ui/TypingIndicator";
|
|
20
20
|
import ChatImagePreviewModal from "./ChatImagePreviewModal";
|
|
21
|
+
import { GRADIENT_BORDER, getThemeAttr, getThemeVars } from "../utils/theme";
|
|
21
22
|
|
|
23
|
+
import ChatKebabMenu from "../ui/ChatKebabMenu";
|
|
22
24
|
import type { ChatAdapter, ChatUICallbacks } from "../adapter/types";
|
|
23
25
|
import type { Message, MessageRef, Thread } from "../types";
|
|
24
26
|
|
|
@@ -43,23 +45,7 @@ const avatarBgByInitial: Record<string, string> = {
|
|
|
43
45
|
b: "#F0EDEB",
|
|
44
46
|
};
|
|
45
47
|
|
|
46
|
-
const GRADIENT_BORDER =
|
|
47
|
-
"linear-gradient(236.83deg, rgba(51,201,212,0.3) 0.4%, rgba(39,83,251,0.3) 30.28%, rgba(39,83,251,0.3) 50.2%, rgba(39,83,251,0.3) 65.14%, rgba(235,67,255,0.3) 100%)";
|
|
48
48
|
|
|
49
|
-
function getThemeAttr(theme?: ChatTheme): string {
|
|
50
|
-
if (!theme || theme === "marketplace") return "marketplace";
|
|
51
|
-
if (theme === "admin") return "admin";
|
|
52
|
-
return "custom";
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function getThemeVars(theme?: ChatTheme): React.CSSProperties {
|
|
56
|
-
if (!theme || theme === "marketplace" || theme === "admin") return {};
|
|
57
|
-
const vars: Record<string, string> = {};
|
|
58
|
-
if (theme.primary) vars["--color-banbox-primary"] = theme.primary;
|
|
59
|
-
if (theme.primaryActive) vars["--color-banbox-primary-active"] = theme.primaryActive;
|
|
60
|
-
if (theme.surfaceLow) vars["--color-banbox-surface-container-low"] = theme.surfaceLow;
|
|
61
|
-
return vars as React.CSSProperties;
|
|
62
|
-
}
|
|
63
49
|
|
|
64
50
|
/* ══════════════════════════════════════════════════
|
|
65
51
|
Component
|
|
@@ -135,12 +121,19 @@ const InboxPopup: React.FC<InboxPopupProps> = ({ adapter, uiCallbacks, theme })
|
|
|
135
121
|
|
|
136
122
|
const prevActiveIdRef = useRef(activeId);
|
|
137
123
|
useEffect(() => {
|
|
124
|
+
// Mark read on thread SWITCH
|
|
138
125
|
if (prevActiveIdRef.current !== activeId) {
|
|
139
126
|
prevActiveIdRef.current = activeId;
|
|
140
127
|
if (activeId) adapter.threads.markRead?.(activeId);
|
|
141
128
|
}
|
|
142
129
|
}, [activeId, adapter]);
|
|
143
130
|
|
|
131
|
+
// Mark read on initial open (prevActiveIdRef starts equal to activeId so the above won't fire)
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (activeId) adapter.threads.markRead?.(activeId);
|
|
134
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
135
|
+
}, []);
|
|
136
|
+
|
|
144
137
|
const toRef = (m: Message): MessageRef => ({
|
|
145
138
|
id: m.id,
|
|
146
139
|
author: typeof m.author === "string" ? m.author : "U",
|
|
@@ -183,7 +176,7 @@ const InboxPopup: React.FC<InboxPopupProps> = ({ adapter, uiCallbacks, theme })
|
|
|
183
176
|
RENDER
|
|
184
177
|
══════════════════════════════════════════════════ */
|
|
185
178
|
return (
|
|
186
|
-
<div className="fixed bottom-4 right-4 z-
|
|
179
|
+
<div className="fixed bottom-4 right-4 z-10002">
|
|
187
180
|
{/* Backdrop */}
|
|
188
181
|
<motion.button
|
|
189
182
|
aria-label="Close chat"
|
|
@@ -255,13 +248,23 @@ const InboxPopup: React.FC<InboxPopupProps> = ({ adapter, uiCallbacks, theme })
|
|
|
255
248
|
)
|
|
256
249
|
}
|
|
257
250
|
right={
|
|
258
|
-
uiCallbacks?.renderKebabMenu
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
251
|
+
uiCallbacks?.renderKebabMenu
|
|
252
|
+
? uiCallbacks.renderKebabMenu({
|
|
253
|
+
pinned: Boolean(activeThread?.pinned),
|
|
254
|
+
onPinToggle: () => {
|
|
255
|
+
if (activeId) adapter.threads.pin(activeId, !activeThread?.pinned);
|
|
256
|
+
},
|
|
257
|
+
onDelete: () => setShowDelete(true),
|
|
258
|
+
})
|
|
259
|
+
: (
|
|
260
|
+
<ChatKebabMenu
|
|
261
|
+
pinned={Boolean(activeThread?.pinned)}
|
|
262
|
+
onPinToggle={() => {
|
|
263
|
+
if (activeId) adapter.threads.pin(activeId, !activeThread?.pinned);
|
|
264
|
+
}}
|
|
265
|
+
onDelete={() => setShowDelete(true)}
|
|
266
|
+
/>
|
|
267
|
+
)
|
|
265
268
|
}
|
|
266
269
|
/>
|
|
267
270
|
</div>
|
package/src/chat/SinglePopup.tsx
CHANGED
|
@@ -5,32 +5,35 @@ import { motion } from "framer-motion";
|
|
|
5
5
|
import React from "react";
|
|
6
6
|
|
|
7
7
|
import { useChatUI } from "../contexts/ChatUIContext";
|
|
8
|
+
import { useGallery } from "../contexts/GalleryContext";
|
|
8
9
|
import { ChatXIcon } from "../icons";
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
10
|
+
import ChatKebabMenu from "../ui/ChatKebabMenu";
|
|
11
|
+
import ChatConfirmModal from "../modals/ChatConfirmModal";
|
|
12
|
+
import ChatFooter from "../ui/ChatFooter";
|
|
13
|
+
import ChatHeader from "../ui/ChatHeader";
|
|
14
|
+
import ChatIdentity from "../ui/ChatIdentity";
|
|
15
|
+
import ChatMessageItem from "../ui/ChatMessageItem";
|
|
16
|
+
import ChatScroll from "../ui/ChatScroll";
|
|
17
|
+
import TypingIndicator from "../ui/TypingIndicator";
|
|
18
|
+
import ChatImagePreviewModal from "./ChatImagePreviewModal";
|
|
19
|
+
import { GRADIENT_BORDER, getThemeAttr, getThemeVars } from "../utils/theme";
|
|
15
20
|
|
|
16
21
|
import type { ChatAdapter, ChatUICallbacks } from "../adapter/types";
|
|
17
22
|
import type { Message, MessageRef, Reference, Thread } from "../types";
|
|
18
23
|
import type { ChatTheme } from "./InboxPopup";
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
const GRADIENT_BORDER =
|
|
22
|
-
"linear-gradient(236.83deg, rgba(51,201,212,0.3) 0.4%, rgba(39,83,251,0.3) 30.28%, rgba(39,83,251,0.3) 50.2%, rgba(39,83,251,0.3) 65.14%, rgba(235,67,255,0.3) 100%)";
|
|
25
|
+
|
|
23
26
|
|
|
24
27
|
function coalesceThreadId(reference: Reference | undefined, threads: Thread[]): string {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
28
|
+
if (!reference?.id) return threads[0]?.id ?? "";
|
|
29
|
+
const refId = reference.id;
|
|
30
|
+
// Priority: exact thread.id match → orderId match → inquiryId match → first thread
|
|
29
31
|
return (
|
|
30
|
-
(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
threads.find((t) => t.id === refId)?.id ??
|
|
33
|
+
threads.find((t) => t.orderId === refId)?.id ??
|
|
34
|
+
threads.find((t) => t.inquiryId === refId)?.id ??
|
|
35
|
+
threads[0]?.id ??
|
|
36
|
+
""
|
|
34
37
|
);
|
|
35
38
|
}
|
|
36
39
|
|
|
@@ -46,20 +49,7 @@ function toRef(m: Message): MessageRef {
|
|
|
46
49
|
};
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
function getThemeAttr(theme?: ChatTheme): string {
|
|
50
|
-
if (!theme || theme === "marketplace") return "marketplace";
|
|
51
|
-
if (theme === "admin") return "admin";
|
|
52
|
-
return "custom";
|
|
53
|
-
}
|
|
54
52
|
|
|
55
|
-
function getThemeVars(theme?: ChatTheme): React.CSSProperties {
|
|
56
|
-
if (!theme || theme === "marketplace" || theme === "admin") return {};
|
|
57
|
-
const vars: Record<string, string> = {};
|
|
58
|
-
if (theme.primary) vars["--color-banbox-primary"] = theme.primary;
|
|
59
|
-
if (theme.primaryActive) vars["--color-banbox-primary-active"] = theme.primaryActive;
|
|
60
|
-
if (theme.surfaceLow) vars["--color-banbox-surface-container-low"] = theme.surfaceLow;
|
|
61
|
-
return vars as React.CSSProperties;
|
|
62
|
-
}
|
|
63
53
|
|
|
64
54
|
export type SinglePopupProps = {
|
|
65
55
|
adapter: ChatAdapter;
|
|
@@ -72,10 +62,21 @@ export type SinglePopupProps = {
|
|
|
72
62
|
══════════════════════════════════════════════════ */
|
|
73
63
|
const SinglePopup: React.FC<SinglePopupProps> = ({ adapter, uiCallbacks, theme }) => {
|
|
74
64
|
const { close, reference } = useChatUI();
|
|
65
|
+
const { isOpen: isGalleryOpen, closeGallery } = useGallery();
|
|
66
|
+
|
|
67
|
+
// ── Threads — subscribed so real-API updates (new msg, pin, delete) are reflected
|
|
68
|
+
const [threads, setThreads] = React.useState<Thread[]>(() => adapter.threads.list(reference));
|
|
69
|
+
React.useEffect(() => {
|
|
70
|
+
// Refresh once on mount (covers any gap between render and subscribe)
|
|
71
|
+
setThreads(adapter.threads.list(reference));
|
|
72
|
+
const unsub = adapter.threads.subscribe(() => {
|
|
73
|
+
setThreads(adapter.threads.list(reference));
|
|
74
|
+
});
|
|
75
|
+
return unsub;
|
|
76
|
+
}, [adapter, reference]);
|
|
75
77
|
|
|
76
|
-
const threads = adapter.threads.list(reference);
|
|
77
78
|
const initialThreadId = React.useMemo(
|
|
78
|
-
() => coalesceThreadId(reference, threads),
|
|
79
|
+
() => coalesceThreadId(reference, adapter.threads.list(reference)),
|
|
79
80
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
80
81
|
[reference],
|
|
81
82
|
);
|
|
@@ -101,6 +102,7 @@ const SinglePopup: React.FC<SinglePopupProps> = ({ adapter, uiCallbacks, theme }
|
|
|
101
102
|
);
|
|
102
103
|
const [scrollKey, setScrollKey] = React.useState<number>(Date.now());
|
|
103
104
|
const [replyTo, setReplyTo] = React.useState<MessageRef | undefined>(undefined);
|
|
105
|
+
const [showDelete, setShowDelete] = React.useState(false);
|
|
104
106
|
|
|
105
107
|
React.useEffect(() => {
|
|
106
108
|
if (!activeId || !adapter.messages.subscribe) return;
|
|
@@ -117,7 +119,17 @@ const SinglePopup: React.FC<SinglePopupProps> = ({ adapter, uiCallbacks, theme }
|
|
|
117
119
|
setReplyTo(undefined);
|
|
118
120
|
}, [activeId, adapter]);
|
|
119
121
|
|
|
120
|
-
|
|
122
|
+
const handleConfirmDelete = React.useCallback(() => {
|
|
123
|
+
if (!activeId) { setShowDelete(false); return; }
|
|
124
|
+
adapter.threads.delete(activeId);
|
|
125
|
+
uiCallbacks?.showToast?.({
|
|
126
|
+
type: "success",
|
|
127
|
+
title: "Chat Deleted",
|
|
128
|
+
message: "The chat has been deleted successfully.",
|
|
129
|
+
});
|
|
130
|
+
setShowDelete(false);
|
|
131
|
+
close();
|
|
132
|
+
}, [activeId, adapter, uiCallbacks, close]);
|
|
121
133
|
|
|
122
134
|
return (
|
|
123
135
|
<div className="fixed bottom-4 right-4 z-[10002]">
|
|
@@ -169,13 +181,33 @@ const SinglePopup: React.FC<SinglePopupProps> = ({ adapter, uiCallbacks, theme }
|
|
|
169
181
|
/>
|
|
170
182
|
}
|
|
171
183
|
right={
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
184
|
+
<div className="flex items-center gap-1">
|
|
185
|
+
{uiCallbacks?.renderKebabMenu
|
|
186
|
+
? uiCallbacks.renderKebabMenu({
|
|
187
|
+
pinned: Boolean(activeThread?.pinned),
|
|
188
|
+
onPinToggle: () => {
|
|
189
|
+
if (activeId) adapter.threads.pin(activeId, !activeThread?.pinned);
|
|
190
|
+
},
|
|
191
|
+
onDelete: () => setShowDelete(true),
|
|
192
|
+
})
|
|
193
|
+
: (
|
|
194
|
+
<ChatKebabMenu
|
|
195
|
+
pinned={Boolean(activeThread?.pinned)}
|
|
196
|
+
onPinToggle={() => {
|
|
197
|
+
if (activeId) adapter.threads.pin(activeId, !activeThread?.pinned);
|
|
198
|
+
}}
|
|
199
|
+
onDelete={() => setShowDelete(true)}
|
|
200
|
+
/>
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
<button
|
|
204
|
+
type="button"
|
|
205
|
+
onClick={close}
|
|
206
|
+
className="flex h-[34px] w-[34px] items-center justify-center rounded-full bg-white text-black shadow-[0px_2px_4px_0px_#A5A3AE4D] hover:bg-black/5 hover:text-[var(--color-banbox-warning)] cursor-pointer border-none"
|
|
207
|
+
>
|
|
208
|
+
<ChatXIcon className="h-6 w-6" />
|
|
209
|
+
</button>
|
|
210
|
+
</div>
|
|
179
211
|
}
|
|
180
212
|
/>
|
|
181
213
|
</div>
|
|
@@ -233,6 +265,15 @@ const SinglePopup: React.FC<SinglePopupProps> = ({ adapter, uiCallbacks, theme }
|
|
|
233
265
|
</div>
|
|
234
266
|
</div>
|
|
235
267
|
</motion.div>
|
|
268
|
+
|
|
269
|
+
{/* Delete confirm modal */}
|
|
270
|
+
<ChatConfirmModal
|
|
271
|
+
open={showDelete}
|
|
272
|
+
onClose={() => setShowDelete(false)}
|
|
273
|
+
onConfirm={handleConfirmDelete}
|
|
274
|
+
/>
|
|
275
|
+
{/* Image gallery preview */}
|
|
276
|
+
<ChatImagePreviewModal isOpen={isGalleryOpen} onClose={closeGallery} />
|
|
236
277
|
</div>
|
|
237
278
|
);
|
|
238
279
|
};
|
package/src/icons/index.tsx
CHANGED
|
@@ -212,6 +212,20 @@ export const MapPinIcon = ({ className = "" }: IconProps) => (
|
|
|
212
212
|
</svg>
|
|
213
213
|
);
|
|
214
214
|
|
|
215
|
+
export const MapIcon2 = ({ className = "" }: IconProps) => (
|
|
216
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
|
217
|
+
<path d="M7.9987 1.33203C5.41203 1.33203 3.33203 3.41203 3.33203 5.9987C3.33203 9.4987 7.9987 14.6654 7.9987 14.6654C7.9987 14.6654 12.6654 9.4987 12.6654 5.9987C12.6654 3.41203 10.5854 1.33203 7.9987 1.33203Z" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
|
|
218
|
+
<circle cx="8" cy="6" r="1.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
|
|
219
|
+
</svg>
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
export const FlyIcon = ({ className = "" }: IconProps) => (
|
|
223
|
+
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
|
224
|
+
<path d="M16.5 1.5L8.25 9.75" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
225
|
+
<path d="M16.5 1.5L11.25 16.5L8.25 9.75L1.5 6.75L16.5 1.5Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
226
|
+
</svg>
|
|
227
|
+
);
|
|
228
|
+
|
|
215
229
|
export const MenuIcon = ({ className }: IconProps) => (
|
|
216
230
|
<svg width="24" height="24" className={className} viewBox="0 0 24 24" fill="currentColor">
|
|
217
231
|
<circle cx="12" cy="5" r="2" />
|
|
@@ -246,3 +260,44 @@ export const ChatTrashIcon = ({ className }: IconProps) => (
|
|
|
246
260
|
<path d="M7.5 5.83333V3.33333C7.5 2.8731 7.8731 2.5 8.33333 2.5H11.6667C12.1269 2.5 12.5 2.8731 12.5 3.33333V5.83333" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" />
|
|
247
261
|
</svg>
|
|
248
262
|
);
|
|
263
|
+
|
|
264
|
+
export const EditIcon = ({ className = "" }: IconProps) => (
|
|
265
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
|
266
|
+
<path d="M9 7H6C4.89543 7 4 7.89543 4 9V18C4 19.1046 4.89543 20 6 20H15C16.1046 20 17 19.1046 17 18V15" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" />
|
|
267
|
+
<path d="M9 15H12L20.5 6.49998C21.3284 5.67156 21.3284 4.32841 20.5 3.49998C19.6716 2.67156 18.3284 2.67156 17.5 3.49998L9 12V15" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" />
|
|
268
|
+
<path d="M16 5L19 8" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" />
|
|
269
|
+
</svg>
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
export const TrashIcon = ({ className }: IconProps) => (
|
|
273
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
|
274
|
+
<path d="M3.3335 5.83464H16.6668" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
275
|
+
<path d="M8.33317 9.16797V14.168" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
276
|
+
<path d="M11.6667 9.16797V14.168" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
277
|
+
<path d="M4.1665 5.83203L4.99984 15.832C4.99984 16.7525 5.74603 17.4987 6.6665 17.4987H13.3332C14.2536 17.4987 14.9998 16.7525 14.9998 15.832L15.8332 5.83203" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
278
|
+
<path d="M7.5 5.83333V3.33333C7.5 2.8731 7.8731 2.5 8.33333 2.5H11.6667C12.1269 2.5 12.5 2.8731 12.5 3.33333V5.83333" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
279
|
+
</svg>
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
export const EmailIcon = ({ className = "" }: IconProps) => (
|
|
283
|
+
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
|
284
|
+
<path d="M3 3H15C15.825 3 16.5 3.675 16.5 4.5V13.5C16.5 14.325 15.825 15 15 15H3C2.175 15 1.5 14.325 1.5 13.5V4.5C1.5 3.675 2.175 3 3 3Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
285
|
+
<path d="M16.5 4.5L9 9.75L1.5 4.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
286
|
+
</svg>
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
export const BadgeHomeAddrIcon = ({ className = "" }: IconProps) => (
|
|
290
|
+
<svg width="12" height="12" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
|
291
|
+
<path d="M2.91667 7H1.75L7 1.75L12.25 7H11.0833" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
|
|
292
|
+
<path d="M2.91406 7V11.0833C2.91406 11.7277 3.4364 12.25 4.08073 12.25H9.91406C10.5584 12.25 11.0807 11.7277 11.0807 11.0833V7" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
|
|
293
|
+
<rect x="5.83594" y="7" width="2.33333" height="2.33333" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
|
|
294
|
+
</svg>
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
export const CheckboxFilledIcon = ({ className = "" }: IconProps) => (
|
|
298
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
|
299
|
+
<rect width="16" height="16" rx="4" fill="currentColor" />
|
|
300
|
+
<path d="M14.8161 1C13.1423 2.42824 11.7356 4.37456 10.6806 6.51692C9.68193 8.56126 8.99268 10.8016 8.69729 13H4.81498V12.972L3.12701 8.56126L2.4659 6.83897L2.18457 6.09685L3.83033 6.05484C4.26639 6.05484 4.66025 6.30688 4.75871 6.68495L5.72929 8.63127L6.517 10.1995L6.728 10.6196C6.91086 10.2415 7.09372 9.87748 7.29065 9.51342C8.34563 7.49708 9.49907 5.67678 10.8635 4.13652C11.6512 3.25438 12.5093 2.45624 13.4658 1.77013C13.8456 1.50408 14.2254 1.25204 14.6333 1.014H14.8161V1Z" fill="white" />
|
|
301
|
+
</svg>
|
|
302
|
+
);
|
|
303
|
+
|
package/src/index.ts
CHANGED
|
@@ -39,18 +39,20 @@ export { ChatUIContext } from "./contexts/ChatUIContext";
|
|
|
39
39
|
export type { ChatUIState, ChatVariant } from "./contexts/ChatUIContext";
|
|
40
40
|
|
|
41
41
|
// ── Individual UI components (advanced usage / custom layouts) ────────────────
|
|
42
|
-
export { default as ChatFooter } from "./ui/
|
|
43
|
-
export { default as ChatHeader } from "./ui/
|
|
44
|
-
export { default as ChatIdentity } from "./ui/
|
|
45
|
-
export { default as ChatMessageItem } from "./ui/
|
|
46
|
-
export { default as ChatScroll } from "./ui/
|
|
47
|
-
export { default as ChatThreadItem } from "./ui/
|
|
48
|
-
export type { ChatThreadStatus } from "./ui/
|
|
49
|
-
export { default as ChatListHeader } from "./ui/
|
|
50
|
-
export { default as ChatInquiryBar } from "./ui/
|
|
51
|
-
export { default as TypingIndicator } from "./ui/
|
|
52
|
-
export { default as ReplyCard } from "./ui/
|
|
53
|
-
export { default as ChatSpinner } from "./ui/
|
|
42
|
+
export { default as ChatFooter } from "./ui/ChatFooter";
|
|
43
|
+
export { default as ChatHeader } from "./ui/ChatHeader";
|
|
44
|
+
export { default as ChatIdentity } from "./ui/ChatIdentity";
|
|
45
|
+
export { default as ChatMessageItem } from "./ui/ChatMessageItem";
|
|
46
|
+
export { default as ChatScroll } from "./ui/ChatScroll";
|
|
47
|
+
export { default as ChatThreadItem } from "./ui/ChatThreadItem";
|
|
48
|
+
export type { ChatThreadStatus } from "./ui/ChatThreadItem";
|
|
49
|
+
export { default as ChatListHeader } from "./ui/ChatListHeader";
|
|
50
|
+
export { default as ChatInquiryBar } from "./ui/ChatInquiryBar";
|
|
51
|
+
export { default as TypingIndicator } from "./ui/TypingIndicator";
|
|
52
|
+
export { default as ReplyCard } from "./ui/ReplyCard";
|
|
53
|
+
export { default as ChatSpinner } from "./ui/ChatSpinner";
|
|
54
|
+
export { default as ChatKebabMenu } from "./ui/ChatKebabMenu";
|
|
55
|
+
export type { ChatKebabMenuProps } from "./ui/ChatKebabMenu";
|
|
54
56
|
|
|
55
57
|
// ── Utilities ─────────────────────────────────────────────────────────────────
|
|
56
58
|
export { cn } from "./utils/cn";
|