@kite-copilot/chat-panel 0.2.1 → 0.2.3
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 +298 -360
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
# @kite-copilot/chat-panel
|
|
2
2
|
|
|
3
|
-
An AI-powered chat panel SDK for embedding intelligent chat assistants. This package provides a
|
|
3
|
+
An AI-powered chat panel SDK for embedding intelligent chat assistants. This package provides a **side panel** interface that integrates with any AI backend agent. The panel slides in from the right edge and automatically adjusts page content - no layout changes required.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
7
|
+
- **Side Panel UX**: Slides in from the right edge, pushes page content (no overlay)
|
|
8
|
+
- **Zero-Config**: Drop-in integration - no layout changes required from host apps
|
|
9
|
+
- **AI-Powered Chat**: Connects to your AI backend agent for intelligent responses
|
|
10
|
+
- **CSV Bulk Operations**: Upload CSV files for bulk data processing
|
|
11
|
+
- **Interactive Guides**: Built-in guided tours with animated cursor
|
|
12
|
+
- **Dynamic Starting Questions**: Customizable per-user questions from backend
|
|
13
|
+
- **Customizable Themes**: Light and dark mode support
|
|
14
|
+
- **Responsive Design**: Works on desktop and mobile
|
|
15
|
+
- **Easy Integration**: Programmatic API or React component
|
|
16
|
+
- **PWA-Ready**: Fully bundled by your build tool, no CDN required
|
|
17
|
+
- **Offline-Safe**: Works with service workers and precaching
|
|
15
18
|
|
|
16
19
|
## Installation
|
|
17
20
|
|
|
@@ -47,129 +50,233 @@ const chat = createKiteChat({
|
|
|
47
50
|
orgId: 'org-456',
|
|
48
51
|
agentUrl: 'https://your-api.example.com',
|
|
49
52
|
onNavigate: (page, subtab) => {
|
|
50
|
-
// Handle navigation requests from the chat
|
|
51
53
|
router.push(`/${page}${subtab ? `?tab=${subtab}` : ''}`);
|
|
52
54
|
},
|
|
53
|
-
onActionComplete: (actionType, data) => {
|
|
54
|
-
console.log('Action completed:', actionType, data);
|
|
55
|
-
},
|
|
56
55
|
});
|
|
57
56
|
|
|
58
|
-
// Mount
|
|
59
|
-
chat.mount(
|
|
57
|
+
// Mount - that's it! No container needed, panel handles its own positioning
|
|
58
|
+
chat.mount(document.body);
|
|
59
|
+
|
|
60
|
+
// Control the panel programmatically
|
|
61
|
+
chat.open(); // Open the side panel
|
|
62
|
+
chat.close(); // Close the side panel
|
|
63
|
+
chat.toggle(); // Toggle open/closed
|
|
64
|
+
|
|
65
|
+
// Check state
|
|
66
|
+
if (chat.isOpen()) {
|
|
67
|
+
console.log('Panel is open');
|
|
68
|
+
}
|
|
60
69
|
|
|
61
|
-
// Update
|
|
70
|
+
// Update context as user navigates
|
|
62
71
|
chat.setCurrentPage('settings');
|
|
63
|
-
chat.updateConfig({ theme: 'dark' });
|
|
64
72
|
|
|
65
73
|
// Clean up when done
|
|
66
74
|
chat.unmount();
|
|
67
75
|
```
|
|
68
76
|
|
|
69
|
-
###
|
|
77
|
+
### Vue.js
|
|
70
78
|
|
|
71
|
-
|
|
79
|
+
Create a composable for reusable chat functionality:
|
|
72
80
|
|
|
73
81
|
```ts
|
|
74
|
-
|
|
82
|
+
// composables/useKiteChat.ts
|
|
83
|
+
import { ref, onMounted, onUnmounted } from 'vue';
|
|
84
|
+
import { createKiteChat, type KiteChatInstance, type KiteChatConfig } from '@kite-copilot/chat-panel';
|
|
75
85
|
import '@kite-copilot/chat-panel/style.css';
|
|
76
86
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
orgId: 'org-456',
|
|
81
|
-
});
|
|
87
|
+
export function useKiteChat(config: KiteChatConfig) {
|
|
88
|
+
const chat = ref<KiteChatInstance | null>(null);
|
|
89
|
+
const isOpen = ref(false);
|
|
82
90
|
|
|
83
|
-
|
|
84
|
-
chat.
|
|
85
|
-
|
|
91
|
+
onMounted(() => {
|
|
92
|
+
chat.value = createKiteChat({
|
|
93
|
+
...config,
|
|
94
|
+
onNavigate: config.onNavigate,
|
|
95
|
+
});
|
|
96
|
+
chat.value.mount(document.body);
|
|
97
|
+
});
|
|
86
98
|
|
|
87
|
-
|
|
99
|
+
onUnmounted(() => {
|
|
100
|
+
chat.value?.unmount();
|
|
101
|
+
});
|
|
88
102
|
|
|
89
|
-
|
|
103
|
+
const open = () => {
|
|
104
|
+
chat.value?.open();
|
|
105
|
+
isOpen.value = true;
|
|
106
|
+
};
|
|
90
107
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
108
|
+
const close = () => {
|
|
109
|
+
chat.value?.close();
|
|
110
|
+
isOpen.value = false;
|
|
111
|
+
};
|
|
94
112
|
|
|
95
|
-
|
|
96
|
-
|
|
113
|
+
const toggle = () => {
|
|
114
|
+
chat.value?.toggle();
|
|
115
|
+
isOpen.value = !isOpen.value;
|
|
116
|
+
};
|
|
97
117
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
);
|
|
118
|
+
const setCurrentPage = (page: string) => {
|
|
119
|
+
chat.value?.setCurrentPage(page);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
return { isOpen, open, close, toggle, setCurrentPage };
|
|
104
123
|
}
|
|
105
124
|
```
|
|
106
125
|
|
|
107
|
-
|
|
126
|
+
Use in your App.vue or any component:
|
|
127
|
+
|
|
128
|
+
```vue
|
|
129
|
+
<!-- App.vue -->
|
|
130
|
+
<script setup lang="ts">
|
|
131
|
+
import { useKiteChat } from './composables/useKiteChat';
|
|
132
|
+
import { useRouter } from 'vue-router';
|
|
133
|
+
|
|
134
|
+
const router = useRouter();
|
|
135
|
+
|
|
136
|
+
const { open, close, toggle, setCurrentPage } = useKiteChat({
|
|
137
|
+
userId: 'user-123',
|
|
138
|
+
orgId: 'org-456',
|
|
139
|
+
agentUrl: 'https://your-api.example.com',
|
|
140
|
+
onNavigate: (page, subtab) => {
|
|
141
|
+
router.push(`/${page}${subtab ? `?tab=${subtab}` : ''}`);
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Update context when route changes
|
|
146
|
+
router.afterEach((to) => {
|
|
147
|
+
setCurrentPage(to.name as string);
|
|
148
|
+
});
|
|
149
|
+
</script>
|
|
108
150
|
|
|
109
|
-
|
|
151
|
+
<template>
|
|
152
|
+
<div>
|
|
153
|
+
<button @click="toggle">Toggle Help Panel</button>
|
|
154
|
+
<!-- Your app content -->
|
|
155
|
+
<router-view />
|
|
156
|
+
</div>
|
|
157
|
+
</template>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Or initialize directly in main.ts for app-wide availability:
|
|
110
161
|
|
|
111
162
|
```ts
|
|
112
163
|
// main.ts
|
|
164
|
+
import { createApp } from 'vue';
|
|
113
165
|
import { createKiteChat } from '@kite-copilot/chat-panel';
|
|
114
166
|
import '@kite-copilot/chat-panel/style.css';
|
|
115
|
-
import
|
|
167
|
+
import App from './App.vue';
|
|
168
|
+
import router from './router';
|
|
116
169
|
|
|
117
|
-
const
|
|
170
|
+
const app = createApp(App);
|
|
171
|
+
app.use(router);
|
|
172
|
+
app.mount('#app');
|
|
118
173
|
|
|
174
|
+
// Initialize chat after Vue app is mounted
|
|
119
175
|
const chat = createKiteChat({
|
|
120
176
|
userId: 'user-123',
|
|
121
177
|
orgId: 'org-456',
|
|
178
|
+
agentUrl: 'https://your-api.example.com',
|
|
122
179
|
onNavigate: (page) => router.push(`/${page}`),
|
|
123
180
|
});
|
|
181
|
+
chat.mount(document.body);
|
|
124
182
|
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
chat.mount('#kite-chat');
|
|
183
|
+
// Expose globally if needed
|
|
184
|
+
window.kiteChat = chat;
|
|
128
185
|
```
|
|
129
186
|
|
|
130
|
-
###
|
|
187
|
+
### React Component
|
|
131
188
|
|
|
132
|
-
|
|
133
|
-
// chat.service.ts
|
|
134
|
-
import { Injectable, OnDestroy } from '@angular/core';
|
|
135
|
-
import { createKiteChat, KiteChatInstance } from '@kite-copilot/chat-panel';
|
|
189
|
+
For React applications, use the `ChatPanelWithToggle` component:
|
|
136
190
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
191
|
+
```tsx
|
|
192
|
+
import { ChatPanelWithToggle } from '@kite-copilot/chat-panel';
|
|
193
|
+
import '@kite-copilot/chat-panel/style.css';
|
|
140
194
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
195
|
+
function App() {
|
|
196
|
+
return (
|
|
197
|
+
<>
|
|
198
|
+
<YourExistingApp />
|
|
199
|
+
{/* Just add this - no layout changes needed */}
|
|
200
|
+
<ChatPanelWithToggle
|
|
201
|
+
agentUrl="https://your-api.example.com"
|
|
202
|
+
onNavigate={(page) => router.push(`/${page}`)}
|
|
203
|
+
/>
|
|
204
|
+
</>
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
```
|
|
148
208
|
|
|
149
|
-
|
|
150
|
-
this.chat.mount(container);
|
|
151
|
-
}
|
|
209
|
+
For controlled mode:
|
|
152
210
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
211
|
+
```tsx
|
|
212
|
+
import { useState } from 'react';
|
|
213
|
+
import { ChatPanelWithToggle } from '@kite-copilot/chat-panel';
|
|
214
|
+
|
|
215
|
+
function App() {
|
|
216
|
+
const [isPanelOpen, setIsPanelOpen] = useState(false);
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<>
|
|
220
|
+
<button onClick={() => setIsPanelOpen(true)}>Open Help</button>
|
|
221
|
+
<ChatPanelWithToggle
|
|
222
|
+
isOpen={isPanelOpen}
|
|
223
|
+
onOpenChange={setIsPanelOpen}
|
|
224
|
+
agentUrl="https://your-api.example.com"
|
|
225
|
+
/>
|
|
226
|
+
</>
|
|
227
|
+
);
|
|
156
228
|
}
|
|
157
229
|
```
|
|
158
230
|
|
|
159
|
-
|
|
231
|
+
## How It Works
|
|
160
232
|
|
|
161
|
-
|
|
162
|
-
<div id="chat-container"></div>
|
|
163
|
-
<script type="module">
|
|
164
|
-
import { createKiteChat } from './node_modules/@kite-copilot/chat-panel/dist/index.js';
|
|
233
|
+
The side panel uses fixed positioning and automatically manages the body's `padding-right`:
|
|
165
234
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
235
|
+
```
|
|
236
|
+
┌─────────────────────────────────┐ ┌────────────────────────┬────────┐
|
|
237
|
+
│ │ │ │ │
|
|
238
|
+
│ │ │ │ Side │
|
|
239
|
+
│ Your Page Content │ → │ Your Page Content │ Panel │
|
|
240
|
+
│ │ │ (shifted left) │ │
|
|
241
|
+
│ [◀] │ │ [▶] │ │
|
|
242
|
+
└─────────────────────────────────┘ └────────────────────────┴────────┘
|
|
243
|
+
Panel Closed Panel Open
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
- **Closed**: Only the toggle arrow (◀) is visible on the right edge
|
|
247
|
+
- **Open**: Panel slides in, toggle becomes (▶), body gets `padding-right: 400px`
|
|
248
|
+
- **No overlays**: Content is pushed, not covered
|
|
249
|
+
|
|
250
|
+
## Dynamic Starting Questions
|
|
251
|
+
|
|
252
|
+
The panel shows suggested questions when empty. These can be customized per-user:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
// Option 1: Pass questions directly
|
|
256
|
+
const chat = createKiteChat({
|
|
257
|
+
userId: 'user-123',
|
|
258
|
+
orgId: 'org-456',
|
|
259
|
+
startingQuestions: [
|
|
260
|
+
{ id: '1', label: 'Changing layouts', prompt: 'How do I customize the layout?' },
|
|
261
|
+
{ id: '2', label: 'Bulk uploads', prompt: 'How do I upload data in bulk?' },
|
|
262
|
+
{ id: '3', label: 'Example setups', prompt: 'Show me example configurations' },
|
|
263
|
+
],
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// Option 2: Fetch from backend (per-user)
|
|
267
|
+
const chat = createKiteChat({
|
|
268
|
+
userId: 'user-123',
|
|
269
|
+
orgId: 'org-456',
|
|
270
|
+
startingQuestionsEndpoint: '/api/user/starting-questions',
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The endpoint should return:
|
|
275
|
+
```json
|
|
276
|
+
[
|
|
277
|
+
{ "id": "1", "label": "Question label", "prompt": "Full prompt to send" },
|
|
278
|
+
{ "id": "2", "label": "Another question", "prompt": "Another prompt" }
|
|
279
|
+
]
|
|
173
280
|
```
|
|
174
281
|
|
|
175
282
|
## API Reference
|
|
@@ -187,6 +294,8 @@ Creates a new chat instance with explicit lifecycle control.
|
|
|
187
294
|
| `agentUrl` | `string` | No | Backend agent API URL |
|
|
188
295
|
| `currentPage` | `string` | No | Current page context |
|
|
189
296
|
| `theme` | `'light' \| 'dark' \| 'system'` | No | Theme preference |
|
|
297
|
+
| `startingQuestions` | `StartingQuestion[]` | No | Custom starting questions |
|
|
298
|
+
| `startingQuestionsEndpoint` | `string` | No | URL to fetch per-user questions |
|
|
190
299
|
| `onNavigate` | `(page: string, subtab?: string) => void` | No | Navigation callback |
|
|
191
300
|
| `onActionComplete` | `(actionType: string, data: any) => void` | No | Action completion callback |
|
|
192
301
|
|
|
@@ -194,110 +303,112 @@ Creates a new chat instance with explicit lifecycle control.
|
|
|
194
303
|
|
|
195
304
|
| Method | Description |
|
|
196
305
|
|--------|-------------|
|
|
197
|
-
| `mount(container)` | Mount the chat widget
|
|
306
|
+
| `mount(container)` | Mount the chat widget (container is just a React mount point) |
|
|
198
307
|
| `unmount()` | Unmount and clean up the chat widget |
|
|
308
|
+
| `open()` | Open the side panel |
|
|
309
|
+
| `close()` | Close the side panel |
|
|
310
|
+
| `toggle()` | Toggle the panel open/closed |
|
|
311
|
+
| `isOpen()` | Check if the panel is currently open |
|
|
199
312
|
| `setCurrentPage(page)` | Update the current page context |
|
|
200
313
|
| `updateConfig(config)` | Update configuration options |
|
|
201
314
|
| `isMounted()` | Check if the widget is currently mounted |
|
|
202
315
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
## React Component API
|
|
316
|
+
### ChatPanelWithToggle (React)
|
|
206
317
|
|
|
207
|
-
|
|
318
|
+
The recommended React component with integrated toggle button.
|
|
208
319
|
|
|
209
320
|
```tsx
|
|
210
|
-
import {
|
|
211
|
-
|
|
321
|
+
import { ChatPanelWithToggle } from '@kite-copilot/chat-panel';
|
|
322
|
+
```
|
|
212
323
|
|
|
213
|
-
|
|
214
|
-
// Get the current user from your authentication system
|
|
215
|
-
const { userId, orgId } = useAuth()
|
|
324
|
+
#### Props
|
|
216
325
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
326
|
+
| Prop | Type | Default | Description |
|
|
327
|
+
|------|------|---------|-------------|
|
|
328
|
+
| `agentUrl` | `string` | `localhost:5002` | Backend agent URL |
|
|
329
|
+
| `currentPage` | `string` | - | Current page for context |
|
|
330
|
+
| `defaultOpen` | `boolean` | `false` | Initial open state (uncontrolled) |
|
|
331
|
+
| `isOpen` | `boolean` | - | Controlled open state |
|
|
332
|
+
| `onOpenChange` | `(isOpen: boolean) => void` | - | Called when open state changes |
|
|
333
|
+
| `startingQuestions` | `StartingQuestion[]` | - | Custom starting questions |
|
|
334
|
+
| `startingQuestionsEndpoint` | `string` | - | URL to fetch questions |
|
|
335
|
+
| `onNavigate` | `(page, subtab?) => void` | - | Navigation callback |
|
|
336
|
+
| `onActionComplete` | `(type, data) => void` | - | Action completion callback |
|
|
225
337
|
|
|
226
|
-
###
|
|
338
|
+
### Low-Level Components
|
|
339
|
+
|
|
340
|
+
For advanced customization, you can use the individual components:
|
|
227
341
|
|
|
228
342
|
```tsx
|
|
229
|
-
import { ChatPanel,
|
|
230
|
-
import '@kite-copilot/chat-panel/style.css'
|
|
231
|
-
import { useRouter } from 'next/navigation'
|
|
343
|
+
import { ChatPanel, PanelToggle } from '@kite-copilot/chat-panel';
|
|
232
344
|
|
|
233
|
-
function
|
|
234
|
-
const
|
|
235
|
-
const { userId, orgId } = useAuth() // Your auth system
|
|
236
|
-
const [currentPage, setCurrentPage] = useState('dashboard')
|
|
345
|
+
function CustomPanel() {
|
|
346
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
237
347
|
|
|
238
348
|
return (
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
position: 'bottom-right',
|
|
245
|
-
}}
|
|
246
|
-
>
|
|
247
|
-
<YourApp />
|
|
248
|
-
<ChatPanel
|
|
249
|
-
currentPage={currentPage}
|
|
250
|
-
onNavigate={(page, subtab) => {
|
|
251
|
-
setCurrentPage(page)
|
|
252
|
-
router.push(`/${page}${subtab ? `?tab=${subtab}` : ''}`)
|
|
253
|
-
}}
|
|
254
|
-
onActionComplete={(actionType, data) => {
|
|
255
|
-
console.log('Action completed:', actionType, data)
|
|
256
|
-
// Refresh your data or perform other side effects
|
|
257
|
-
}}
|
|
258
|
-
/>
|
|
259
|
-
</ChatPanelProvider>
|
|
260
|
-
)
|
|
349
|
+
<>
|
|
350
|
+
<PanelToggle isOpen={isOpen} onClick={() => setIsOpen(!isOpen)} />
|
|
351
|
+
<ChatPanel isOpen={isOpen} onClose={() => setIsOpen(false)} />
|
|
352
|
+
</>
|
|
353
|
+
);
|
|
261
354
|
}
|
|
262
355
|
```
|
|
263
356
|
|
|
264
|
-
##
|
|
357
|
+
## Framework Examples
|
|
265
358
|
|
|
266
|
-
###
|
|
359
|
+
### Angular
|
|
267
360
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
361
|
+
```ts
|
|
362
|
+
import { Injectable, OnDestroy } from '@angular/core';
|
|
363
|
+
import { createKiteChat, KiteChatInstance } from '@kite-copilot/chat-panel';
|
|
364
|
+
|
|
365
|
+
@Injectable({ providedIn: 'root' })
|
|
366
|
+
export class ChatService implements OnDestroy {
|
|
367
|
+
private chat: KiteChatInstance;
|
|
368
|
+
|
|
369
|
+
constructor(private router: Router) {
|
|
370
|
+
this.chat = createKiteChat({
|
|
371
|
+
userId: 'user-123',
|
|
372
|
+
orgId: 'org-456',
|
|
373
|
+
onNavigate: (page) => this.router.navigate([page]),
|
|
374
|
+
});
|
|
375
|
+
this.chat.mount(document.body);
|
|
376
|
+
}
|
|
271
377
|
|
|
272
|
-
|
|
378
|
+
open() { this.chat.open(); }
|
|
379
|
+
close() { this.chat.close(); }
|
|
380
|
+
toggle() { this.chat.toggle(); }
|
|
273
381
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
| `theme` | `'light' \| 'dark' \| 'system'` | `'light'` | Theme preference |
|
|
280
|
-
| `position` | `'bottom-right' \| 'bottom-left' \| 'custom'` | `'bottom-right'` | Panel position |
|
|
281
|
-
| `guides` | `Record<string, GuideWithSteps>` | - | Custom interactive guides |
|
|
282
|
-
| `folders` | `Folder[]` | - | Custom help topic folders |
|
|
283
|
-
| `showDefaultFolders` | `boolean` | `true` | Show default help topics |
|
|
284
|
-
| `enableGuideCursor` | `boolean` | `true` | Enable animated guide cursor |
|
|
285
|
-
| `className` | `string` | - | Custom CSS class |
|
|
382
|
+
ngOnDestroy() {
|
|
383
|
+
this.chat.unmount();
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
```
|
|
286
387
|
|
|
287
|
-
###
|
|
388
|
+
### Next.js App Router
|
|
288
389
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
390
|
+
```tsx
|
|
391
|
+
// app/layout.tsx
|
|
392
|
+
import { ChatPanelWithToggle } from '@kite-copilot/chat-panel';
|
|
393
|
+
import '@kite-copilot/chat-panel/style.css';
|
|
394
|
+
|
|
395
|
+
export default function RootLayout({ children }) {
|
|
396
|
+
return (
|
|
397
|
+
<html>
|
|
398
|
+
<body>
|
|
399
|
+
{children}
|
|
400
|
+
<ChatPanelWithToggle
|
|
401
|
+
agentUrl={process.env.NEXT_PUBLIC_AGENT_URL}
|
|
402
|
+
/>
|
|
403
|
+
</body>
|
|
404
|
+
</html>
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
```
|
|
297
408
|
|
|
298
409
|
## Backend Integration
|
|
299
410
|
|
|
300
|
-
The ChatPanel expects your backend agent to expose the following SSE endpoints.
|
|
411
|
+
The ChatPanel expects your backend agent to expose the following SSE endpoints.
|
|
301
412
|
|
|
302
413
|
### `/chat/stream` (POST)
|
|
303
414
|
|
|
@@ -326,117 +437,33 @@ CSV file upload endpoint for bulk operations.
|
|
|
326
437
|
|
|
327
438
|
**Request:** FormData with `file`, `message`, `session_id`, `user_id`, `org_id`, `current_page`
|
|
328
439
|
|
|
329
|
-
**SSE Events:**
|
|
330
|
-
- `preview`: CSV preview with row count and sample data
|
|
331
|
-
- `error`: Error messages
|
|
332
|
-
|
|
333
440
|
### `/chat/bulk/confirm` (POST)
|
|
334
441
|
|
|
335
442
|
Confirm and execute bulk operation.
|
|
336
443
|
|
|
337
|
-
|
|
338
|
-
```json
|
|
339
|
-
{
|
|
340
|
-
"session_id": "uuid",
|
|
341
|
-
"user_id": "user-123",
|
|
342
|
-
"org_id": "org-456",
|
|
343
|
-
"bulk_session_id": "bulk-uuid"
|
|
344
|
-
}
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
**SSE Events:**
|
|
348
|
-
- `progress`: Row-by-row processing updates
|
|
349
|
-
- `summary`: Final results with success/failure counts
|
|
350
|
-
- `error`: Error messages
|
|
351
|
-
|
|
352
|
-
## Custom Guides
|
|
353
|
-
|
|
354
|
-
You can add custom interactive guides:
|
|
355
|
-
|
|
356
|
-
```tsx
|
|
357
|
-
const customGuides = {
|
|
358
|
-
'my-guide': {
|
|
359
|
-
id: 'my-guide',
|
|
360
|
-
title: 'My Custom Guide',
|
|
361
|
-
steps: [
|
|
362
|
-
{
|
|
363
|
-
text: 'Step 1: Click the button below',
|
|
364
|
-
navigation: { page: 'settings' },
|
|
365
|
-
cursorTarget: {
|
|
366
|
-
selector: '[data-testid="my-button"]',
|
|
367
|
-
onClick: true
|
|
368
|
-
}
|
|
369
|
-
},
|
|
370
|
-
// More steps...
|
|
371
|
-
]
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
<ChatPanelProvider config={{ userId, orgId, guides: customGuides }}>
|
|
376
|
-
...
|
|
377
|
-
</ChatPanelProvider>
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
## Custom Help Topics
|
|
444
|
+
### `/api/user/starting-questions` (GET) - Optional
|
|
381
445
|
|
|
382
|
-
|
|
446
|
+
Return per-user starting questions.
|
|
383
447
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
topics: [
|
|
390
|
-
{
|
|
391
|
-
id: 'contact',
|
|
392
|
-
label: 'Contact Us',
|
|
393
|
-
prompt: 'How can I contact support?'
|
|
394
|
-
}
|
|
395
|
-
]
|
|
396
|
-
}
|
|
448
|
+
**Response:**
|
|
449
|
+
```json
|
|
450
|
+
[
|
|
451
|
+
{ "id": "1", "label": "Changing layouts", "prompt": "How do I change the layout?" },
|
|
452
|
+
{ "id": "2", "label": "Bulk uploads", "prompt": "How do I upload in bulk?" }
|
|
397
453
|
]
|
|
398
|
-
|
|
399
|
-
<ChatPanelProvider config={{ userId, orgId, folders: customFolders }}>
|
|
400
|
-
...
|
|
401
|
-
</ChatPanelProvider>
|
|
402
454
|
```
|
|
403
455
|
|
|
404
456
|
## Styling
|
|
405
457
|
|
|
406
458
|
### Using the Default Styles
|
|
407
459
|
|
|
408
|
-
Import the CSS file in your app:
|
|
409
|
-
|
|
410
460
|
```tsx
|
|
411
|
-
import '@kite-copilot/chat-panel/style.css'
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
### With Tailwind CSS
|
|
415
|
-
|
|
416
|
-
If you're using Tailwind, extend your config with our preset:
|
|
417
|
-
|
|
418
|
-
```js
|
|
419
|
-
// tailwind.config.js
|
|
420
|
-
module.exports = {
|
|
421
|
-
content: [
|
|
422
|
-
// ... your paths
|
|
423
|
-
'./node_modules/@kite-copilot/chat-panel/dist/**/*.{js,mjs}'
|
|
424
|
-
],
|
|
425
|
-
theme: {
|
|
426
|
-
extend: {
|
|
427
|
-
colors: {
|
|
428
|
-
background: "var(--background)",
|
|
429
|
-
foreground: "var(--foreground)",
|
|
430
|
-
// ... other theme colors
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
461
|
+
import '@kite-copilot/chat-panel/style.css';
|
|
435
462
|
```
|
|
436
463
|
|
|
437
464
|
### CSS Variables
|
|
438
465
|
|
|
439
|
-
|
|
466
|
+
Override theme variables in your CSS:
|
|
440
467
|
|
|
441
468
|
```css
|
|
442
469
|
:root {
|
|
@@ -444,13 +471,11 @@ The component uses CSS variables for theming. Override them in your CSS:
|
|
|
444
471
|
--foreground: oklch(0.145 0 0);
|
|
445
472
|
--primary: oklch(0.205 0 0);
|
|
446
473
|
--primary-foreground: oklch(0.985 0 0);
|
|
447
|
-
/* ... more variables */
|
|
448
474
|
}
|
|
449
475
|
|
|
450
476
|
.dark {
|
|
451
477
|
--background: oklch(0.145 0 0);
|
|
452
478
|
--foreground: oklch(0.985 0 0);
|
|
453
|
-
/* ... dark mode overrides */
|
|
454
479
|
}
|
|
455
480
|
```
|
|
456
481
|
|
|
@@ -460,126 +485,39 @@ Full TypeScript support with exported types:
|
|
|
460
485
|
|
|
461
486
|
```tsx
|
|
462
487
|
import type {
|
|
463
|
-
// Programmatic API types
|
|
464
488
|
KiteChatConfig,
|
|
465
489
|
KiteChatInstance,
|
|
466
|
-
// React component types
|
|
467
|
-
ChatPanelConfig,
|
|
468
490
|
ChatPanelProps,
|
|
491
|
+
ChatPanelWithToggleProps,
|
|
492
|
+
PanelToggleProps,
|
|
493
|
+
StartingQuestion,
|
|
469
494
|
ActionType,
|
|
470
495
|
ActionData,
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
} from '@kite-copilot/chat-panel'
|
|
496
|
+
Page,
|
|
497
|
+
SettingsTab,
|
|
498
|
+
} from '@kite-copilot/chat-panel';
|
|
475
499
|
```
|
|
476
500
|
|
|
477
|
-
##
|
|
501
|
+
## Migration from Overlay Version
|
|
478
502
|
|
|
479
|
-
|
|
503
|
+
If upgrading from a previous version with overlay/floating panel:
|
|
480
504
|
|
|
481
|
-
|
|
482
|
-
|
|
505
|
+
1. **Remove layout changes**: You no longer need flex containers or special positioning
|
|
506
|
+
2. **Update imports**: Use `ChatPanelWithToggle` instead of `ChatPanel` for the full experience
|
|
507
|
+
3. **Update API calls**: Use `open()`/`close()`/`toggle()` instead of managing `isCollapsed` state
|
|
483
508
|
|
|
484
509
|
```tsx
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
```tsx
|
|
495
|
-
// app/providers.tsx
|
|
496
|
-
'use client'
|
|
497
|
-
|
|
498
|
-
import { ChatPanelProvider } from '@kite-copilot/chat-panel'
|
|
499
|
-
import { useAuth } from './auth' // Your auth provider
|
|
500
|
-
|
|
501
|
-
export function Providers({ children }) {
|
|
502
|
-
const { userId, orgId } = useAuth()
|
|
503
|
-
|
|
504
|
-
return (
|
|
505
|
-
<ChatPanelProvider
|
|
506
|
-
config={{
|
|
507
|
-
userId,
|
|
508
|
-
orgId,
|
|
509
|
-
}}
|
|
510
|
-
>
|
|
511
|
-
{children}
|
|
512
|
-
</ChatPanelProvider>
|
|
513
|
-
)
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// app/layout.tsx
|
|
517
|
-
import { Providers } from './providers'
|
|
518
|
-
import '@kite-copilot/chat-panel/style.css'
|
|
519
|
-
|
|
520
|
-
export default function RootLayout({ children }) {
|
|
521
|
-
return (
|
|
522
|
-
<html>
|
|
523
|
-
<body>
|
|
524
|
-
<Providers>{children}</Providers>
|
|
525
|
-
</body>
|
|
526
|
-
</html>
|
|
527
|
-
)
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// app/page.tsx
|
|
531
|
-
'use client'
|
|
532
|
-
|
|
533
|
-
import { ChatPanel } from '@kite-copilot/chat-panel'
|
|
534
|
-
|
|
535
|
-
export default function Page() {
|
|
536
|
-
return (
|
|
537
|
-
<main>
|
|
538
|
-
<h1>My App</h1>
|
|
539
|
-
<ChatPanel currentPage="home" />
|
|
540
|
-
</main>
|
|
541
|
-
)
|
|
542
|
-
}
|
|
543
|
-
```
|
|
544
|
-
|
|
545
|
-
### React with React Router
|
|
546
|
-
|
|
547
|
-
```tsx
|
|
548
|
-
import { BrowserRouter, useLocation, useNavigate } from 'react-router-dom'
|
|
549
|
-
import { ChatPanel, ChatPanelProvider } from '@kite-copilot/chat-panel'
|
|
550
|
-
import '@kite-copilot/chat-panel/style.css'
|
|
551
|
-
import { useAuth } from './auth' // Your auth provider
|
|
552
|
-
|
|
553
|
-
function ChatPanelWithRouter() {
|
|
554
|
-
const location = useLocation()
|
|
555
|
-
const navigate = useNavigate()
|
|
556
|
-
const currentPage = location.pathname.slice(1) || 'dashboard'
|
|
557
|
-
|
|
558
|
-
return (
|
|
559
|
-
<ChatPanel
|
|
560
|
-
currentPage={currentPage}
|
|
561
|
-
onNavigate={(page) => navigate(`/${page}`)}
|
|
562
|
-
/>
|
|
563
|
-
)
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
function App() {
|
|
567
|
-
const { userId, orgId } = useAuth()
|
|
568
|
-
|
|
569
|
-
return (
|
|
570
|
-
<BrowserRouter>
|
|
571
|
-
<ChatPanelProvider config={{ userId, orgId }}>
|
|
572
|
-
<Routes>
|
|
573
|
-
{/* Your routes */}
|
|
574
|
-
</Routes>
|
|
575
|
-
<ChatPanelWithRouter />
|
|
576
|
-
</ChatPanelProvider>
|
|
577
|
-
</BrowserRouter>
|
|
578
|
-
)
|
|
579
|
-
}
|
|
510
|
+
// Before (overlay)
|
|
511
|
+
<div style={{ display: 'flex' }}>
|
|
512
|
+
<main style={{ flex: 1 }}>...</main>
|
|
513
|
+
<div id="chat-container" />
|
|
514
|
+
</div>
|
|
515
|
+
|
|
516
|
+
// After (side panel)
|
|
517
|
+
<main>...</main>
|
|
518
|
+
<ChatPanelWithToggle />
|
|
580
519
|
```
|
|
581
520
|
|
|
582
521
|
## License
|
|
583
522
|
|
|
584
|
-
MIT ©
|
|
585
|
-
|
|
523
|
+
MIT © Kite
|