@banbox/chat 1.0.0
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/README.md +215 -0
- package/dist/index.cjs +3408 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +556 -0
- package/dist/index.d.ts +556 -0
- package/dist/index.js +3385 -0
- package/dist/index.js.map +1 -0
- package/package.json +83 -0
- package/src/adapter/types.ts +146 -0
- package/src/chat/ChatImagePreviewModal.tsx +194 -0
- package/src/chat/ChatRoot.tsx +67 -0
- package/src/chat/InboxPopup.tsx +312 -0
- package/src/chat/SinglePopup.tsx +240 -0
- package/src/contexts/ChatUIContext.tsx +30 -0
- package/src/contexts/ChatUIProvider.tsx +38 -0
- package/src/contexts/GalleryContext.tsx +40 -0
- package/src/contexts/GalleryProvider.tsx +89 -0
- package/src/hooks/useDisableBodyScroll.ts +16 -0
- package/src/icons/index.tsx +248 -0
- package/src/index.ts +56 -0
- package/src/lottie/typingdotanimation2.json +1 -0
- package/src/modals/chat/ChatConfirmModal.tsx +104 -0
- package/src/modals/chat/ChatTranslateSettingsModal.tsx +180 -0
- package/src/types/index.ts +163 -0
- package/src/ui/Button.tsx +83 -0
- package/src/ui/Portal.tsx +40 -0
- package/src/ui/Select.tsx +74 -0
- package/src/ui/chat/AttachmentPreviewStrip.tsx +166 -0
- package/src/ui/chat/ChatComposerBar.tsx +231 -0
- package/src/ui/chat/ChatFooter.tsx +442 -0
- package/src/ui/chat/ChatHeader.tsx +24 -0
- package/src/ui/chat/ChatIdentity.tsx +145 -0
- package/src/ui/chat/ChatInquiryBar.tsx +57 -0
- package/src/ui/chat/ChatListHeader.tsx +179 -0
- package/src/ui/chat/ChatMessageItem.tsx +214 -0
- package/src/ui/chat/ChatScroll.tsx +64 -0
- package/src/ui/chat/ChatSpinner.tsx +49 -0
- package/src/ui/chat/ChatThreadItem.tsx +140 -0
- package/src/ui/chat/MessageHoverActions.tsx +120 -0
- package/src/ui/chat/ReplyCard.tsx +217 -0
- package/src/ui/chat/TypingIndicator.tsx +93 -0
- package/src/ui/chat/drop-up/BusinessCardDropup.tsx +253 -0
- package/src/ui/chat/drop-up/EmojiDropup.tsx +132 -0
- package/src/ui/chat/message-items/ChatAddressCard.tsx +130 -0
- package/src/ui/chat/message-items/ChatBubbleAudio.tsx +209 -0
- package/src/ui/chat/message-items/ChatBubbleFiles.tsx +80 -0
- package/src/ui/chat/message-items/ChatBubbleImages.tsx +120 -0
- package/src/ui/chat/message-items/ChatBubbleText.tsx +16 -0
- package/src/ui/chat/message-items/ChatBusinessCard.tsx +95 -0
- package/src/ui/chat/scrollToMessage.ts +61 -0
- package/src/ui/chat/types.ts +37 -0
- package/src/utils/cn.ts +6 -0
package/README.md
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# @banbox/chat
|
|
2
|
+
|
|
3
|
+
Banbox Chat UI package — plug-and-play chat popup for any React or Next.js project.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# From GitHub private registry
|
|
9
|
+
npm install @banbox/chat
|
|
10
|
+
|
|
11
|
+
# Or local development link
|
|
12
|
+
npm install ../banbox-chat
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
| Peer dep | Version |
|
|
18
|
+
|----------|---------|
|
|
19
|
+
| react | ≥ 18 |
|
|
20
|
+
| react-dom | ≥ 18 |
|
|
21
|
+
| framer-motion | ≥ 10 |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Quick Start (Vite / React)
|
|
26
|
+
|
|
27
|
+
### 1. Wrap your app
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
// main.tsx
|
|
31
|
+
import { ChatUIProvider, ChatRoot } from "@banbox/chat";
|
|
32
|
+
import { createDemoChatAdapter } from "./components/chat/demoData";
|
|
33
|
+
import "@banbox/chat/dist/index.css"; // if CSS file is emitted
|
|
34
|
+
|
|
35
|
+
const adapter = createDemoChatAdapter();
|
|
36
|
+
|
|
37
|
+
createRoot(document.getElementById("root")!).render(
|
|
38
|
+
<ChatUIProvider>
|
|
39
|
+
<App />
|
|
40
|
+
<ChatRoot
|
|
41
|
+
adapter={adapter}
|
|
42
|
+
uiCallbacks={{
|
|
43
|
+
showToast: ({ title }) => toast(title),
|
|
44
|
+
onNavigate: ({ type, id }) => navigate(`/${type}s/${id}`),
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
</ChatUIProvider>
|
|
48
|
+
);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Open the chat from anywhere
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { useChatUI } from "@banbox/chat";
|
|
55
|
+
|
|
56
|
+
function OrderPage() {
|
|
57
|
+
const { openSingle } = useChatUI();
|
|
58
|
+
return (
|
|
59
|
+
<button onClick={() => openSingle({ reference: { kind: "order", id: "ORD-123" } })}>
|
|
60
|
+
Chat with Buyer
|
|
61
|
+
</button>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Quick Start (Next.js App Router)
|
|
69
|
+
|
|
70
|
+
### 1. Create a client wrapper component
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
// components/ChatWrapper.tsx
|
|
74
|
+
"use client";
|
|
75
|
+
import { ChatUIProvider, ChatRoot } from "@banbox/chat";
|
|
76
|
+
import { createDemoChatAdapter } from "@/lib/chat/demoAdapter";
|
|
77
|
+
|
|
78
|
+
const adapter = createDemoChatAdapter();
|
|
79
|
+
|
|
80
|
+
export function ChatWrapper({ children }: { children: React.ReactNode }) {
|
|
81
|
+
return (
|
|
82
|
+
<ChatUIProvider>
|
|
83
|
+
{children}
|
|
84
|
+
<ChatRoot adapter={adapter} />
|
|
85
|
+
</ChatUIProvider>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 2. Add to your root layout
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
// app/layout.tsx
|
|
94
|
+
import { ChatWrapper } from "@/components/ChatWrapper";
|
|
95
|
+
|
|
96
|
+
export default function RootLayout({ children }) {
|
|
97
|
+
return (
|
|
98
|
+
<html>
|
|
99
|
+
<body>
|
|
100
|
+
<ChatWrapper>{children}</ChatWrapper>
|
|
101
|
+
</body>
|
|
102
|
+
</html>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 3. Open from any Client Component
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
"use client";
|
|
111
|
+
import { useChatUI } from "@banbox/chat";
|
|
112
|
+
|
|
113
|
+
export function ChatButton() {
|
|
114
|
+
const { openInbox } = useChatUI();
|
|
115
|
+
return <button onClick={() => openInbox()}>Messages</button>;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Tailwind CSS Setup
|
|
122
|
+
|
|
123
|
+
The package uses Tailwind utility classes. Add the package source to your Tailwind content config so the classes are included in your build:
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
// tailwind.config.ts (or vite.config.ts with @tailwindcss/vite)
|
|
127
|
+
export default {
|
|
128
|
+
content: [
|
|
129
|
+
"./src/**/*.{ts,tsx}",
|
|
130
|
+
// ↓ Include @banbox/chat source for Tailwind scanning
|
|
131
|
+
"./node_modules/@banbox/chat/src/**/*.{ts,tsx}",
|
|
132
|
+
],
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Implementing the ChatAdapter
|
|
139
|
+
|
|
140
|
+
The package is data-agnostic. You implement `ChatAdapter` in your host app:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// lib/chat/apiAdapter.ts
|
|
144
|
+
import type { ChatAdapter } from "@banbox/chat";
|
|
145
|
+
|
|
146
|
+
export const createApiChatAdapter = ({ baseUrl, token }): ChatAdapter => ({
|
|
147
|
+
threads: {
|
|
148
|
+
list: () => cache.threads,
|
|
149
|
+
subscribe: (cb) => {
|
|
150
|
+
socket.on("threads:update", cb);
|
|
151
|
+
return () => socket.off("threads:update", cb);
|
|
152
|
+
},
|
|
153
|
+
pin: (id, pinned) => api.patch(`/threads/${id}`, { pinned }),
|
|
154
|
+
delete: (id) => api.delete(`/threads/${id}`),
|
|
155
|
+
markRead: (id) => api.post(`/threads/${id}/read`),
|
|
156
|
+
},
|
|
157
|
+
messages: {
|
|
158
|
+
list: (tid) => cache.messages[tid] ?? [],
|
|
159
|
+
subscribe: (tid, cb) => {
|
|
160
|
+
socket.on(`messages:${tid}`, cb);
|
|
161
|
+
return () => socket.off(`messages:${tid}`, cb);
|
|
162
|
+
},
|
|
163
|
+
send: (tid, payload) => api.post(`/threads/${tid}/messages`, payload),
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## API Reference
|
|
171
|
+
|
|
172
|
+
### Components
|
|
173
|
+
|
|
174
|
+
| Component | Description |
|
|
175
|
+
|-----------|-------------|
|
|
176
|
+
| `<ChatRoot adapter uiCallbacks? />` | Main entry point — mounts the chat popup |
|
|
177
|
+
| `<ChatUIProvider>` | Context provider — wrap your app with this |
|
|
178
|
+
|
|
179
|
+
### Hooks
|
|
180
|
+
|
|
181
|
+
| Hook | Description |
|
|
182
|
+
|------|-------------|
|
|
183
|
+
| `useChatUI()` | Open/close chat, select threads |
|
|
184
|
+
|
|
185
|
+
### `useChatUI()` methods
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
const {
|
|
189
|
+
openInbox, // open the inbox (thread list) view
|
|
190
|
+
openSingle, // open a single chat view
|
|
191
|
+
close, // close the popup
|
|
192
|
+
selectThread, // switch active thread
|
|
193
|
+
isOpen, // boolean
|
|
194
|
+
variant, // "inbox" | "single"
|
|
195
|
+
} = useChatUI();
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### `openSingle(opts)` Reference kinds
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
openSingle({ reference: { kind: "order", id: "ORD-123", title: "Order Details" } });
|
|
202
|
+
openSingle({ reference: { kind: "inquiry", id: "INQ-456", title: "Product Inquiry" } });
|
|
203
|
+
openSingle({ reference: { kind: "quotation", id: "QUOT-789", title: "Quotation Request" } });
|
|
204
|
+
openSingle({ reference: { kind: "productInquiry", id: "PI-101" } });
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Build
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
npm run build # compile to dist/
|
|
213
|
+
npm run build:watch # watch mode
|
|
214
|
+
npm run typecheck # tsc --noEmit
|
|
215
|
+
```
|