@banbox/chat 1.0.8 → 1.0.9

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 (42) hide show
  1. package/dist/index.cjs +1166 -202
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +11 -1
  4. package/dist/index.d.ts +11 -1
  5. package/dist/index.js +1090 -127
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/chat/InboxPopup.tsx +30 -19
  9. package/src/chat/SinglePopup.tsx +59 -14
  10. package/src/icons/index.tsx +55 -0
  11. package/src/index.ts +14 -12
  12. package/src/modals/ChatAddressModal.tsx +844 -0
  13. package/src/modals/{chat/ChatConfirmModal.tsx → ChatConfirmModal.tsx} +2 -2
  14. package/src/modals/ChatTranslateSettingsModal.tsx +182 -0
  15. package/src/styles/index.build.css +15 -0
  16. package/src/styles/index.css +10 -2
  17. package/src/ui/{chat/AttachmentPreviewStrip.tsx → AttachmentPreviewStrip.tsx} +2 -2
  18. package/src/ui/{chat/ChatComposerBar.tsx → ChatComposerBar.tsx} +2 -2
  19. package/src/ui/{chat/ChatFooter.tsx → ChatFooter.tsx} +102 -8
  20. package/src/ui/{chat/ChatIdentity.tsx → ChatIdentity.tsx} +2 -2
  21. package/src/ui/{chat/ChatInquiryBar.tsx → ChatInquiryBar.tsx} +1 -1
  22. package/src/ui/ChatKebabMenu.tsx +125 -0
  23. package/src/ui/{chat/ChatListHeader.tsx → ChatListHeader.tsx} +1 -1
  24. package/src/ui/{chat/ChatMessageItem.tsx → ChatMessageItem.tsx} +1 -1
  25. package/src/ui/{chat/ChatScroll.tsx → ChatScroll.tsx} +1 -1
  26. package/src/ui/{chat/ChatSpinner.tsx → ChatSpinner.tsx} +1 -1
  27. package/src/ui/{chat/ChatThreadItem.tsx → ChatThreadItem.tsx} +1 -1
  28. package/src/ui/{chat/MessageHoverActions.tsx → MessageHoverActions.tsx} +2 -2
  29. package/src/ui/{chat/ReplyCard.tsx → ReplyCard.tsx} +2 -2
  30. package/src/ui/{chat/TypingIndicator.tsx → TypingIndicator.tsx} +1 -1
  31. package/src/ui/{chat/drop-up → drop-up}/BusinessCardDropup.tsx +15 -3
  32. package/src/ui/{chat/drop-up → drop-up}/EmojiDropup.tsx +1 -1
  33. package/src/ui/{chat/message-items → message-items}/ChatAddressCard.tsx +4 -4
  34. package/src/ui/{chat/message-items → message-items}/ChatBubbleFiles.tsx +1 -1
  35. package/src/ui/{chat/message-items → message-items}/ChatBubbleImages.tsx +2 -2
  36. package/src/ui/{chat/message-items → message-items}/ChatBusinessCard.tsx +1 -1
  37. package/src/ui/{chat/scrollToMessage.ts → scrollToMessage.ts} +1 -1
  38. package/src/ui/{chat/types.ts → types.ts} +2 -2
  39. package/src/modals/chat/ChatTranslateSettingsModal.tsx +0 -180
  40. /package/src/ui/{chat/ChatHeader.tsx → ChatHeader.tsx} +0 -0
  41. /package/src/ui/{chat/message-items → message-items}/ChatBubbleAudio.tsx +0 -0
  42. /package/src/ui/{chat/message-items → message-items}/ChatBubbleText.tsx +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@banbox/chat",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Banbox Chat UI components — reusable across all Banbox React/Next.js projects",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -6,19 +6,20 @@ 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/chat/ChatConfirmModal";
