@cas0570/chat-widget 0.0.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.
Files changed (37) hide show
  1. package/README.md +367 -0
  2. package/dist/components/ChatBubble.d.ts +8 -0
  3. package/dist/components/ChatWidget.d.ts +3 -0
  4. package/dist/components/ChatWindow.d.ts +18 -0
  5. package/dist/components/Icons.d.ts +26 -0
  6. package/dist/components/MarkdownRenderer.d.ts +6 -0
  7. package/dist/components/MessageInput.d.ts +8 -0
  8. package/dist/components/MessageList.d.ts +9 -0
  9. package/dist/components/PopoutWindow.d.ts +25 -0
  10. package/dist/components/ToggleButton.d.ts +9 -0
  11. package/dist/components/TypingIndicator.d.ts +1 -0
  12. package/dist/components/__tests__/ChatBubble.test.d.ts +1 -0
  13. package/dist/components/__tests__/ChatWidget.test.d.ts +1 -0
  14. package/dist/components/__tests__/ChatWindow.test.d.ts +1 -0
  15. package/dist/components/__tests__/Icons.test.d.ts +1 -0
  16. package/dist/components/__tests__/MarkdownRenderer.test.d.ts +1 -0
  17. package/dist/components/__tests__/MessageInput.test.d.ts +1 -0
  18. package/dist/components/__tests__/MessageList.test.d.ts +1 -0
  19. package/dist/components/__tests__/PopoutWindow.test.d.ts +1 -0
  20. package/dist/components/__tests__/ToggleButton.test.d.ts +1 -0
  21. package/dist/components/__tests__/TypingIndicator.test.d.ts +1 -0
  22. package/dist/components/__tests__/index.test.d.ts +1 -0
  23. package/dist/components/index.d.ts +9 -0
  24. package/dist/embed.d.ts +17 -0
  25. package/dist/geoapps-chat-widget.js +1471 -0
  26. package/dist/geoapps-chat-widget.umd.cjs +597 -0
  27. package/dist/hooks/__tests__/useChat.test.d.ts +1 -0
  28. package/dist/hooks/useChat.d.ts +17 -0
  29. package/dist/index.d.ts +9 -0
  30. package/dist/main.d.ts +1 -0
  31. package/dist/style.css +1 -0
  32. package/dist/test/setup.d.ts +1 -0
  33. package/dist/types.d.ts +70 -0
  34. package/dist/utils/__tests__/chatPersistence.test.d.ts +1 -0
  35. package/dist/utils/chatPersistence.d.ts +44 -0
  36. package/dist/utils/index.d.ts +1 -0
  37. package/package.json +80 -0
