nextjs-chatbot-ui 1.0.1 → 1.1.1
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 +468 -330
- package/components/AdminSetup.tsx +155 -71
- package/package.json +68 -68
package/README.md
CHANGED
|
@@ -1,330 +1,468 @@
|
|
|
1
|
-
# Chatbot UI Component
|
|
2
|
-
|
|
3
|
-
A beautiful, configurable chatbot UI component for Next.js applications with Tailwind CSS. Inspired by Sendbird's modern chat interface.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- 🎨 Modern, Sendbird-inspired UI design
|
|
8
|
-
- ⚙️ Fully configurable (labels, position, colors, backend URL)
|
|
9
|
-
- 📱 Responsive and mobile-friendly
|
|
10
|
-
- 🎯 TypeScript support
|
|
11
|
-
- 🚀 Easy to integrate
|
|
12
|
-
- 💬 Real-time messaging support
|
|
13
|
-
- 🎭 Customizable user and bot avatars
|
|
14
|
-
- ⏰ Optional timestamp display
|
|
15
|
-
|
|
16
|
-
## Compatibility Requirements
|
|
17
|
-
|
|
18
|
-
This package requires:
|
|
19
|
-
- **Next.js
|
|
20
|
-
- **React 18+**
|
|
21
|
-
- **TypeScript
|
|
22
|
-
- **Tailwind CSS 3+** (must be configured in your project)
|
|
23
|
-
|
|
24
|
-
**Important Notes:**
|
|
25
|
-
- The package exports TypeScript source files directly, which Next.js will compile automatically
|
|
26
|
-
- Make sure your `tailwind.config.js` includes the package path in the `content` array
|
|
27
|
-
- This package uses the `'use client'` directive and requires client-side rendering
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
{
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
//
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
1
|
+
# Chatbot UI Component
|
|
2
|
+
|
|
3
|
+
A beautiful, configurable chatbot UI component for Next.js applications with Tailwind CSS. Inspired by Sendbird's modern chat interface.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎨 Modern, Sendbird-inspired UI design
|
|
8
|
+
- ⚙️ Fully configurable (labels, position, colors, backend URL)
|
|
9
|
+
- 📱 Responsive and mobile-friendly
|
|
10
|
+
- 🎯 TypeScript support
|
|
11
|
+
- 🚀 Easy to integrate
|
|
12
|
+
- 💬 Real-time messaging support
|
|
13
|
+
- 🎭 Customizable user and bot avatars
|
|
14
|
+
- ⏰ Optional timestamp display
|
|
15
|
+
|
|
16
|
+
## Compatibility Requirements
|
|
17
|
+
|
|
18
|
+
This package requires:
|
|
19
|
+
- **Next.js 13+** (with App Router or Pages Router support)
|
|
20
|
+
- **React 18+**
|
|
21
|
+
- **TypeScript** (optional, but recommended)
|
|
22
|
+
- **Tailwind CSS 3+** (must be configured in your project)
|
|
23
|
+
|
|
24
|
+
**Important Notes:**
|
|
25
|
+
- The package exports TypeScript source files directly, which Next.js will compile automatically
|
|
26
|
+
- Make sure your `tailwind.config.js` includes the package path in the `content` array
|
|
27
|
+
- This package uses the `'use client'` directive and requires client-side rendering
|
|
28
|
+
- Works with both **App Router** (`app/` directory) and **Pages Router** (`pages/` directory)
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install nextjs-chatbot-ui
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
### Basic Setup
|
|
39
|
+
|
|
40
|
+
**Step 1: Configure Next.js** - Add the package to your `next.config.js`:
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
// next.config.js
|
|
44
|
+
/** @type {import('next').NextConfig} */
|
|
45
|
+
const nextConfig = {
|
|
46
|
+
transpilePackages: ['nextjs-chatbot-ui'],
|
|
47
|
+
// ... your other config
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = nextConfig
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Step 2: Configure Tailwind CSS** - Make sure your `tailwind.config.js` includes the component:
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
// tailwind.config.js
|
|
57
|
+
module.exports = {
|
|
58
|
+
content: [
|
|
59
|
+
'./node_modules/nextjs-chatbot-ui/**/*.{js,ts,jsx,tsx}',
|
|
60
|
+
'./app/**/*.{js,ts,jsx,tsx,mdx}',
|
|
61
|
+
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
|
|
62
|
+
'./components/**/*.{js,ts,jsx,tsx,mdx}',
|
|
63
|
+
],
|
|
64
|
+
// ... rest of your config
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Step 3: Import and use the component**:
|
|
69
|
+
|
|
70
|
+
For **App Router** (app directory):
|
|
71
|
+
```javascript
|
|
72
|
+
// app/page.tsx or app/any-page.tsx
|
|
73
|
+
'use client'; // Required for App Router
|
|
74
|
+
|
|
75
|
+
import { Chatbot } from 'nextjs-chatbot-ui';
|
|
76
|
+
import type { ChatbotConfig } from 'nextjs-chatbot-ui';
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
For **Pages Router** (pages directory):
|
|
80
|
+
```javascript
|
|
81
|
+
// pages/index.js or pages/any-page.js
|
|
82
|
+
import { Chatbot } from 'nextjs-chatbot-ui';
|
|
83
|
+
import type { ChatbotConfig } from 'nextjs-chatbot-ui';
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Step 4: Configure and use the component**:
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
const config: ChatbotConfig = {
|
|
90
|
+
backendUrl: 'https://your-backend-api.com/chat',
|
|
91
|
+
labels: {
|
|
92
|
+
title: 'Support Chat',
|
|
93
|
+
placeholder: 'Type your message...',
|
|
94
|
+
sendButton: 'Send',
|
|
95
|
+
welcomeMessage: 'Hello! How can I help you?',
|
|
96
|
+
},
|
|
97
|
+
position: 'bottom-right',
|
|
98
|
+
botInfo: {
|
|
99
|
+
name: 'Support Bot',
|
|
100
|
+
avatar: 'https://example.com/bot-avatar.png',
|
|
101
|
+
},
|
|
102
|
+
userInfo: {
|
|
103
|
+
name: 'User',
|
|
104
|
+
avatar: 'https://example.com/user-avatar.png',
|
|
105
|
+
},
|
|
106
|
+
primaryColor: '#0ea5e9',
|
|
107
|
+
autoOpen: false,
|
|
108
|
+
showTimestamp: true,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default function Page() {
|
|
112
|
+
return (
|
|
113
|
+
<div>
|
|
114
|
+
<h1>My Website</h1>
|
|
115
|
+
<Chatbot config={config} />
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Complete Example (App Router)
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
// app/page.tsx
|
|
125
|
+
'use client';
|
|
126
|
+
|
|
127
|
+
import { Chatbot } from 'nextjs-chatbot-ui';
|
|
128
|
+
import type { ChatbotConfig } from 'nextjs-chatbot-ui';
|
|
129
|
+
|
|
130
|
+
export default function Home() {
|
|
131
|
+
const config: ChatbotConfig = {
|
|
132
|
+
backendUrl: 'https://api.example.com/chat',
|
|
133
|
+
labels: {
|
|
134
|
+
title: 'Support Chat',
|
|
135
|
+
placeholder: 'Type your message...',
|
|
136
|
+
sendButton: 'Send',
|
|
137
|
+
welcomeMessage: 'Hello! How can I help you today?',
|
|
138
|
+
},
|
|
139
|
+
position: 'bottom-right',
|
|
140
|
+
botInfo: {
|
|
141
|
+
name: 'Support Bot',
|
|
142
|
+
},
|
|
143
|
+
userInfo: {
|
|
144
|
+
name: 'User',
|
|
145
|
+
},
|
|
146
|
+
primaryColor: '#6B46C1',
|
|
147
|
+
autoOpen: false,
|
|
148
|
+
showTimestamp: true,
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<main>
|
|
153
|
+
<h1>Welcome to My Site</h1>
|
|
154
|
+
<Chatbot config={config} />
|
|
155
|
+
</main>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Complete Example (Pages Router)
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
// pages/index.js
|
|
164
|
+
import { Chatbot } from 'nextjs-chatbot-ui';
|
|
165
|
+
|
|
166
|
+
export default function Home() {
|
|
167
|
+
const config = {
|
|
168
|
+
backendUrl: 'https://api.example.com/chat',
|
|
169
|
+
labels: {
|
|
170
|
+
title: 'Support Chat',
|
|
171
|
+
placeholder: 'Type your message...',
|
|
172
|
+
},
|
|
173
|
+
position: 'bottom-right',
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<div>
|
|
178
|
+
<h1>Welcome to My Site</h1>
|
|
179
|
+
<Chatbot config={config} />
|
|
180
|
+
</div>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Configuration Options
|
|
186
|
+
|
|
187
|
+
#### `ChatbotConfig` Interface
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
interface ChatbotConfig {
|
|
191
|
+
// Required
|
|
192
|
+
backendUrl: string; // Your backend API endpoint for handling messages
|
|
193
|
+
|
|
194
|
+
// Optional Labels
|
|
195
|
+
labels?: {
|
|
196
|
+
title?: string; // Chat header title (default: "Chat Support")
|
|
197
|
+
placeholder?: string; // Input placeholder (default: "Type your message...")
|
|
198
|
+
sendButton?: string; // Send button text (default: "Send")
|
|
199
|
+
typingIndicator?: string; // Loading message (default: "Typing...")
|
|
200
|
+
welcomeMessage?: string; // Initial bot message (default: "Hello! How can I help you today?")
|
|
201
|
+
errorMessage?: string; // Error message (default: "Sorry, something went wrong. Please try again.")
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// Position
|
|
205
|
+
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'; // Default: 'bottom-right'
|
|
206
|
+
|
|
207
|
+
// User Information
|
|
208
|
+
userInfo?: {
|
|
209
|
+
name?: string; // User name
|
|
210
|
+
avatar?: string; // User avatar URL
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// Bot Information
|
|
214
|
+
botInfo?: {
|
|
215
|
+
name?: string; // Bot name (default: uses title)
|
|
216
|
+
avatar?: string; // Bot avatar URL
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// Styling
|
|
220
|
+
primaryColor?: string; // Primary color (hex code)
|
|
221
|
+
backgroundColor?: string; // Chat background color (hex code)
|
|
222
|
+
|
|
223
|
+
// Behavior
|
|
224
|
+
autoOpen?: boolean; // Auto-open chat on load (default: false)
|
|
225
|
+
showTimestamp?: boolean; // Show message timestamps (default: false)
|
|
226
|
+
showDateSeparator?: boolean; // Show date separators between messages (default: false)
|
|
227
|
+
poweredByText?: string; // Footer text (e.g., "Powered by sendbird")
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Backend API Requirements
|
|
232
|
+
|
|
233
|
+
Your backend should accept POST requests with the following format:
|
|
234
|
+
|
|
235
|
+
**Request:**
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"message": "User's message text",
|
|
239
|
+
"userInfo": {
|
|
240
|
+
"name": "User",
|
|
241
|
+
"avatar": "https://example.com/avatar.png"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Response:**
|
|
247
|
+
```json
|
|
248
|
+
{
|
|
249
|
+
"message": "Bot's response text",
|
|
250
|
+
"suggestedReplies": ["Option 1", "Option 2", "Option 3"]
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
or
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"response": "Bot's response text",
|
|
259
|
+
"suggestions": ["Option 1", "Option 2", "Option 3"]
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Note:** The `suggestedReplies` or `suggestions` field is optional and will display as clickable buttons below the bot's message, similar to Sendbird's interface.
|
|
264
|
+
|
|
265
|
+
### Example Implementation
|
|
266
|
+
|
|
267
|
+
```javascript
|
|
268
|
+
// pages/index.js or app/page.js
|
|
269
|
+
'use client';
|
|
270
|
+
|
|
271
|
+
import { Chatbot } from 'nextjs-chatbot-ui';
|
|
272
|
+
import type { ChatbotConfig } from 'nextjs-chatbot-ui';
|
|
273
|
+
|
|
274
|
+
export default function Home() {
|
|
275
|
+
const chatbotConfig: ChatbotConfig = {
|
|
276
|
+
backendUrl: 'https://api.example.com/chat',
|
|
277
|
+
labels: {
|
|
278
|
+
title: 'Customer Support',
|
|
279
|
+
placeholder: 'Ask us anything...',
|
|
280
|
+
sendButton: 'Send',
|
|
281
|
+
welcomeMessage: 'Welcome! We\'re here to help.',
|
|
282
|
+
},
|
|
283
|
+
position: 'bottom-right',
|
|
284
|
+
botInfo: {
|
|
285
|
+
name: 'Support Assistant',
|
|
286
|
+
avatar: '/bot-avatar.png',
|
|
287
|
+
},
|
|
288
|
+
userInfo: {
|
|
289
|
+
name: 'Guest User',
|
|
290
|
+
},
|
|
291
|
+
primaryColor: '#6B46C1', // Purple like Sendbird
|
|
292
|
+
autoOpen: false,
|
|
293
|
+
showTimestamp: true,
|
|
294
|
+
showDateSeparator: true,
|
|
295
|
+
poweredByText: 'Powered by nextjs-chatbot-ui',
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
return (
|
|
299
|
+
<div>
|
|
300
|
+
<h1>My Website</h1>
|
|
301
|
+
<Chatbot config={chatbotConfig} />
|
|
302
|
+
</div>
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Tailwind CSS Setup
|
|
308
|
+
|
|
309
|
+
Make sure you have Tailwind CSS configured in your Next.js project. The component uses Tailwind classes, so ensure your `tailwind.config.js` includes the component:
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
// tailwind.config.js
|
|
313
|
+
module.exports = {
|
|
314
|
+
content: [
|
|
315
|
+
'./node_modules/nextjs-chatbot-ui/**/*.{js,ts,jsx,tsx}',
|
|
316
|
+
// ... your other paths
|
|
317
|
+
],
|
|
318
|
+
// ... rest of your config
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Development
|
|
323
|
+
|
|
324
|
+
To develop or modify this package:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
# Install dependencies
|
|
328
|
+
npm install
|
|
329
|
+
|
|
330
|
+
# Run development server
|
|
331
|
+
npm run dev
|
|
332
|
+
|
|
333
|
+
# Build for production
|
|
334
|
+
npm run build
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Admin Setup Component
|
|
338
|
+
|
|
339
|
+
The package also includes an `AdminSetup` component for configuring database connections in your admin panel.
|
|
340
|
+
|
|
341
|
+
### Usage
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
import { AdminSetup } from 'nextjs-chatbot-ui';
|
|
345
|
+
import type { DatabaseConfig, DatabaseConnection } from 'nextjs-chatbot-ui';
|
|
346
|
+
|
|
347
|
+
function AdminPanel() {
|
|
348
|
+
const handleSave = (config: DatabaseConfig) => {
|
|
349
|
+
// Save configuration to your backend
|
|
350
|
+
console.log('Config:', config);
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
const handleTestConnection = async (connection: DatabaseConnection) => {
|
|
354
|
+
// Test database connection
|
|
355
|
+
const response = await fetch('/api/database/test', {
|
|
356
|
+
method: 'POST',
|
|
357
|
+
body: JSON.stringify(connection),
|
|
358
|
+
});
|
|
359
|
+
return response.ok;
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
const handleFetchColumns = async (connection: DatabaseConnection) => {
|
|
363
|
+
// Fetch columns from database
|
|
364
|
+
const response = await fetch('/api/database/columns', {
|
|
365
|
+
method: 'POST',
|
|
366
|
+
body: JSON.stringify(connection),
|
|
367
|
+
});
|
|
368
|
+
const data = await response.json();
|
|
369
|
+
return data.columns || [];
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
return (
|
|
373
|
+
<aside className="sidebar">
|
|
374
|
+
<AdminSetup
|
|
375
|
+
onSave={handleSave}
|
|
376
|
+
onTestConnection={handleTestConnection}
|
|
377
|
+
onFetchColumns={handleFetchColumns}
|
|
378
|
+
/>
|
|
379
|
+
</aside>
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Features
|
|
385
|
+
|
|
386
|
+
- **Database Selection**: Choose between MongoDB and PostgreSQL
|
|
387
|
+
- **Connection Configuration**: Configure all necessary connection parameters
|
|
388
|
+
- **Connection Testing**: Test database connection before proceeding
|
|
389
|
+
- **Column Selection**: Select columns for:
|
|
390
|
+
- Embedding processing
|
|
391
|
+
- LLM processing
|
|
392
|
+
- ChromaDB storage
|
|
393
|
+
- **Modal Interface**: Clean, step-by-step modal interface
|
|
394
|
+
- **Sidebar Integration**: Ready to integrate into admin panel sidebars
|
|
395
|
+
|
|
396
|
+
### Database Configuration
|
|
397
|
+
|
|
398
|
+
The component supports:
|
|
399
|
+
- **MongoDB**: Connection string or individual fields (host, port, database, SSL)
|
|
400
|
+
- **PostgreSQL**: Host, port, database, username, password, SSL
|
|
401
|
+
|
|
402
|
+
### Backend API Requirements
|
|
403
|
+
|
|
404
|
+
Your backend should provide:
|
|
405
|
+
|
|
406
|
+
1. **Test Connection Endpoint** (`POST /api/database/test`)
|
|
407
|
+
- Accepts `DatabaseConnection` object
|
|
408
|
+
- Returns success/failure status
|
|
409
|
+
|
|
410
|
+
2. **Fetch Columns Endpoint** (`POST /api/database/columns`)
|
|
411
|
+
- Accepts `DatabaseConnection` object
|
|
412
|
+
- Returns array of column names
|
|
413
|
+
|
|
414
|
+
3. **Save Configuration Endpoint** (your implementation)
|
|
415
|
+
- Accepts `DatabaseConfig` object
|
|
416
|
+
- Saves configuration to your storage
|
|
417
|
+
|
|
418
|
+
## Troubleshooting
|
|
419
|
+
|
|
420
|
+
### Component not rendering or styles not working
|
|
421
|
+
|
|
422
|
+
1. **Check Tailwind Configuration**: Make sure `nextjs-chatbot-ui` is in your `tailwind.config.js` content array:
|
|
423
|
+
```javascript
|
|
424
|
+
content: [
|
|
425
|
+
'./node_modules/nextjs-chatbot-ui/**/*.{js,ts,jsx,tsx}',
|
|
426
|
+
// ... other paths
|
|
427
|
+
]
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
2. **Check Next.js Configuration**: Ensure `transpilePackages` is set in `next.config.js`:
|
|
431
|
+
```javascript
|
|
432
|
+
transpilePackages: ['nextjs-chatbot-ui']
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
3. **Restart Development Server**: After configuration changes, restart your Next.js dev server.
|
|
436
|
+
|
|
437
|
+
### TypeScript Errors
|
|
438
|
+
|
|
439
|
+
If you see TypeScript errors:
|
|
440
|
+
- Make sure you're using TypeScript 5+ (optional but recommended)
|
|
441
|
+
- The package includes type definitions, so TypeScript should work out of the box
|
|
442
|
+
- If using JavaScript, you can ignore type imports: `import { Chatbot } from 'nextjs-chatbot-ui';`
|
|
443
|
+
|
|
444
|
+
### "Module not found" or Import Errors
|
|
445
|
+
|
|
446
|
+
1. **Verify Installation**: Run `npm install nextjs-chatbot-ui` again
|
|
447
|
+
2. **Check Node Modules**: Ensure the package exists in `node_modules/nextjs-chatbot-ui`
|
|
448
|
+
3. **Clear Cache**: Try deleting `.next` folder and `node_modules`, then reinstall
|
|
449
|
+
|
|
450
|
+
### Component not appearing
|
|
451
|
+
|
|
452
|
+
- Make sure you're using `'use client'` directive in App Router
|
|
453
|
+
- Check that the component is not hidden by CSS (z-index, overflow, etc.)
|
|
454
|
+
- Verify the `position` prop is set correctly
|
|
455
|
+
|
|
456
|
+
### Backend API Issues
|
|
457
|
+
|
|
458
|
+
- Ensure your backend URL is correct and accessible
|
|
459
|
+
- Check CORS settings if making cross-origin requests
|
|
460
|
+
- Verify the API response format matches the expected structure (see Backend API Requirements)
|
|
461
|
+
|
|
462
|
+
## License
|
|
463
|
+
|
|
464
|
+
MIT
|
|
465
|
+
|
|
466
|
+
## Contributing
|
|
467
|
+
|
|
468
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
@@ -13,6 +13,7 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
|
|
|
13
13
|
const [currentStep, setCurrentStep] = useState<'connection' | 'columns'>('connection');
|
|
14
14
|
const [isConnecting, setIsConnecting] = useState(false);
|
|
15
15
|
const [connectionError, setConnectionError] = useState<string | null>(null);
|
|
16
|
+
const [connectionSuccess, setConnectionSuccess] = useState(false);
|
|
16
17
|
const [availableColumns, setAvailableColumns] = useState<string[]>([]);
|
|
17
18
|
const [isLoadingColumns, setIsLoadingColumns] = useState(false);
|
|
18
19
|
|
|
@@ -52,52 +53,69 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
|
|
|
52
53
|
setConnectionError(null);
|
|
53
54
|
};
|
|
54
55
|
|
|
55
|
-
const handleTestConnection = async () => {
|
|
56
|
+
const handleTestConnection = async (): Promise<boolean> => {
|
|
56
57
|
if (!onTestConnection) {
|
|
57
58
|
// Default test - just validate fields
|
|
58
59
|
if (!connection.host || !connection.database) {
|
|
59
60
|
setConnectionError('Please fill in all required fields');
|
|
60
|
-
|
|
61
|
+
setConnectionSuccess(false);
|
|
62
|
+
return false;
|
|
61
63
|
}
|
|
62
64
|
setConnectionError(null);
|
|
63
|
-
|
|
65
|
+
setConnectionSuccess(true);
|
|
66
|
+
return true;
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
setIsConnecting(true);
|
|
67
70
|
setConnectionError(null);
|
|
71
|
+
setConnectionSuccess(false);
|
|
68
72
|
|
|
69
73
|
try {
|
|
70
74
|
const isValid = await onTestConnection(connection);
|
|
71
75
|
if (isValid) {
|
|
72
76
|
setConnectionError(null);
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
setConnectionSuccess(true);
|
|
78
|
+
return true;
|
|
75
79
|
} else {
|
|
76
80
|
setConnectionError('Connection failed. Please check your credentials.');
|
|
81
|
+
setConnectionSuccess(false);
|
|
82
|
+
return false;
|
|
77
83
|
}
|
|
78
84
|
} catch (error: any) {
|
|
79
85
|
setConnectionError(error.message || 'Connection failed. Please try again.');
|
|
86
|
+
setConnectionSuccess(false);
|
|
87
|
+
return false;
|
|
80
88
|
} finally {
|
|
81
89
|
setIsConnecting(false);
|
|
82
90
|
}
|
|
83
91
|
};
|
|
84
92
|
|
|
85
|
-
const handleFetchColumns = async () => {
|
|
93
|
+
const handleFetchColumns = async (): Promise<string[]> => {
|
|
86
94
|
if (!onFetchColumns) {
|
|
87
95
|
// Mock columns for demo
|
|
88
|
-
|
|
96
|
+
const mockColumns = ['id', 'title', 'content', 'description', 'category', 'tags', 'created_at', 'updated_at'];
|
|
97
|
+
setAvailableColumns(mockColumns);
|
|
89
98
|
setIsLoadingColumns(false);
|
|
90
|
-
return;
|
|
99
|
+
return mockColumns;
|
|
91
100
|
}
|
|
92
101
|
|
|
93
102
|
setIsLoadingColumns(true);
|
|
103
|
+
setConnectionError(null);
|
|
94
104
|
try {
|
|
95
105
|
const columns = await onFetchColumns(connection);
|
|
96
|
-
|
|
106
|
+
if (columns && columns.length > 0) {
|
|
107
|
+
setAvailableColumns(columns);
|
|
108
|
+
setIsLoadingColumns(false);
|
|
109
|
+
return columns;
|
|
110
|
+
} else {
|
|
111
|
+
setConnectionError('No columns found in the database.');
|
|
112
|
+
setIsLoadingColumns(false);
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
97
115
|
} catch (error: any) {
|
|
98
116
|
setConnectionError(error.message || 'Failed to fetch columns');
|
|
99
|
-
} finally {
|
|
100
117
|
setIsLoadingColumns(false);
|
|
118
|
+
return [];
|
|
101
119
|
}
|
|
102
120
|
};
|
|
103
121
|
|
|
@@ -106,21 +124,39 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
|
|
|
106
124
|
if (dbType === 'mongodb') {
|
|
107
125
|
if (!connection.connectionString && (!connection.host || !connection.database)) {
|
|
108
126
|
setConnectionError('Please provide connection string or host and database');
|
|
127
|
+
setConnectionSuccess(false);
|
|
109
128
|
return;
|
|
110
129
|
}
|
|
111
130
|
} else {
|
|
112
131
|
if (!connection.host || !connection.database || !connection.username || !connection.password) {
|
|
113
132
|
setConnectionError('Please fill in all required fields');
|
|
133
|
+
setConnectionSuccess(false);
|
|
114
134
|
return;
|
|
115
135
|
}
|
|
116
136
|
}
|
|
117
137
|
|
|
118
|
-
//
|
|
119
|
-
|
|
138
|
+
// Clear previous errors
|
|
139
|
+
setConnectionError(null);
|
|
140
|
+
setConnectionSuccess(false);
|
|
141
|
+
|
|
142
|
+
// Test connection first
|
|
143
|
+
const connectionSuccess = await handleTestConnection();
|
|
120
144
|
|
|
121
|
-
|
|
122
|
-
|
|
145
|
+
if (!connectionSuccess) {
|
|
146
|
+
// Connection failed, don't proceed
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// If connection successful, fetch columns
|
|
151
|
+
const fetchedColumns = await handleFetchColumns();
|
|
152
|
+
|
|
153
|
+
if (fetchedColumns && fetchedColumns.length > 0) {
|
|
154
|
+
// Successfully fetched columns, move to next step
|
|
123
155
|
setCurrentStep('columns');
|
|
156
|
+
setConnectionError(null);
|
|
157
|
+
} else {
|
|
158
|
+
// Column fetching failed, show error but keep connection success
|
|
159
|
+
// Error is already set in handleFetchColumns
|
|
124
160
|
}
|
|
125
161
|
};
|
|
126
162
|
|
|
@@ -158,6 +194,8 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
|
|
|
158
194
|
setIsModalOpen(false);
|
|
159
195
|
setCurrentStep('connection');
|
|
160
196
|
setConnectionError(null);
|
|
197
|
+
setConnectionSuccess(false);
|
|
198
|
+
setAvailableColumns([]);
|
|
161
199
|
setColumnSelection({
|
|
162
200
|
embeddingColumns: [],
|
|
163
201
|
llmColumns: [],
|
|
@@ -435,88 +473,131 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
|
|
|
435
473
|
<p className="text-sm text-red-800">{connectionError}</p>
|
|
436
474
|
</div>
|
|
437
475
|
)}
|
|
476
|
+
{connectionSuccess && !connectionError && !isConnecting && (
|
|
477
|
+
<div className="bg-green-50 border border-green-200 rounded-lg p-4">
|
|
478
|
+
<p className="text-sm text-green-800">✓ Connection successful!</p>
|
|
479
|
+
</div>
|
|
480
|
+
)}
|
|
438
481
|
</div>
|
|
439
482
|
) : (
|
|
440
483
|
<div className="space-y-6">
|
|
441
484
|
{isLoadingColumns ? (
|
|
442
|
-
<div className="flex items-center justify-center py-8">
|
|
443
|
-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
|
|
485
|
+
<div className="flex flex-col items-center justify-center py-8">
|
|
486
|
+
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mb-3"></div>
|
|
487
|
+
<p className="text-sm text-gray-600">Loading columns...</p>
|
|
488
|
+
</div>
|
|
489
|
+
) : availableColumns.length === 0 ? (
|
|
490
|
+
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
|
491
|
+
<p className="text-sm text-yellow-800">No columns available. Please go back and check your connection.</p>
|
|
444
492
|
</div>
|
|
445
493
|
) : (
|
|
446
494
|
<>
|
|
447
495
|
<div>
|
|
448
|
-
<p className="text-sm text-gray-600 mb-
|
|
449
|
-
Select which columns to use for
|
|
496
|
+
<p className="text-sm text-gray-600 mb-2">
|
|
497
|
+
Select which columns to use for <strong>Embeddings</strong>, <strong>LLM processing</strong>, and <strong>ChromaDB storage</strong>.
|
|
498
|
+
</p>
|
|
499
|
+
<p className="text-xs text-gray-500 mb-4">
|
|
500
|
+
Found {availableColumns.length} column{availableColumns.length !== 1 ? 's' : ''} in your database.
|
|
450
501
|
</p>
|
|
451
502
|
</div>
|
|
452
503
|
|
|
453
504
|
{/* Embedding Columns */}
|
|
454
505
|
<div>
|
|
455
|
-
<label className="block text-sm font-medium text-gray-700 mb-
|
|
456
|
-
|
|
506
|
+
<label className="block text-sm font-medium text-gray-700 mb-2">
|
|
507
|
+
Works with Embeddings
|
|
457
508
|
</label>
|
|
458
|
-
<
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
<
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
509
|
+
<p className="text-xs text-gray-500 mb-3">Select columns that will be used for embedding generation</p>
|
|
510
|
+
<div className="grid grid-cols-2 gap-2 max-h-40 overflow-y-auto border border-gray-200 rounded-lg p-3 bg-gray-50">
|
|
511
|
+
{availableColumns.length === 0 ? (
|
|
512
|
+
<p className="text-sm text-gray-500 col-span-2 text-center py-2">No columns available</p>
|
|
513
|
+
) : (
|
|
514
|
+
availableColumns.map((column) => (
|
|
515
|
+
<label
|
|
516
|
+
key={`embedding-${column}`}
|
|
517
|
+
className="flex items-center gap-2 cursor-pointer hover:bg-white p-2 rounded transition-colors"
|
|
518
|
+
>
|
|
519
|
+
<input
|
|
520
|
+
type="checkbox"
|
|
521
|
+
checked={columnSelection.embeddingColumns.includes(column)}
|
|
522
|
+
onChange={() => handleColumnToggle(column, 'embeddingColumns')}
|
|
523
|
+
className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
|
524
|
+
/>
|
|
525
|
+
<span className="text-sm text-gray-700">{column}</span>
|
|
526
|
+
</label>
|
|
527
|
+
))
|
|
528
|
+
)}
|
|
473
529
|
</div>
|
|
530
|
+
{columnSelection.embeddingColumns.length > 0 && (
|
|
531
|
+
<p className="text-xs text-green-600 mt-1">
|
|
532
|
+
{columnSelection.embeddingColumns.length} column{columnSelection.embeddingColumns.length !== 1 ? 's' : ''} selected
|
|
533
|
+
</p>
|
|
534
|
+
)}
|
|
474
535
|
</div>
|
|
475
536
|
|
|
476
537
|
{/* LLM Columns */}
|
|
477
538
|
<div>
|
|
478
|
-
<label className="block text-sm font-medium text-gray-700 mb-
|
|
479
|
-
LLM
|
|
539
|
+
<label className="block text-sm font-medium text-gray-700 mb-2">
|
|
540
|
+
Works with LLM
|
|
480
541
|
</label>
|
|
481
|
-
<
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
<
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
542
|
+
<p className="text-xs text-gray-500 mb-3">Select columns that will be processed by the LLM</p>
|
|
543
|
+
<div className="grid grid-cols-2 gap-2 max-h-40 overflow-y-auto border border-gray-200 rounded-lg p-3 bg-gray-50">
|
|
544
|
+
{availableColumns.length === 0 ? (
|
|
545
|
+
<p className="text-sm text-gray-500 col-span-2 text-center py-2">No columns available</p>
|
|
546
|
+
) : (
|
|
547
|
+
availableColumns.map((column) => (
|
|
548
|
+
<label
|
|
549
|
+
key={`llm-${column}`}
|
|
550
|
+
className="flex items-center gap-2 cursor-pointer hover:bg-white p-2 rounded transition-colors"
|
|
551
|
+
>
|
|
552
|
+
<input
|
|
553
|
+
type="checkbox"
|
|
554
|
+
checked={columnSelection.llmColumns.includes(column)}
|
|
555
|
+
onChange={() => handleColumnToggle(column, 'llmColumns')}
|
|
556
|
+
className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
|
557
|
+
/>
|
|
558
|
+
<span className="text-sm text-gray-700">{column}</span>
|
|
559
|
+
</label>
|
|
560
|
+
))
|
|
561
|
+
)}
|
|
496
562
|
</div>
|
|
563
|
+
{columnSelection.llmColumns.length > 0 && (
|
|
564
|
+
<p className="text-xs text-green-600 mt-1">
|
|
565
|
+
{columnSelection.llmColumns.length} column{columnSelection.llmColumns.length !== 1 ? 's' : ''} selected
|
|
566
|
+
</p>
|
|
567
|
+
)}
|
|
497
568
|
</div>
|
|
498
569
|
|
|
499
570
|
{/* ChromaDB Columns */}
|
|
500
571
|
<div>
|
|
501
|
-
<label className="block text-sm font-medium text-gray-700 mb-
|
|
502
|
-
ChromaDB
|
|
572
|
+
<label className="block text-sm font-medium text-gray-700 mb-2">
|
|
573
|
+
Works with ChromaDB
|
|
503
574
|
</label>
|
|
504
|
-
<
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
<
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
575
|
+
<p className="text-xs text-gray-500 mb-3">Select columns that will be stored in ChromaDB</p>
|
|
576
|
+
<div className="grid grid-cols-2 gap-2 max-h-40 overflow-y-auto border border-gray-200 rounded-lg p-3 bg-gray-50">
|
|
577
|
+
{availableColumns.length === 0 ? (
|
|
578
|
+
<p className="text-sm text-gray-500 col-span-2 text-center py-2">No columns available</p>
|
|
579
|
+
) : (
|
|
580
|
+
availableColumns.map((column) => (
|
|
581
|
+
<label
|
|
582
|
+
key={`chroma-${column}`}
|
|
583
|
+
className="flex items-center gap-2 cursor-pointer hover:bg-white p-2 rounded transition-colors"
|
|
584
|
+
>
|
|
585
|
+
<input
|
|
586
|
+
type="checkbox"
|
|
587
|
+
checked={columnSelection.chromaColumns.includes(column)}
|
|
588
|
+
onChange={() => handleColumnToggle(column, 'chromaColumns')}
|
|
589
|
+
className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
|
590
|
+
/>
|
|
591
|
+
<span className="text-sm text-gray-700">{column}</span>
|
|
592
|
+
</label>
|
|
593
|
+
))
|
|
594
|
+
)}
|
|
519
595
|
</div>
|
|
596
|
+
{columnSelection.chromaColumns.length > 0 && (
|
|
597
|
+
<p className="text-xs text-green-600 mt-1">
|
|
598
|
+
{columnSelection.chromaColumns.length} column{columnSelection.chromaColumns.length !== 1 ? 's' : ''} selected
|
|
599
|
+
</p>
|
|
600
|
+
)}
|
|
520
601
|
</div>
|
|
521
602
|
</>
|
|
522
603
|
)}
|
|
@@ -537,9 +618,12 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
|
|
|
537
618
|
<button
|
|
538
619
|
onClick={handleConnectAndNext}
|
|
539
620
|
disabled={isConnecting || isLoadingColumns}
|
|
540
|
-
className="px-6 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
|
621
|
+
className="px-6 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center gap-2"
|
|
541
622
|
>
|
|
542
|
-
{isConnecting
|
|
623
|
+
{isConnecting && (
|
|
624
|
+
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white"></div>
|
|
625
|
+
)}
|
|
626
|
+
{isLoadingColumns ? 'Loading Columns...' : isConnecting ? 'Connecting...' : 'Connect & Next'}
|
|
543
627
|
</button>
|
|
544
628
|
) : (
|
|
545
629
|
<button
|
package/package.json
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "nextjs-chatbot-ui",
|
|
3
|
-
|
|
4
|
-
"version": "1.
|
|
5
|
-
"description": "A configurable chatbot UI component for Next.js with Tailwind CSS",
|
|
6
|
-
"main": "./index.tsx",
|
|
7
|
-
"module": "./index.tsx",
|
|
8
|
-
"types": "./types/index.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./types/index.ts",
|
|
12
|
-
"import": "./index.tsx",
|
|
13
|
-
"require": "./index.tsx",
|
|
14
|
-
"default": "./index.tsx"
|
|
15
|
-
},
|
|
16
|
-
"./components/Chatbot": {
|
|
17
|
-
"types": "./types/index.ts",
|
|
18
|
-
"import": "./components/Chatbot.tsx",
|
|
19
|
-
"require": "./components/Chatbot.tsx",
|
|
20
|
-
"default": "./components/Chatbot.tsx"
|
|
21
|
-
},
|
|
22
|
-
"./types": {
|
|
23
|
-
"types": "./types/index.ts",
|
|
24
|
-
"import": "./types/index.ts",
|
|
25
|
-
"require": "./types/index.ts",
|
|
26
|
-
"default": "./types/index.ts"
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
"files": [
|
|
30
|
-
"components",
|
|
31
|
-
"types",
|
|
32
|
-
"index.tsx",
|
|
33
|
-
"README.md"
|
|
34
|
-
],
|
|
35
|
-
"scripts": {
|
|
36
|
-
"build": "echo 'Package is ready to use. Source files are included.'",
|
|
37
|
-
"dev": "next dev",
|
|
38
|
-
"prepare": "npm run build",
|
|
39
|
-
"type-check": "tsc --noEmit"
|
|
40
|
-
},
|
|
41
|
-
"keywords": [
|
|
42
|
-
"chatbot",
|
|
43
|
-
"ui",
|
|
44
|
-
"component",
|
|
45
|
-
"nextjs",
|
|
46
|
-
"tailwind",
|
|
47
|
-
"react"
|
|
48
|
-
],
|
|
49
|
-
"author": "",
|
|
50
|
-
"license": "MIT",
|
|
51
|
-
"peerDependencies": {
|
|
52
|
-
"react": "^18.0.0",
|
|
53
|
-
"react-dom": "^18.0.0",
|
|
54
|
-
"next": "^14.0.0"
|
|
55
|
-
},
|
|
56
|
-
"dependencies": {
|
|
57
|
-
"clsx": "^2.1.0"
|
|
58
|
-
},
|
|
59
|
-
"devDependencies": {
|
|
60
|
-
"@types/node": "^20.0.0",
|
|
61
|
-
"@types/react": "^18.0.0",
|
|
62
|
-
"@types/react-dom": "^18.0.0",
|
|
63
|
-
"autoprefixer": "^10.4.16",
|
|
64
|
-
"postcss": "^8.4.32",
|
|
65
|
-
"tailwindcss": "^3.4.0",
|
|
66
|
-
"typescript": "^5.3.3"
|
|
67
|
-
}
|
|
68
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "nextjs-chatbot-ui",
|
|
3
|
+
|
|
4
|
+
"version": "1.1.1",
|
|
5
|
+
"description": "A configurable chatbot UI component for Next.js with Tailwind CSS",
|
|
6
|
+
"main": "./index.tsx",
|
|
7
|
+
"module": "./index.tsx",
|
|
8
|
+
"types": "./types/index.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./types/index.ts",
|
|
12
|
+
"import": "./index.tsx",
|
|
13
|
+
"require": "./index.tsx",
|
|
14
|
+
"default": "./index.tsx"
|
|
15
|
+
},
|
|
16
|
+
"./components/Chatbot": {
|
|
17
|
+
"types": "./types/index.ts",
|
|
18
|
+
"import": "./components/Chatbot.tsx",
|
|
19
|
+
"require": "./components/Chatbot.tsx",
|
|
20
|
+
"default": "./components/Chatbot.tsx"
|
|
21
|
+
},
|
|
22
|
+
"./types": {
|
|
23
|
+
"types": "./types/index.ts",
|
|
24
|
+
"import": "./types/index.ts",
|
|
25
|
+
"require": "./types/index.ts",
|
|
26
|
+
"default": "./types/index.ts"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"components",
|
|
31
|
+
"types",
|
|
32
|
+
"index.tsx",
|
|
33
|
+
"README.md"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "echo 'Package is ready to use. Source files are included.'",
|
|
37
|
+
"dev": "next dev",
|
|
38
|
+
"prepare": "npm run build",
|
|
39
|
+
"type-check": "tsc --noEmit"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"chatbot",
|
|
43
|
+
"ui",
|
|
44
|
+
"component",
|
|
45
|
+
"nextjs",
|
|
46
|
+
"tailwind",
|
|
47
|
+
"react"
|
|
48
|
+
],
|
|
49
|
+
"author": "",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
53
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
54
|
+
"next": "^13.0.0 || ^14.0.0 || ^15.0.0"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"clsx": "^2.1.0"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@types/node": "^20.0.0",
|
|
61
|
+
"@types/react": "^18.0.0",
|
|
62
|
+
"@types/react-dom": "^18.0.0",
|
|
63
|
+
"autoprefixer": "^10.4.16",
|
|
64
|
+
"postcss": "^8.4.32",
|
|
65
|
+
"tailwindcss": "^3.4.0",
|
|
66
|
+
"typescript": "^5.3.3"
|
|
67
|
+
}
|
|
68
|
+
}
|