@enjoys/react-chatbot-plugin 1.1.0 → 1.3.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 CHANGED
@@ -1,8 +1,25 @@
1
- # @enjoys/react-chatbot-plugin
1
+ <p align="center">
2
+ <img src="https://img.shields.io/npm/v/@enjoys/react-chatbot-plugin?color=6C5CE7&style=for-the-badge" alt="npm version" />
3
+ <img src="https://img.shields.io/npm/dm/@enjoys/react-chatbot-plugin?color=A29BFE&style=for-the-badge" alt="npm downloads" />
4
+ <img src="https://img.shields.io/bundlephobia/minzip/@enjoys/react-chatbot-plugin?color=00b894&style=for-the-badge" alt="bundle size" />
5
+ <img src="https://img.shields.io/npm/l/@enjoys/react-chatbot-plugin?color=fd79a8&style=for-the-badge" alt="license" />
6
+ <img src="https://img.shields.io/github/stars/enjoys-in/react-chatbot-plugin?color=fdcb6e&style=for-the-badge" alt="stars" />
7
+ </p>
2
8
 
3
- A customizable, plugin-based chatbot widget for React — like tawk.to but fully programmable.
9
+ <h1 align="center">@enjoys/react-chatbot-plugin</h1>
4
10
 
5
- [![npm](https://img.shields.io/npm/v/@enjoys/react-chatbot-plugin)](https://www.npmjs.com/package/@enjoys/react-chatbot-plugin)
11
+ <p align="center">
12
+ A customizable, plugin-based chatbot widget for React — like tawk.to but fully programmable.
13
+ </p>
14
+
15
+ <p align="center">
16
+ <a href="https://github.com/enjoys-in/react-chatbot-plugin">GitHub</a> ·
17
+ <a href="https://www.npmjs.com/package/@enjoys/react-chatbot-plugin">npm</a> ·
18
+ <a href="https://github.com/enjoys-in/react-chatbot-plugin/issues">Report Bug</a> ·
19
+ <a href="https://github.com/enjoys-in/react-chatbot-plugin/issues">Request Feature</a>
20
+ </p>
21
+
22
+ ---
6
23
 
7
24
  ## Features
8
25
 
@@ -14,6 +31,7 @@ A customizable, plugin-based chatbot widget for React — like tawk.to but fully
14
31
  - **Slash commands** — `/help`, `/back`, `/cancel`, `/restart` built-in
15
32
  - **Custom header/input** — Swap the header or input with your own React components
16
33
  - **Forms** — Text, select, radio, checkbox, file upload, with validation
34
+ - **Custom form fields** — Replace any form field type with your own React component
17
35
  - **Theming** — Light/dark mode, CSS variables, glassmorphism design
18
36
  - **File uploads** — Drag & drop, preview, size/count limits
19
37
  - **Emoji picker** — Built-in emoji selector
@@ -25,6 +43,10 @@ A customizable, plugin-based chatbot widget for React — like tawk.to but fully
25
43
  ```bash
26
44
  npm install @enjoys/react-chatbot-plugin
27
45
  # or
46
+ yarn add @enjoys/react-chatbot-plugin
47
+ # or
48
+ pnpm add @enjoys/react-chatbot-plugin
49
+ # or
28
50
  bun add @enjoys/react-chatbot-plugin
29
51
  ```
30
52
 
@@ -57,14 +79,32 @@ function App() {
57
79
  <ChatBot
58
80
  flow={flow}
59
81
  header={{ title: 'Acme Support', subtitle: 'Online', showRestart: true }}
60
- callbacks={{
61
- onFlowEnd: (data) => console.log('Flow ended:', data),
62
- }}
63
82
  />
64
83
  );
65
84
  }
66
85
  ```
67
86
 
87
+ ## Documentation
88
+
89
+ Full documentation is available in the [`docs/`](./docs/) folder:
90
+
91
+ | # | Guide | Description |
92
+ |---|-------|-------------|
93
+ | 1 | [Getting Started](./docs/getting-started.md) | Installation, quick start, minimal example |
94
+ | 2 | [Basic Flows](./docs/basic-flows.md) | Steps, messages, quick replies, delays |
95
+ | 3 | [Forms & Validation](./docs/forms.md) | All 15 field types, validation rules, login forms |
96
+ | 4 | [Conditional Branching](./docs/conditional-branching.md) | If/else routing based on collected data |
97
+ | 5 | [Async Actions](./docs/async-actions.md) | API calls, progress messages, error handling |
98
+ | 6 | [Custom Components](./docs/custom-components.md) | React widgets inside flow steps |
99
+ | 7 | [Dynamic Routing](./docs/dynamic-routing.md) | Route based on API response status |
100
+ | 8 | [Theming & Styling](./docs/theming.md) | Colors, CSS variables, dark mode |
101
+ | 9 | [Plugins](./docs/plugins.md) | Built-in & custom plugins |
102
+ | 10 | [Slash Commands](./docs/slash-commands.md) | /help, /back, /restart, /cancel |
103
+ | 11 | [File Upload](./docs/file-upload.md) | Drag & drop, restrictions, previews |
104
+ | 12 | [Custom Header & Input](./docs/custom-header-input.md) | Replace header/input with React components |
105
+ | 13 | [Advanced Patterns](./docs/advanced-patterns.md) | E-commerce bot, onboarding wizard, full examples |
106
+ | 14 | [API Reference](./docs/api-reference.md) | All types, props, and exports |
107
+
68
108
  ## Props
69
109
 
70
110
  | Prop | Type | Description |
@@ -92,439 +132,16 @@ function App() {
92
132
  | `launcherIcon` | `ReactNode` | Custom launcher icon |
93
133
  | `closeIcon` | `ReactNode` | Custom close icon |
94
134
  | `zIndex` | `number` | CSS z-index |
135
+ | `renderFormField` | `FormFieldRenderMap` | Custom renderers for form field types |
95
136
  | `className` | `string` | Root element class name |
96
137
 
97
- ## Conversation Flows
98
-
99
- Flows are JSON objects with steps. Each step can have messages, quick replies, forms, conditional branching, and delays.
100
-
101
- ```ts
102
- const flow: FlowConfig = {
103
- startStep: 'welcome',
104
- steps: [
105
- {
106
- id: 'welcome',
107
- message: 'Welcome! What brings you here?',
108
- quickReplies: [
109
- { label: 'Buy', value: 'buy', next: 'purchase' },
110
- { label: 'Help', value: 'help', next: 'support' },
111
- ],
112
- },
113
- {
114
- id: 'purchase',
115
- message: 'Great choice!',
116
- form: {
117
- id: 'order',
118
- title: 'Order Details',
119
- fields: [
120
- { name: 'email', type: 'email', label: 'Email', required: true },
121
- { name: 'quantity', type: 'number', label: 'Quantity', required: true },
122
- ],
123
- submitLabel: 'Place Order',
124
- },
125
- next: 'thanks',
126
- },
127
- {
128
- id: 'support',
129
- message: 'Please describe your issue.',
130
- },
131
- {
132
- id: 'thanks',
133
- message: 'Order placed! We will email you shortly.',
134
- },
135
- ],
136
- };
137
- ```
138
-
139
- ### Step Properties
140
-
141
- | Property | Type | Description |
142
- |----------|------|-------------|
143
- | `id` | `string` | Unique step identifier |
144
- | `message` | `string` | Single bot message |
145
- | `messages` | `string[]` | Multiple bot messages |
146
- | `quickReplies` | `FlowQuickReply[]` | Clickable option buttons |
147
- | `form` | `FormConfig` | Inline form |
148
- | `next` | `string` | Next step ID (auto-advance) |
149
- | `delay` | `number` | Typing delay in ms (default: 500) |
150
- | `condition` | `FlowCondition` | Conditional branching |
151
- | `component` | `string` | Key into `components` map — renders a custom React widget |
152
- | `asyncAction` | `FlowAsyncAction` | Async action to run when the step is entered |
153
-
154
- ### Conditional Branching
155
-
156
- ```ts
157
- {
158
- id: 'check_age',
159
- message: 'Checking your age...',
160
- condition: {
161
- field: 'age',
162
- operator: 'gt', // eq, neq, contains, gt, lt
163
- value: 18,
164
- then: 'adult_flow',
165
- else: 'minor_flow',
166
- },
167
- }
168
- ```
169
-
170
- ## Async Actions
171
-
172
- Run API calls, validations, or any async work when a step is entered. The chat shows real-time progress messages and routes based on the result.
173
-
174
- ```tsx
175
- import type { FlowConfig, FlowActionResult, ActionContext } from '@enjoys/react-chatbot-plugin';
176
-
177
- const flow: FlowConfig = {
178
- startStep: 'collect_email',
179
- steps: [
180
- {
181
- id: 'collect_email',
182
- message: 'Enter your email to verify:',
183
- form: {
184
- id: 'email-form',
185
- title: 'Email Verification',
186
- fields: [{ name: 'email', type: 'email', label: 'Email', required: true }],
187
- submitLabel: 'Verify',
188
- },
189
- next: 'verify',
190
- },
191
- {
192
- id: 'verify',
193
- message: 'Starting verification...',
194
- asyncAction: {
195
- handler: 'verify-email', // key into actionHandlers
196
- loadingMessage: '🔄 Verifying...', // shown while running
197
- successMessage: '✅ Verified!', // shown on success
198
- errorMessage: '❌ Failed.', // shown on error/throw
199
- onSuccess: 'done', // next step on success
200
- onError: 'retry', // next step on error
201
- },
202
- },
203
- { id: 'done', message: 'Your email is verified! 🎉' },
204
- {
205
- id: 'retry',
206
- message: 'Verification failed. Try again?',
207
- quickReplies: [
208
- { label: 'Retry', value: 'retry', next: 'collect_email' },
209
- ],
210
- },
211
- ],
212
- };
213
-
214
- <ChatBot
215
- flow={flow}
216
- actionHandlers={{
217
- 'verify-email': async (data, ctx) => {
218
- ctx.updateMessage('📡 Contacting server...'); // update status message in real-time
219
- await fetch('/api/verify', { method: 'POST', body: JSON.stringify(data) });
220
- ctx.updateMessage('🔐 Validating...');
221
- // return result — status determines routing
222
- return { status: 'success', data: { verified: true } };
223
- },
224
- }}
225
- />
226
- ```
227
-
228
- ### FlowAsyncAction Properties
229
-
230
- | Property | Type | Description |
231
- |----------|------|-------------|
232
- | `handler` | `string` | Key into `actionHandlers` prop |
233
- | `loadingMessage` | `string` | Message shown while running (default: "Processing...") |
234
- | `successMessage` | `string` | Message shown on success |
235
- | `errorMessage` | `string` | Message shown on error or exception |
236
- | `onSuccess` | `string` | Next step ID on success |
237
- | `onError` | `string` | Next step ID on error |
238
- | `routes` | `Record<string, string>` | Map of `result.status` → step ID for custom routing |
239
-
240
- ### ActionContext
241
-
242
- | Method | Description |
243
- |--------|-------------|
244
- | `updateMessage(text)` | Update the loading/status message text in real-time |
245
-
246
- ### FlowActionResult
247
-
248
- Returned by action handlers to control routing and data:
249
-
250
- | Property | Type | Description |
251
- |----------|------|-------------|
252
- | `status` | `string` | `'success'`, `'error'`, or any custom string for route matching |
253
- | `data` | `Record<string, unknown>` | Data to merge into collected data |
254
- | `message` | `string` | Override the success/error message |
255
- | `next` | `string` | Override all routing — go directly to this step |
256
-
257
- **Routing priority:** `result.next` → `routes[status]` → `onSuccess/onError` → `step.next`
258
-
259
- ## Custom Step Components
260
-
261
- Render your own interactive React widgets inside flow steps. Components receive collected data and an `onComplete` callback to continue the flow.
262
-
263
- ```tsx
264
- import type { StepComponentProps } from '@enjoys/react-chatbot-plugin';
265
-
266
- const PlanSelector: React.FC<StepComponentProps> = ({ data, onComplete }) => (
267
- <div>
268
- <p>Hi {data.name as string}! Choose a plan:</p>
269
- <button onClick={() => onComplete({ status: 'success', data: { plan: 'basic' }, next: 'basic_info' })}>
270
- Basic — $9/mo
271
- </button>
272
- <button onClick={() => onComplete({ status: 'success', data: { plan: 'pro' }, next: 'pro_info' })}>
273
- Pro — $29/mo
274
- </button>
275
- </div>
276
- );
277
-
278
- const flow: FlowConfig = {
279
- startStep: 'choose_plan',
280
- steps: [
281
- {
282
- id: 'choose_plan',
283
- message: 'Select your plan:',
284
- component: 'PlanSelector', // key into components map
285
- },
286
- { id: 'basic_info', message: 'Basic plan selected!' },
287
- { id: 'pro_info', message: 'Pro plan selected!' },
288
- ],
289
- };
290
-
291
- <ChatBot
292
- flow={flow}
293
- components={{ PlanSelector }} // register your components here
294
- />
295
- ```
296
-
297
- ### StepComponentProps
298
-
299
- | Property | Type | Description |
300
- |----------|------|-------------|
301
- | `stepId` | `string` | The step ID that owns this component |
302
- | `data` | `Record<string, unknown>` | All collected flow/form data |
303
- | `onComplete` | `(result?: FlowActionResult) => void` | Call to complete the step and route to the next |
304
-
305
- ## Dynamic Routing
306
-
307
- Use `asyncAction.routes` to map API result statuses to different steps:
308
-
309
- ```tsx
310
- {
311
- id: 'check_account',
312
- message: 'Looking up your account...',
313
- asyncAction: {
314
- handler: 'check-account',
315
- loadingMessage: '🔍 Searching...',
316
- routes: {
317
- admin: 'admin_panel', // result.status === 'admin'
318
- vip: 'vip_welcome', // result.status === 'vip'
319
- active: 'dashboard', // result.status === 'active'
320
- not_found: 'register', // result.status === 'not_found'
321
- },
322
- },
323
- }
324
- ```
325
-
326
- The action handler returns the status that determines which route to take:
327
-
328
- ```ts
329
- 'check-account': async (data, ctx) => {
330
- const user = await api.lookup(data.username);
331
- if (!user) return { status: 'not_found' };
332
- return { status: user.role, data: { userId: user.id } };
333
- }
334
- ```
335
-
336
- ## Slash Commands
337
-
338
- Users can type these commands in the chat input:
339
-
340
- | Command | Description |
341
- |---------|-------------|
342
- | `/help` | Show available commands |
343
- | `/back` | Go back to the previous step |
344
- | `/cancel` | Same as /back — cancel current step |
345
- | `/restart` | Restart the conversation from the beginning |
346
-
347
- ## Custom Header & Input
348
-
349
- Use `renderHeader` and `renderInput` to replace the default header or input with your own components. Both receive a `ChatRenderContext` object and the default element:
350
-
351
- ```tsx
352
- <ChatBot
353
- flow={flow}
354
- renderHeader={(ctx, defaultHeader) => (
355
- <div style={{ padding: 16, background: '#333', color: '#fff' }}>
356
- <h3>My Custom Header</h3>
357
- <p>Step: {ctx.currentStepId ?? 'none'}</p>
358
- <button onClick={ctx.restartSession}>Restart</button>
359
- <button onClick={ctx.toggleChat}>Close</button>
360
- </div>
361
- )}
362
- renderInput={(ctx, defaultInput) => {
363
- // Use the default input but wrap it
364
- return (
365
- <div>
366
- {defaultInput}
367
- <small>Step: {ctx.currentStepId}</small>
368
- </div>
369
- );
370
- }}
371
- />
372
- ```
373
-
374
- ### ChatRenderContext
375
-
376
- | Property | Type | Description |
377
- |----------|------|-------------|
378
- | `currentStepId` | `string \| null` | Current flow step ID |
379
- | `isOpen` | `boolean` | Whether the chat window is open |
380
- | `messages` | `ChatMessage[]` | All messages |
381
- | `collectedData` | `Record<string, unknown>` | Collected form/flow data |
382
- | `toggleChat` | `() => void` | Open/close the chat |
383
- | `restartSession` | `() => void` | Restart from beginning |
384
- | `sendMessage` | `(text: string) => void` | Send a message programmatically |
385
-
386
- ## Theming
387
-
388
- ```tsx
389
- <ChatBot
390
- theme={{
391
- primaryColor: '#6C5CE7',
392
- headerBg: 'linear-gradient(135deg, #6C5CE7, #A29BFE)',
393
- borderRadius: '20px',
394
- mode: 'dark', // or 'light'
395
- fontFamily: '"Inter", sans-serif',
396
- windowWidth: '400px',
397
- windowHeight: '600px',
398
- }}
399
- />
400
- ```
401
-
402
- All theme values are also exposed as CSS variables (`--cb-primary`, `--cb-header-bg`, etc.).
403
-
404
- ## Plugins
405
-
406
- ### Built-in Plugins
407
-
408
- ```tsx
409
- import { analyticsPlugin, webhookPlugin, persistencePlugin } from '@enjoys/react-chatbot-plugin';
410
-
411
- <ChatBot
412
- plugins={[
413
- analyticsPlugin({
414
- onTrack: (event, data) => console.log(event, data),
415
- }),
416
- webhookPlugin({
417
- url: '/api/chatbot-webhook',
418
- events: ['message', 'submit'],
419
- }),
420
- persistencePlugin({
421
- storageKey: 'my_chat',
422
- storage: 'local', // or 'session'
423
- }),
424
- ]}
425
- />
426
- ```
427
-
428
- ### Custom Plugin
429
-
430
- ```ts
431
- import type { ChatPlugin } from '@enjoys/react-chatbot-plugin';
432
-
433
- const myPlugin: ChatPlugin = {
434
- name: 'my-plugin',
435
- onInit(ctx) {
436
- console.log('Chat initialized');
437
- },
438
- onMessage(message, ctx) {
439
- console.log('Message:', message);
440
- },
441
- onSubmit(data, ctx) {
442
- console.log('Form submitted:', data);
443
- },
444
- onDestroy(ctx) {
445
- console.log('Chat destroyed');
446
- },
447
- };
448
- ```
449
-
450
- ### Plugin Context
451
-
452
- | Method | Description |
453
- |--------|-------------|
454
- | `sendMessage(text)` | Send a user message |
455
- | `addBotMessage(text)` | Add a bot message |
456
- | `getMessages()` | Get all messages |
457
- | `getData()` | Get collected data |
458
- | `setData(key, value)` | Set data |
459
- | `on(event, handler)` | Subscribe to events |
460
- | `emit(event, ...args)` | Emit events |
461
-
462
- ## Forms
463
-
464
- Forms can be used in flows or as a login screen:
465
-
466
- ```ts
467
- const form: FormConfig = {
468
- id: 'contact',
469
- title: 'Contact Us',
470
- description: 'Fill out the form below',
471
- fields: [
472
- { name: 'name', type: 'text', label: 'Name', required: true },
473
- { name: 'email', type: 'email', label: 'Email', required: true,
474
- validation: { pattern: '^[^@]+@[^@]+\\.[^@]+$', message: 'Invalid email' } },
475
- { name: 'priority', type: 'select', label: 'Priority', options: [
476
- { label: 'Low', value: 'low' },
477
- { label: 'High', value: 'high' },
478
- ]},
479
- { name: 'message', type: 'textarea', label: 'Message' },
480
- { name: 'file', type: 'file', label: 'Attachment', accept: 'image/*,.pdf' },
481
- ],
482
- submitLabel: 'Send',
483
- };
484
- ```
485
-
486
- **Supported field types:** `text`, `email`, `password`, `number`, `tel`, `url`, `textarea`, `select`, `multiselect`, `radio`, `checkbox`, `file`, `date`, `time`, `hidden`
487
-
488
- ## Callbacks
489
-
490
- ```tsx
491
- <ChatBot
492
- callbacks={{
493
- onOpen: () => {},
494
- onClose: () => {},
495
- onMessageSend: (msg) => {},
496
- onMessageReceive: (msg) => {},
497
- onSubmit: (data) => {},
498
- onLogin: (data) => {},
499
- onFormSubmit: (formId, data) => {},
500
- onQuickReply: (value, label) => {},
501
- onFileUpload: (files) => {},
502
- onFlowEnd: (collectedData) => {},
503
- onError: (error) => {},
504
- onEvent: (event, payload) => {},
505
- }}
506
- />
507
- ```
508
-
509
- ## File Upload
510
-
511
- ```tsx
512
- <ChatBot
513
- fileUpload={{
514
- enabled: true,
515
- accept: 'image/*,.pdf,.doc,.docx',
516
- multiple: true,
517
- maxSize: 5 * 1024 * 1024, // 5MB
518
- maxFiles: 3,
519
- }}
520
- />
521
- ```
522
-
523
138
  ## Exported Components
524
139
 
525
140
  All internal components are exported for advanced use cases:
526
141
 
527
- `ChatBot`, `ChatHeader`, `ChatInput`, `ChatWindow`, `Launcher`, `MessageBubble`, `MessageList`, `QuickReplies`, `TypingIndicator`, `WelcomeScreen`, `LoginScreen`, `Branding`, `EmojiPicker`, `FileUploadButton`, `FilePreviewList`, `DynamicForm`, `TextField`, `SelectField`, `RadioField`, `CheckboxField`, `FileUploadField`
142
+ **UI:** `ChatBot`, `ChatHeader`, `ChatInput`, `ChatWindow`, `Launcher`, `MessageBubble`, `MessageList`, `QuickReplies`, `TypingIndicator`, `WelcomeScreen`, `LoginScreen`, `Branding`, `EmojiPicker`, `FileUploadButton`, `FilePreviewList`, `DynamicForm`
143
+
144
+ **Forms:** `TextField`, `SelectField`, `RadioField`, `CheckboxField`, `FileUploadField`
528
145
 
529
146
  **Icons:** `SendIcon`, `ChatBubbleIcon`, `CloseIcon`, `MinimizeIcon`, `EmojiIcon`, `AttachmentIcon`, `FileIcon`, `ImageIcon`, `RemoveIcon`, `RestartIcon`
530
147
 
@@ -532,19 +149,31 @@ All internal components are exported for advanced use cases:
532
149
 
533
150
  **Theme utilities:** `resolveTheme`, `buildStyles`, `buildCSSVariables`
534
151
 
152
+ **Built-in plugins:** `analyticsPlugin`, `webhookPlugin`, `persistencePlugin`
153
+
535
154
  ## Development
536
155
 
537
156
  ```bash
538
157
  # Install dependencies
539
158
  bun install
540
159
 
541
- # Run demo
160
+ # Run demo (14 interactive demos)
542
161
  bun run dev
543
162
 
544
163
  # Build library
545
164
  bun run build
546
165
  ```
547
166
 
167
+ ## Contributing
168
+
169
+ Contributions are welcome! Please open an issue or submit a pull request.
170
+
171
+ 1. Fork the repository
172
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
173
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
174
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
175
+ 5. Open a Pull Request
176
+
548
177
  ## License
549
178
 
550
- MIT
179
+ MIT © [Enjoys](https://github.com/enjoys-in)