10
- import ChatFooter from "../ui/chat/ChatFooter";
11
- import ChatHeader from "../ui/chat/ChatHeader";
12
- import ChatIdentity from "../ui/chat/ChatIdentity";
13
- import ChatInquiryBar from "../ui/chat/ChatInquiryBar";
14
- import ChatListHeader from "../ui/chat/ChatListHeader";
15
- import ChatMessageItem from "../ui/chat/ChatMessageItem";
16
- import ChatScroll from "../ui/chat/ChatScroll";
17
- import type { ChatThreadStatus } from "../ui/chat/ChatThreadItem";
18
- import ChatThreadItem from "../ui/chat/ChatThreadItem";
19
- import TypingIndicator from "../ui/chat/TypingIndicator";
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
21
 
22
+ import ChatKebabMenu from "../ui/ChatKebabMenu";
22
23
  import type { ChatAdapter, ChatUICallbacks } from "../adapter/types";
23
24
  import type { Message, MessageRef, Thread } from "../types";
24
25
 
@@ -183,7 +184,7 @@ const InboxPopup: React.FC<InboxPopupProps> = ({ adapter, uiCallbacks, theme })
183
184
  RENDER
184
185
  ══════════════════════════════════════════════════ */
185
186
  return (
186
- <div className="fixed bottom-4 right-4 z-[10002]">
187
+ <div className="fixed bottom-4 right-4 z-10002">
187
188
  {/* Backdrop */}
188
189
  <motion.button
189
190
  aria-label="Close chat"
@@ -255,13 +256,23 @@ const InboxPopup: React.FC<InboxPopupProps> = ({ adapter, uiCallbacks, theme })
255
256
  )
256
257
  }
257
258
  right={
258
- uiCallbacks?.renderKebabMenu?.({
259
- pinned: Boolean(activeThread?.pinned),
260
- onPinToggle: () => {
261
- if (activeId) adapter.threads.pin(activeId, !activeThread?.pinned);
262
- },
263
- onDelete: () => setShowDelete(true),
264
- }) ?? null
259
+ uiCallbacks?.renderKebabMenu
260
+ ? uiCallbacks.renderKebabMenu({
261
+ pinned: Boolean(activeThread?.pinned),
262
+ onPinToggle: () => {
263
+ if (activeId) adapter.threads.pin(activeId, !activeThread?.pinned);
264
+ },
265
+ onDelete: () => setShowDelete(true),
266
+ })
267
+ : (
268
+ <ChatKebabMenu
269
+ pinned={Boolean(activeThread?.pinned)}
270
+ onPinToggle={() => {
271
+ if (activeId) adapter.threads.pin(activeId, !activeThread?.pinned);
272
+ }}
273
+ onDelete={() => setShowDelete(true)}
274
+ />
275
+ )
265
276
  }
266
277
  />
267
278
  </div>
@@ -5,13 +5,17 @@ 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 ChatFooter from "../ui/chat/ChatFooter";
10
- import ChatHeader from "../ui/chat/ChatHeader";
11
- import ChatIdentity from "../ui/chat/ChatIdentity";
12
- import ChatMessageItem from "../ui/chat/ChatMessageItem";
13
- import ChatScroll from "../ui/chat/ChatScroll";
14
- import TypingIndicator from "../ui/chat/TypingIndicator";
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";
15
19
 
16
20
  import type { ChatAdapter, ChatUICallbacks } from "../adapter/types";
17
21
  import type { Message, MessageRef, Reference, Thread } from "../types";