package/README.md ADDED
@@ -0,0 +1,367 @@
1
+ # GeoApps Chat Widget
2
+
3
+ > Embeddable React chat widget for GeoApps documentation assistant.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ | | |
10
+ | --- | --- |
11
+ | **Type** | Frontend Component Library |
12
+ | **Framework** | React 18 + TypeScript |
13
+ | **Purpose** | Embed chat functionality in any website |
14
+ | **Bundle Formats** | ESM, UMD, IIFE |
15
+
16
+ The Chat Widget provides a floating chat button and dialog that connects to the GeoApps Chat API for RAG-powered documentation assistance.
17
+
18
+ ---
19
+
20
+ ## Quick Start
21
+
22
+ ### NPM Installation
23
+
24
+ ```bash
25
+ npm install @geoapps/chat-widget
26
+ ```
27
+
28
+ ### React Usage
29
+
30
+ ```tsx
31
+ import { ChatWidget } from '@geoapps/chat-widget'
32
+ import '@geoapps/chat-widget/style.css'
33
+
34
+ function App() {
35
+ return (
36
+ <ChatWidget
37
+ apiUrl="https://api.geoapps.nl/api/v1/chat"
38
+ title="GeoApps Help"
39
+ />
40
+ )
41
+ }
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Features
47
+
48
+ | Feature | Description |
49
+ | --------- | ------------- |
50
+ | 💬 **Floating Chat** | Collapsible chat bubble with dialog |
51
+ | 📡 **Streaming** | Real-time response streaming via SSE |
52
+ | 🎨 **Customizable** | Full control over colors, text, positioning |
53
+ | 📱 **Responsive** | Works on desktop and mobile |
54
+ | ♿ **Accessible** | WCAG compliant with keyboard navigation |
55
+ | 🌐 **Framework Agnostic** | Works with any frontend via script tag |
56
+
57
+ ---
58
+
59
+ ## Installation Methods
60
+
61
+ ### Method 1: NPM Package
62
+
63
+ ```bash
64
+ npm install @geoapps/chat-widget
65
+ # or
66
+ yarn add @geoapps/chat-widget
67
+ # or
68
+ pnpm add @geoapps/chat-widget
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Usage
74
+
75
+ ### React Component
76
+
77
+ ```tsx
78
+ import { ChatWidget } from '@geoapps/chat-widget'
79
+ import '@geoapps/chat-widget/style.css'
80
+
81
+ function App() {
82
+ return (
83
+ <ChatWidget
84
+ apiUrl="https://api.geoapps.nl/api/v1/chat"
85
+ title="GeoApps Help"
86
+ subtitle="Vraag me iets over GeoApps"
87
+ primaryColor="#3b82f6"
88
+ position="bottom-right"
89
+ placeholder="Typ je vraag..."
90
+ />
91
+ )
92
+ }
93
+ ```
94
+
95
+ ### Vue.js
96
+
97
+ ```vue
98
+ <template>
99
+ <ChatWidget
100
+ api-url="https://api.geoapps.nl/api/v1/chat"
101
+ title="GeoApps Help"
102
+ />
103
+ </template>
104
+
105
+ <script setup>
106
+ import { ChatWidget } from '@geoapps/chat-widget'
107
+ import '@geoapps/chat-widget/style.css'
108
+ </script>
109
+ ```
110
+
111
+ ### Next.js
112
+
113
+ ```tsx
114
+ 'use client'
115
+
116
+ import dynamic from 'next/dynamic'
117
+ import '@geoapps/chat-widget/style.css'
118
+
119
+ const ChatWidget = dynamic(
120
+ () => import('@geoapps/chat-widget').then(mod => mod.ChatWidget),
121
+ { ssr: false }
122
+ )
123
+
124
+ export default function Page() {
125
+ return <ChatWidget apiUrl="https://api.geoapps.nl/api/v1/chat" />
126
+ }
127
+ ```
128
+
129
+ ---
130
+
131
+ ## API Reference
132
+
133
+ ### Props
134
+
135
+ | Prop | Type | Default | Description |
136
+ | ------ | ------ | --------- | ------------- |
137
+ | `apiUrl` | `string` | **Required** | Chat API endpoint URL |
138
+ | `tenantId` | `string` | `""` | Optional tenant ID for multi-tenant setup |
139
+ | `title` | `string` | `"Chat"` | Dialog header title |
140
+ | `subtitle` | `string` | `""` | Dialog header subtitle |
141
+ | `placeholder` | `string` | `"Typ een bericht..."` | Input placeholder text |
142
+ | `greeting` | `string` | `""` | Initial greeting message |
143
+ | `primaryColor` | `string` | `"#3b82f6"` | Main accent color (hex) or var() |
144
+ | `position` | `Position` | `"bottom-right"` | Widget position |
145
+ | `defaultOpen` | `boolean` | `false` | Default open state |
146
+ | `defaultSize` | `WidgetSize` | `medium` | Default widget size |
147
+ | `headers` | `Record<string, string>` | `""` | Custom headers for API calls |
148
+
149
+ ### Position Options
150
+
151
+ ```typescript
152
+ 'bottom-right'
153
+ 'bottom-left'
154
+ 'top-right'
155
+ 'top-left'
156
+ ```
157
+
158
+ ### Widget Sizes
159
+
160
+ ```typescript
161
+ 'small'
162
+ 'medium'
163
+ 'large'
164
+ 'fullscreen'
165
+ ```
166
+
167
+ ### Events / Callbacks
168
+
169
+ | Prop | Type | Description |
170
+ | ------ | ------ | ------------- |
171
+ | `onOpen` | `() => void` | Called when chat dialog opens |
172
+ | `onClose` | `() => void` | Called when chat dialog closes |
173
+ | `onMessageSent` | `(message: string) => void` | Called when message is sent |
174
+ | `onResponseReceived` | `(response: string) => void` | Called when a response is received |
175
+
176
+ ### Example with Callbacks
177
+
178
+ ```tsx
179
+ <ChatWidget
180
+ apiUrl="https://api.geoapps.nl/api/v1/chat"
181
+ onOpen={() => analytics.track('chat_opened')}
182
+ onClose={() => analytics.track('chat_closed')}
183
+ onMessageSent={(msg) => console.log('Message:', msg)}
184
+ />
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Customization
190
+
191
+ ### Theme Customization
192
+
193
+ ```tsx
194
+ <ChatWidget
195
+ apiUrl="..."
196
+ primaryColor="#10b981" // Green theme
197
+ // CSS variables available:
198
+ // --chat-primary: primaryColor
199
+ // --chat-primary-hover: auto-generated
200
+ // --chat-bg: white
201
+ // --chat-text: #1f2937
202
+ />
203
+ ```
204
+
205
+ ### Custom CSS
206
+
207
+ ```css
208
+ /* Override default styles */
209
+ .geoapps-chat-widget {
210
+ --chat-font-family: 'Inter', sans-serif;
211
+ --chat-border-radius: 16px;
212
+ }
213
+
214
+ .geoapps-chat-bubble {
215
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
216
+ }
217
+
218
+ .geoapps-chat-message--bot {
219
+ background: #f3f4f6;
220
+ }
221
+ ```
222
+
223
+ ### Custom Chat Bubble
224
+
225
+ ```tsx
226
+ import { ChatWidget, ChatBubble } from '@geoapps/chat-widget'
227
+
228
+ // Use custom trigger button
229
+ <ChatWidget
230
+ apiUrl="..."
231
+ renderTrigger={({ isOpen, toggle }) => (
232
+ <button onClick={toggle}>
233
+ {isOpen ? 'Close Chat' : 'Need Help?'}
234
+ </button>
235
+ )}
236
+ />
237
+ ```
238
+
239
+ ---
240
+
241
+ ## Project Structure
242
+
243
+ ```txt
244
+ geoapps-chat-widget/
245
+ ├── src/
246
+ │ ├── index.ts # Package exports
247
+ │ ├── embed.ts # IIFE entry for script tag
248
+ │ ├── components/
249
+ │ │ ├── ChatWidget.tsx # Main widget component
250
+ │ │ ├── ChatBubble.tsx # Floating button
251
+ │ │ ├── ChatDialog.tsx # Chat dialog window
252
+ │ │ ├── ChatMessage.tsx # Message bubble
253
+ │ │ ├── ChatInput.tsx # Text input
254
+ │ │ └── SourceLink.tsx # Source reference
255
+ │ ├── hooks/
256
+ │ │ ├── useChat.ts # Chat logic hook
257
+ │ │ ├── useStream.ts # SSE streaming hook
258
+ │ │ └── useSession.ts # Session persistence
259
+ │ ├── styles/
260
+ │ │ ├── widget.css # Main styles
261
+ │ │ └── variables.css # CSS variables
262
+ │ └── types/
263
+ │ └── index.ts # TypeScript types
264
+ ├── dist/ # Built files
265
+ │ ├── index.js # ESM bundle
266
+ │ ├── index.cjs # CommonJS bundle
267
+ │ ├── embed.iife.js # Script tag bundle
268
+ │ └── style.css # Styles
269
+ ├── package.json
270
+ ├── tsconfig.json
271
+ ├── vite.config.ts # Build configuration
272
+ └── README.md
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Development
278
+
279
+ ### Local Setup
280
+
281
+ ```bash
282
+ # Install dependencies
283
+ npm install
284
+
285
+ # Start development server
286
+ npm run dev
287
+
288
+ # Build library
289
+ npm run build:lib
290
+
291
+ # Run tests
292
+ npm test
293
+
294
+ # Lint code
295
+ npm run lint
296
+
297
+ # Type check
298
+ npm run type-check
299
+ ```
300
+
301
+ ### Testing Locally
302
+
303
+ ```bash
304
+ # Start dev server with demo page
305
+ npm run dev
306
+
307
+ # Open http://localhost:5173/demo.html
308
+ ```
309
+
310
+ ### Publishing
311
+
312
+ ```bash
313
+ # Build production bundle
314
+ npm run build:lib
315
+
316
+ # Publish to npm
317
+ npm publish --access public
318
+ ```
319
+
320
+ ---
321
+
322
+ ## Browser Support
323
+
324
+ | Browser | Version |
325
+ | --------- | --------- |
326
+ | Chrome | 80+ |
327
+ | Firefox | 75+ |
328
+ | Safari | 14+ |
329
+ | Edge | 80+ |
330
+ | Mobile Safari | 14+ |
331
+ | Chrome Android | 80+ |
332
+
333
+ ---
334
+
335
+ ## Troubleshooting
336
+
337
+ | Issue | Solution |
338
+ | ------- | ---------- |
339
+ | Widget not appearing | Check z-index conflicts |
340
+ | CORS errors | Ensure API allows your domain in CORS_ORIGINS |
341
+ | Messages not sending | Verify apiUrl is correct and API is running |
342
+ | Styles not loading | Import the CSS file: `import '@geoapps/chat-widget/style.css'` |
343
+ | SSR errors (Next.js) | Use dynamic import with `ssr: false` |
344
+
345
+ ---
346
+
347
+ ## Accessibility
348
+
349
+ The widget follows WCAG 2.1 guidelines:
350
+
351
+ - ✅ Keyboard navigation (Tab, Enter, Escape)
352
+ - ✅ Focus management
353
+ - ✅ ARIA labels
354
+ - ✅ Color contrast ratios
355
+ - ✅ Screen reader support
356
+
357
+ ---
358
+
359
+ ## Related Documentation
360
+
361
+ - [Main README](https://github.com/geoapps/geoapps-chatbot/) - Repository overview
362
+ - [Chat API](https://github.com/geoapps/geoapps-chat-api/)- Backend service
363
+ - [Doc Indexer](https://github.com/geoapps/geoapps-doc-indexer/) - Index documentation
364
+
365
+ ---
366
+
367
+ Built with ❤️ by [Cas Doorn](https://casdoorn.nl)
@@ -0,0 +1,8 @@
1
+ import { Message } from '../types';
2
+
3
+ interface ChatBubbleProps {
4
+ message: Message;
5
+ primaryColor: string;
6
+ }
7
+ export declare function ChatBubble({ message, primaryColor }: ChatBubbleProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,3 @@
1
+ import { ChatWidgetProps } from '../types';
2
+
3
+ export declare function ChatWidget({ apiUrl, tenantId, title, subtitle, placeholder, greeting, primaryColor, position, defaultOpen, defaultSize, headers, onOpen, onClose, onMessageSent, onResponseReceived, }: ChatWidgetProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { Message, WidgetSize } from '../types';
2
+
3
+ interface ChatWindowProps {
4
+ title: string;
5
+ subtitle: string;
6
+ placeholder: string;
7
+ messages: Message[];
8
+ isLoading: boolean;
9
+ onSendMessage: (content: string) => void;
10
+ onClose: () => void;
11
+ onClear: () => void;
12
+ onSizeChange: (size: WidgetSize) => void;
13
+ onPopout: () => void;
14
+ primaryColor: string;
15
+ size: WidgetSize;
16
+ }
17
+ export declare function ChatWindow({ title, subtitle, placeholder, messages, isLoading, onSendMessage, onClose, onClear, onSizeChange, onPopout, primaryColor, size, }: ChatWindowProps): import("react/jsx-runtime").JSX.Element;
18
+ export {};
@@ -0,0 +1,26 @@
1
+ import { WidgetSize } from '../types';
2
+
3
+ interface ResizeIconProps {
4
+ size: WidgetSize;
5
+ className?: string;
6
+ }
7
+ export declare function ResizeIcon({ size, className }: ResizeIconProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function ExpandIcon({ className }: {
9
+ className?: string;
10
+ }): import("react/jsx-runtime").JSX.Element;
11
+ export declare function ContractIcon({ className }: {
12
+ className?: string;
13
+ }): import("react/jsx-runtime").JSX.Element;
14
+ export declare function PopoutIcon({ className }: {
15
+ className?: string;
16
+ }): import("react/jsx-runtime").JSX.Element;
17
+ export declare function CloseIcon({ className }: {
18
+ className?: string;
19
+ }): import("react/jsx-runtime").JSX.Element;
20
+ export declare function TrashIcon({ className }: {
21
+ className?: string;
22
+ }): import("react/jsx-runtime").JSX.Element;
23
+ export declare function ChatIcon({ className }: {
24
+ className?: string;
25
+ }): import("react/jsx-runtime").JSX.Element;
26
+ export {};
@@ -0,0 +1,6 @@
1
+ interface MarkdownRendererProps {
2
+ content: string;
3
+ className?: string;
4
+ }
5
+ export declare function MarkdownRenderer({ content, className }: MarkdownRendererProps): import("react/jsx-runtime").JSX.Element | null;
6
+ export {};
@@ -0,0 +1,8 @@
1
+ interface MessageInputProps {
2
+ placeholder: string;
3
+ isLoading: boolean;
4
+ onSendMessage: (content: string) => void;
5
+ primaryColor: string;
6
+ }
7
+ export declare function MessageInput({ placeholder, isLoading, onSendMessage, primaryColor }: MessageInputProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,9 @@
1
+ import { Message } from '../types';
2
+
3
+ interface MessageListProps {
4
+ messages: Message[];
5
+ isLoading: boolean;
6
+ primaryColor: string;
7
+ }
8
+ export declare function MessageList({ messages, isLoading, primaryColor }: MessageListProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1,25 @@
1
+ import { Message, WidgetSize } from '../types';
2
+
3
+ interface PopoutConfig {
4
+ apiUrl: string;
5
+ tenantId?: string;
6
+ title: string;
7
+ subtitle: string;
8
+ placeholder: string;
9
+ primaryColor: string;
10
+ sessionId?: string | null;
11
+ messages: Message[];
12
+ headers?: Record<string, string>;
13
+ }
14
+ interface UsePopoutReturn {
15
+ isPoppedOut: boolean;
16
+ openPopout: () => void;
17
+ closePopout: () => void;
18
+ focusPopout: () => void;
19
+ }
20
+ /**
21
+ * Hook to manage the popout window state
22
+ */
23
+ export declare function usePopout(config: PopoutConfig, size: WidgetSize, onPopoutClose?: () => void): UsePopoutReturn;
24
+ export declare function ChatWindowStandalone(): null;
25
+ export {};
@@ -0,0 +1,9 @@
1
+ interface ToggleButtonProps {
2
+ isOpen: boolean;
3
+ onClick: () => void;
4
+ primaryColor: string;
5
+ hasUnread?: boolean;
6
+ isPoppedOut?: boolean;
7
+ }
8
+ export declare function ToggleButton({ isOpen, onClick, primaryColor, hasUnread, isPoppedOut }: ToggleButtonProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1 @@
1
+ export declare function TypingIndicator(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ export { ChatWidget } from './ChatWidget';
2
+ export { ChatWindow } from './ChatWindow';
3
+ export { ChatBubble } from './ChatBubble';
4
+ export { MessageList } from './MessageList';
5
+ export { MessageInput } from './MessageInput';
6
+ export { ToggleButton } from './ToggleButton';
7
+ export { MarkdownRenderer } from './MarkdownRenderer';
8
+ export { usePopout } from './PopoutWindow';
9
+ export { ResizeIcon, ExpandIcon, ContractIcon, PopoutIcon, CloseIcon, TrashIcon, ChatIcon } from './Icons';
@@ -0,0 +1,17 @@
1
+ import { ChatWidgetProps } from './types';
2
+
3
+ /**
4
+ * Embed the GeoApps Chat Widget into a page
5
+ *
6
+ * @example
7
+ * // Using as a script tag:
8
+ * <script src="https://cdn.example.com/geoapps-chat-widget.js"></script>
9
+ * <script>
10
+ * GeoAppsChatWidget.embed({
11
+ * apiUrl: 'https://api.geoapps.nl/chat',
12
+ * title: 'GeoApps Help',
13
+ * greeting: 'Hello! How can I help you with GeoApps today?'
14
+ * });
15
+ * </script>
16
+ */
17
+ export declare function embedChatWidget(props: ChatWidgetProps, containerId?: string): () => void;