@@ -72,6 +76,7 @@ export type SinglePopupProps = {
72
76
  ══════════════════════════════════════════════════ */
73
77
  const SinglePopup: React.FC<SinglePopupProps> = ({ adapter, uiCallbacks, theme }) => {
74
78
  const { close, reference } = useChatUI();
79
+ const { isOpen: isGalleryOpen, closeGallery } = useGallery();
75
80
 
76
81
  const threads = adapter.threads.list(reference);
77
82
  const initialThreadId = React.useMemo(
@@ -101,6 +106,7 @@ const SinglePopup: React.FC<SinglePopupProps> = ({ adapter, uiCallbacks, theme }
101
106
  );
102
107
  const [scrollKey, setScrollKey] = React.useState<number>(Date.now());
103
108
  const [replyTo, setReplyTo] = React.useState<MessageRef | undefined>(undefined);
109
+ const [showDelete, setShowDelete] = React.useState(false);
104
110
 
105
111
  React.useEffect(() => {
106
112
  if (!activeId || !adapter.messages.subscribe) return;
@@ -117,7 +123,17 @@ const SinglePopup: React.FC<SinglePopupProps> = ({ adapter, uiCallbacks, theme }
117
123
  setReplyTo(undefined);
118
124
  }, [activeId, adapter]);
119
125
 
120
- void uiCallbacks;
126
+ const handleConfirmDelete = React.useCallback(() => {
127
+ if (!activeId) { setShowDelete(false); return; }
128
+ adapter.threads.delete(activeId);
129
+ uiCallbacks?.showToast?.({
130
+ type: "success",
131
+ title: "Chat Deleted",
132
+ message: "The chat has been deleted successfully.",
133
+ });
134
+ setShowDelete(false);
135
+ close();
136
+ }, [activeId, adapter, uiCallbacks, close]);
121
137
 
122
138
  return (
123
139
  <div className="fixed bottom-4 right-4 z-[10002]">
@@ -169,13 +185,33 @@ const SinglePopup: React.FC<SinglePopupProps> = ({ adapter, uiCallbacks, theme }
169
185
  />
170
186
  }
171
187
  right={
172
- <button
173
- type="button"
174
- onClick={close}
175
- 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"
176
- >
177
- <ChatXIcon className="h-6 w-6" />
178
- </button>
188
+ <div className="flex items-center gap-1">
189
+ {uiCallbacks?.renderKebabMenu
190
+ ? uiCallbacks.renderKebabMenu({
191
+ pinned: Boolean(activeThread?.pinned),
192
+ onPinToggle: () => {
193
+ if (activeId) adapter.threads.pin(activeId, !activeThread?.pinned);
194
+ },
195
+ onDelete: () => setShowDelete(true),
196
+ })
197
+ : (
198
+ <ChatKebabMenu
199
+ pinned={Boolean(activeThread?.pinned)}
200
+ onPinToggle={() => {
201
+ if (activeId) adapter.threads.pin(activeId, !activeThread?.pinned);
202
+ }}
203
+ onDelete={() => setShowDelete(true)}
204
+ />
205
+ )
206
+ }
207
+ <button
208
+ type="button"
209
+ onClick={close}
210
+ 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"
211
+ >
212
+ <ChatXIcon className="h-6 w-6" />
213
+ </button>
214
+ </div>
179
215
  }
180
216
  />
181
217
  </div>
@@ -233,6 +269,15 @@ const SinglePopup: React.FC<SinglePopupProps> = ({ adapter, uiCallbacks, theme }
233
269
  </div>
234
270
  </div>
235
271
  </motion.div>
272
+
273
+ {/* Delete confirm modal */}
274
+ <ChatConfirmModal
275
+ open={showDelete}
276
+ onClose={() => setShowDelete(false)}
277
+ onConfirm={handleConfirmDelete}
278
+ />
279
+ {/* Image gallery preview */}
280
+ <ChatImagePreviewModal isOpen={isGalleryOpen} onClose={closeGallery} />
236
281
  </div>
237
282
  );
238
283
  };
@@ -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/chat/ChatFooter";
43
- export { default as ChatHeader } from "./ui/chat/ChatHeader";
44
- export { default as ChatIdentity } from "./ui/chat/ChatIdentity";
45
- export { default as ChatMessageItem } from "./ui/chat/ChatMessageItem";
46
- export { default as ChatScroll } from "./ui/chat/ChatScroll";
47
- export { default as ChatThreadItem } from "./ui/chat/ChatThreadItem";
48
- export type { ChatThreadStatus } from "./ui/chat/ChatThreadItem";
49
- export { default as ChatListHeader } from "./ui/chat/ChatListHeader";
50
- export { default as ChatInquiryBar } from "./ui/chat/ChatInquiryBar";
51
- export { default as TypingIndicator } from "./ui/chat/TypingIndicator";
52
- export { default as ReplyCard } from "./ui/chat/ReplyCard";
53
- export { default as ChatSpinner } from "./ui/chat/ChatSpinner";
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";