@vezlo/assistant-chat 1.1.1 → 1.2.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
@@ -20,6 +20,8 @@ A complete chat widget solution with both a React component library and standalo
20
20
  - **Embed Code Generator**: Get ready-to-use embed codes
21
21
  - **Docker Support**: Easy deployment with Docker Compose
22
22
  - **Vercel Ready**: One-click deployment to Vercel
23
+ - **Shared Layout**: `MainLayout` + `Header` provide a consistent, Vercel-style shell across every page
24
+ - **Auth-Ready Context**: `AppProvider` exposes user/workspace state, token helpers, and `ProtectedRoute` support for future login flows
23
25
 
24
26
  ## Quick Start
25
27
 
@@ -65,6 +67,7 @@ npm run dev
65
67
  - Live preview and playground
66
68
  - Embed code generation
67
69
  - Docker and Vercel deployment support
70
+ - Theme + widget matrices: see [`docs/THEME_WIDGET_CONFIG.md`](docs/THEME_WIDGET_CONFIG.md) for every field, color mapping tips, and widget overrides
68
71
 
69
72
  ## Prerequisites
70
73
 
@@ -160,10 +163,18 @@ assistant-chat/
160
163
  ### How It Works
161
164
 
162
165
  - **Same Widget Code**: Both the NPM package and standalone app use the same `Widget.tsx` component
166
+ - **Embed & Playground**: `WidgetPage.tsx` powers the iframe, embed script, and playground preview using that same component
163
167
  - **NPM Package**: Publishes the widget component as a reusable library
164
168
  - **Standalone App**: Uses the widget component directly for admin interface and playground
165
169
  - **No Duplication**: Single source of truth for the widget component
166
170
 
171
+ ## Layout & Auth Architecture
172
+
173
+ - `AppProvider` manages `user`, `workspace`, auth token, and exposes `login/logout` helpers plus `ProtectedRoute` for future API integration.
174
+ - `Header` & `MainLayout` deliver the new full-width, two-row dashboard shell (logo, workspace switcher, company badge, primary nav, profile dropdown).
175
+ - `ConfigPage` (dashboard) and every other route render inside `MainLayout`, so all future pages automatically inherit the header and spacing.
176
+ - `LoginPage` lives outside the layout and is already wired to `AppProvider`, making it ready for real authentication APIs.
177
+
167
178
  ## Architecture
168
179
 
169
180
  ```
@@ -5,6 +5,7 @@ import { Send, X, MessageCircle, Bot, ThumbsUp, ThumbsDown } from 'lucide-react'
5
5
  import { generateId, formatTimestamp } from '../utils/index.js';
6
6
  import { VezloFooter } from './ui/VezloFooter.js';
7
7
  import { createConversation, createUserMessage, generateAIResponse } from '../api/index.js';
8
+ import { THEME } from '../config/theme.js';
8
9
  export function Widget({ config, isPlayground = false, onOpen, onClose, onMessage, onError, useShadowRoot = false, }) {
9
10
  // Use defaultOpen from config, fallback to isPlayground for backward compatibility
10
11
  const [isOpen, setIsOpen] = useState(config.defaultOpen ?? isPlayground);
@@ -233,7 +234,7 @@ export function Widget({ config, isPlayground = false, onOpen, onClose, onMessag
233
234
  } }), !isOpen && (_jsxs("div", { className: "relative animate-fadeIn", style: { pointerEvents: 'auto', width: 64, height: 64 }, children: [_jsx("div", { style: {
234
235
  position: 'absolute',
235
236
  inset: 0,
236
- backgroundColor: config.themeColor || '#059669',
237
+ backgroundColor: config.themeColor || THEME.primary.hex,
237
238
  borderRadius: 9999,
238
239
  opacity: 0.2,
239
240
  filter: 'blur(0px)'
@@ -243,7 +244,7 @@ export function Widget({ config, isPlayground = false, onOpen, onClose, onMessag
243
244
  height: 64,
244
245
  borderRadius: 9999,
245
246
  color: '#fff',
246
- background: `linear-gradient(135deg, ${config.themeColor}, ${config.themeColor}dd)`,
247
+ background: `linear-gradient(135deg, ${config.themeColor || THEME.primary.hex}, ${config.themeColor || THEME.primary.hex}dd)`,
247
248
  boxShadow: '0 10px 25px rgba(0,0,0,0.20)',
248
249
  display: 'flex',
249
250
  alignItems: 'center',
@@ -259,18 +260,21 @@ export function Widget({ config, isPlayground = false, onOpen, onClose, onMessag
259
260
  pointerEvents: 'auto',
260
261
  width: (config.size && config.size.width) ? config.size.width : 420,
261
262
  height: (config.size && config.size.height) ? config.size.height : 600
262
- }, children: [_jsxs("div", { className: "text-white p-4 flex justify-between items-center relative overflow-hidden", style: { background: `linear-gradient(to right, ${config.themeColor}, ${config.themeColor}dd, ${config.themeColor}bb)`, color: '#fff' }, children: [_jsxs("div", { className: "absolute inset-0 opacity-10", children: [_jsx("div", { className: "absolute top-0 left-0 w-full h-full bg-gradient-to-br from-white/20 to-transparent" }), _jsx("div", { className: "absolute bottom-0 right-0 w-32 h-32 bg-white/10 rounded-full -translate-y-8 translate-x-8" })] }), _jsxs("div", { className: "flex items-center gap-3 relative z-10", children: [_jsx("div", { className: "w-10 h-10 bg-white/20 rounded-full flex items-center justify-center backdrop-blur-sm", children: _jsx(Bot, { className: "w-5 h-5 text-white" }) }), _jsxs("div", { children: [_jsx("h3", { className: "font-semibold text-lg", children: config.title }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("div", { className: "w-2 h-2 bg-green-400 rounded-full animate-pulse" }), _jsxs("p", { className: "text-xs text-emerald-100", children: ["Online \u2022 ", config.subtitle] })] })] })] }), _jsx("button", { onClick: handleCloseWidget, className: "hover:bg-white/20 rounded-lg p-2 transition-all duration-200 hover:scale-110 relative z-10", children: _jsx(X, { className: "w-5 h-5" }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-4 space-y-4 bg-gradient-to-b from-gray-50 to-gray-100", children: [messages.map((message, index) => (_jsxs("div", { className: `flex ${message.role === 'user' ? 'justify-end' : 'justify-start'} animate-fadeIn`, style: { animationDelay: `${index * 0.1}s` }, children: [message.role === 'assistant' && (_jsx("div", { className: "w-8 h-8 bg-emerald-100 rounded-full flex items-center justify-center flex-shrink-0 mt-1 mr-2", children: _jsx(Bot, { className: "w-4 h-4 text-emerald-600" }) })), _jsxs("div", { className: "flex flex-col max-w-[75%]", children: [_jsx("div", { className: `rounded-2xl px-4 py-3 shadow-sm transition-all duration-200 hover:shadow-md ${message.role === 'user'
263
+ }, children: [_jsxs("div", { className: "text-white p-4 flex justify-between items-center relative overflow-hidden", style: { background: `linear-gradient(to right, ${config.themeColor || THEME.primary.hex}, ${config.themeColor || THEME.primary.hex}dd, ${config.themeColor || THEME.primary.hex}bb)`, color: '#fff' }, children: [_jsxs("div", { className: "absolute inset-0 opacity-10", children: [_jsx("div", { className: "absolute top-0 left-0 w-full h-full bg-gradient-to-br from-white/20 to-transparent" }), _jsx("div", { className: "absolute bottom-0 right-0 w-32 h-32 bg-white/10 rounded-full -translate-y-8 translate-x-8" })] }), _jsxs("div", { className: "flex items-center gap-3 relative z-10", children: [_jsx("div", { className: "w-12 h-12 bg-white/20 rounded-2xl flex items-center justify-center backdrop-blur-sm flex-shrink-0", children: _jsx(Bot, { className: "w-6 h-6 text-white" }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h3", { className: "font-semibold text-lg leading-tight truncate", children: config.title }), _jsxs("div", { className: "flex items-center gap-1.5 mt-0.5", children: [_jsx("div", { className: "w-2 h-2 bg-green-400 rounded-full animate-pulse flex-shrink-0" }), _jsxs("p", { className: "text-xs text-white/90 truncate", children: ["Online \u2022 ", config.subtitle] })] })] })] }), _jsx("button", { onClick: handleCloseWidget, className: "hover:bg-white/20 rounded-lg p-2 transition-all duration-200 hover:scale-110 relative z-10", children: _jsx(X, { className: "w-5 h-5" }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-4 space-y-4 bg-gradient-to-b from-gray-50 to-white", children: [messages.map((message, index) => (_jsxs("div", { className: `flex ${message.role === 'user' ? 'justify-end' : 'justify-start'} animate-fadeIn`, style: { animationDelay: `${index * 0.1}s` }, children: [message.role === 'assistant' && (_jsx("div", { className: "w-8 h-8 bg-emerald-50 rounded-full flex items-center justify-center flex-shrink-0 mt-1 mr-2 border border-emerald-100", children: _jsx(Bot, { className: "w-4 h-4 text-emerald-600" }) })), _jsxs("div", { className: "flex flex-col max-w-[75%]", children: [_jsx("div", { className: `rounded-2xl px-4 py-3 shadow-sm transition-all duration-200 hover:shadow-md ${message.role === 'user'
263
264
  ? 'text-white'
264
265
  : 'bg-white text-gray-900 border border-gray-200'}`, style: {
265
- backgroundColor: message.role === 'user' ? config.themeColor : undefined,
266
+ backgroundColor: message.role === 'user' ? (config.themeColor || THEME.primary.hex) : undefined,
266
267
  boxShadow: message.role === 'user'
267
- ? `0 4px 12px ${config.themeColor}4D` // 4D is ~30% opacity
268
+ ? `0 4px 12px ${(config.themeColor || THEME.primary.hex)}4D` // 4D is ~30% opacity
268
269
  : '0 2px 8px rgba(0, 0, 0, 0.1)'
269
270
  }, children: _jsx("p", { className: "text-sm whitespace-pre-wrap break-words leading-relaxed", children: message.content }) }), _jsxs("div", { className: "flex items-center justify-between mt-1", children: [_jsx("p", { className: `text-xs ${message.role === 'user' ? 'text-emerald-100' : 'text-gray-500'}`, children: formatTimestamp(message.timestamp) }), message.role === 'assistant' && (_jsxs("div", { className: "flex items-center gap-1 ml-2", children: [_jsx("button", { onClick: () => handleFeedback(message.id, 'like'), className: `p-1 rounded transition-all duration-200 hover:scale-110 cursor-pointer ${messageFeedback[message.id] === 'like'
270
271
  ? 'text-green-600'
271
272
  : 'text-gray-400 hover:text-green-600'}`, children: _jsx(ThumbsUp, { className: `w-4 h-4 ${messageFeedback[message.id] === 'like' ? 'fill-current' : ''}` }) }), _jsx("button", { onClick: () => handleFeedback(message.id, 'dislike'), className: `p-1 rounded transition-all duration-200 hover:scale-110 cursor-pointer ${messageFeedback[message.id] === 'dislike'
272
273
  ? 'text-red-600'
273
- : 'text-gray-400 hover:text-red-600'}`, children: _jsx(ThumbsDown, { className: `w-4 h-4 ${messageFeedback[message.id] === 'dislike' ? 'fill-current' : ''}` }) })] }))] })] })] }, message.id))), streamingMessage && (_jsxs("div", { className: "flex justify-start animate-fadeIn", children: [_jsx("div", { className: "w-8 h-8 bg-emerald-100 rounded-full flex items-center justify-center flex-shrink-0 mt-1 mr-2", children: _jsx(Bot, { className: "w-4 h-4 text-emerald-600" }) }), _jsx("div", { className: "flex flex-col max-w-[75%]", children: _jsx("div", { className: "bg-white text-gray-900 border border-gray-200 rounded-2xl px-4 py-3 shadow-sm", children: _jsxs("p", { className: "text-sm whitespace-pre-wrap break-words leading-relaxed", style: { color: '#111827' }, children: [streamingMessage, _jsx("span", { style: { display: 'inline-block', animation: 'vezloCaretBlink 1s steps(1, end) infinite' }, children: "|" })] }) }) })] })), isLoading && (_jsx("div", { className: "flex justify-start animate-fadeIn", children: _jsx("div", { className: "bg-white border border-gray-200 rounded-2xl px-4 py-3 flex items-center gap-3 shadow-sm", children: _jsxs("div", { className: "flex gap-1", style: { display: 'flex', gap: '4px' }, children: [_jsx("span", { style: { width: 8, height: 8, borderRadius: 9999, backgroundColor: config.themeColor || '#10b981', display: 'inline-block', animation: 'vezloDotPulse 1s infinite ease-in-out', animationDelay: '0s' } }), _jsx("span", { style: { width: 8, height: 8, borderRadius: 9999, backgroundColor: config.themeColor || '#10b981', display: 'inline-block', animation: 'vezloDotPulse 1s infinite ease-in-out', animationDelay: '0.15s' } }), _jsx("span", { style: { width: 8, height: 8, borderRadius: 9999, backgroundColor: config.themeColor || '#10b981', display: 'inline-block', animation: 'vezloDotPulse 1s infinite ease-in-out', animationDelay: '0.3s' } })] }) }) })), _jsx("div", { ref: messagesEndRef })] }), _jsx("div", { className: "border-t border-gray-200 p-4 bg-white", children: _jsxs("div", { className: "flex gap-3", children: [_jsx("input", { type: "text", value: input, onChange: (e) => setInput(e.target.value), onKeyPress: handleKeyPress, placeholder: config.placeholder, disabled: isLoading, className: "flex-1 px-4 py-3 border border-gray-300 rounded-2xl focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed text-sm transition-all duration-200" }), _jsx("button", { onClick: handleSendMessage, disabled: !input.trim() || isLoading, className: "text-white px-4 py-3 rounded-2xl hover:from-blue-700 hover:to-blue-800 transition-all duration-200 disabled:bg-gray-300 disabled:cursor-not-allowed flex items-center justify-center shadow-lg hover:shadow-xl disabled:shadow-none transform hover:scale-105 disabled:scale-100", style: { background: `linear-gradient(to right, ${config.themeColor}, ${config.themeColor}dd)` }, children: _jsx(Send, { className: "w-4 h-4" }) })] }) }), _jsx("div", { className: "border-t border-gray-200 px-4 py-3 bg-gradient-to-r from-gray-50 to-gray-100", children: _jsx(VezloFooter, { size: "sm" }) })] }))] }));
274
+ : 'text-gray-400 hover:text-red-600'}`, children: _jsx(ThumbsDown, { className: `w-4 h-4 ${messageFeedback[message.id] === 'dislike' ? 'fill-current' : ''}` }) })] }))] })] })] }, message.id))), streamingMessage && (_jsxs("div", { className: "flex justify-start animate-fadeIn", children: [_jsx("div", { className: "w-8 h-8 bg-emerald-50 rounded-full flex items-center justify-center flex-shrink-0 mt-1 mr-2 border border-emerald-100", children: _jsx(Bot, { className: "w-4 h-4 text-emerald-600" }) }), _jsx("div", { className: "flex flex-col max-w-[75%]", children: _jsx("div", { className: "bg-white text-gray-900 border border-gray-200 rounded-2xl px-4 py-3 shadow-sm", children: _jsxs("p", { className: "text-sm whitespace-pre-wrap break-words leading-relaxed", style: { color: '#111827' }, children: [streamingMessage, _jsx("span", { style: { display: 'inline-block', animation: 'vezloCaretBlink 1s steps(1, end) infinite' }, children: "|" })] }) }) })] })), isLoading && (_jsx("div", { className: "flex justify-start animate-fadeIn", children: _jsx("div", { className: "bg-white border border-gray-200 rounded-2xl px-4 py-3 flex items-center gap-3 shadow-sm", children: _jsxs("div", { className: "flex gap-1", style: { display: 'flex', gap: '4px' }, children: [_jsx("span", { style: { width: 8, height: 8, borderRadius: 9999, backgroundColor: config.themeColor || THEME.primary.hex, display: 'inline-block', animation: 'vezloDotPulse 1s infinite ease-in-out', animationDelay: '0s' } }), _jsx("span", { style: { width: 8, height: 8, borderRadius: 9999, backgroundColor: config.themeColor || THEME.primary.hex, display: 'inline-block', animation: 'vezloDotPulse 1s infinite ease-in-out', animationDelay: '0.15s' } }), _jsx("span", { style: { width: 8, height: 8, borderRadius: 9999, backgroundColor: config.themeColor || THEME.primary.hex, display: 'inline-block', animation: 'vezloDotPulse 1s infinite ease-in-out', animationDelay: '0.3s' } })] }) }) })), _jsx("div", { ref: messagesEndRef })] }), _jsx("div", { className: "border-t border-gray-200 p-4 bg-white", children: _jsxs("div", { className: "flex gap-3", children: [_jsx("input", { type: "text", value: input, onChange: (e) => setInput(e.target.value), onKeyPress: handleKeyPress, placeholder: config.placeholder, disabled: isLoading, className: "flex-1 px-4 py-3 border border-gray-300 rounded-2xl focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed text-sm transition-all duration-200 placeholder:text-gray-400" }), _jsx("button", { onClick: handleSendMessage, disabled: !input.trim() || isLoading, className: "text-white px-4 py-3 rounded-2xl transition-all duration-200 disabled:bg-gray-300 disabled:cursor-not-allowed flex items-center justify-center shadow-lg hover:shadow-xl disabled:shadow-none transform hover:scale-105 disabled:scale-100 min-w-[48px]", style: {
275
+ background: `linear-gradient(to right, ${config.themeColor || THEME.primary.hex}, ${config.themeColor || THEME.primary.hex}dd)`,
276
+ opacity: (!input.trim() || isLoading) ? 0.6 : 1
277
+ }, children: _jsx(Send, { className: "w-4 h-4" }) })] }) }), _jsx("div", { className: "border-t border-gray-200 px-4 bg-gradient-to-r from-gray-50 to-white", style: { minHeight: 52 }, children: _jsx(VezloFooter, { size: "sm" }) })] }))] }));
274
278
  if (useShadowRoot) {
275
279
  // Ensure host exists in DOM
276
280
  return (_jsx("div", { ref: hostRef, style: { all: 'initial' }, children: shadowReady && shadowMountRef.current ? createPortal(content, shadowMountRef.current) : null }));
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { THEME } from '../../config/theme.js';
3
- export function VezloFooter({ size = 'md' }) {
4
- const iconSize = size === 'sm' ? 'w-3 h-3' : 'w-4 h-4';
2
+ import { Zap } from 'lucide-react';
3
+ export function VezloFooter({ size = 'sm' }) {
5
4
  const textSize = size === 'sm' ? 'text-xs' : 'text-sm';
6
- return (_jsxs("div", { className: "flex items-center justify-center gap-2", children: [_jsx("div", { className: `${iconSize} rounded-sm flex items-center justify-center`, style: { backgroundColor: THEME.primary.hex }, children: _jsx("span", { className: "text-white text-xs font-bold", children: "V" }) }), _jsxs("p", { className: `${textSize} text-gray-600`, children: ["Powered by ", _jsx("span", { className: "font-semibold", style: { color: THEME.primary.hex }, children: "Vezlo" })] })] }));
5
+ const logoHeight = size === 'sm' ? 48 : 68;
6
+ const iconSize = size === 'sm' ? 'w-4 h-4' : 'w-5 h-5';
7
+ const gapClass = 'gap-1';
8
+ return (_jsxs("div", { className: `flex items-center justify-center ${gapClass}`, children: [_jsx("span", { className: `${textSize} text-gray-600 font-medium`, children: "Powered by" }), _jsx(Zap, { className: `${iconSize} flex-shrink-0 -mr-1`, style: { color: '#f5c518' } }), _jsx("img", { src: "/assets/vezlo.png", alt: "Vezlo", style: { height: `${logoHeight}px`, width: 'auto' }, className: "object-contain" })] }));
7
9
  }
@@ -6,6 +6,9 @@ export declare const THEME: {
6
6
  readonly primary: {
7
7
  readonly hex: "#059669";
8
8
  readonly tailwind: "emerald";
9
+ readonly darker: "#047857";
10
+ readonly lighter: "#10b981";
11
+ readonly lightest: "#d1fae5";
9
12
  };
10
13
  readonly colors: {
11
14
  readonly bg: "bg-emerald-600";
@@ -18,6 +21,34 @@ export declare const THEME: {
18
21
  readonly border: "border-emerald-600";
19
22
  readonly borderLight: "border-emerald-200";
20
23
  };
24
+ readonly typography: {
25
+ readonly fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif";
26
+ readonly heading: {
27
+ readonly weight: "600";
28
+ readonly size: {
29
+ readonly sm: "0.875rem";
30
+ readonly md: "1rem";
31
+ readonly lg: "1.125rem";
32
+ readonly xl: "1.25rem";
33
+ };
34
+ };
35
+ readonly body: {
36
+ readonly weight: "400";
37
+ readonly size: {
38
+ readonly sm: "0.75rem";
39
+ readonly md: "0.875rem";
40
+ readonly lg: "1rem";
41
+ };
42
+ };
43
+ };
44
+ readonly spacing: {
45
+ readonly xs: "0.5rem";
46
+ readonly sm: "0.75rem";
47
+ readonly md: "1rem";
48
+ readonly lg: "1.5rem";
49
+ readonly xl: "2rem";
50
+ };
21
51
  };
22
52
  export declare const getButtonGradient: (color?: string) => string;
23
53
  export declare const getHeaderGradient: (color?: string) => string;
54
+ export declare const getHoverColor: () => "#047857";
@@ -3,10 +3,14 @@
3
3
  * Change these values to update colors across the entire application
4
4
  */
5
5
  export const THEME = {
6
- // Primary brand color (emerald)
6
+ // Primary brand color (emerald/teal)
7
7
  primary: {
8
8
  hex: '#059669',
9
9
  tailwind: 'emerald',
10
+ // Color variants for different use cases
11
+ darker: '#047857', // For hover states
12
+ lighter: '#10b981', // For accents
13
+ lightest: '#d1fae5', // For backgrounds
10
14
  },
11
15
  // Tailwind color variants
12
16
  colors: {
@@ -20,6 +24,35 @@ export const THEME = {
20
24
  border: 'border-emerald-600',
21
25
  borderLight: 'border-emerald-200',
22
26
  },
27
+ // Typography
28
+ typography: {
29
+ fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
30
+ heading: {
31
+ weight: '600',
32
+ size: {
33
+ sm: '0.875rem',
34
+ md: '1rem',
35
+ lg: '1.125rem',
36
+ xl: '1.25rem',
37
+ },
38
+ },
39
+ body: {
40
+ weight: '400',
41
+ size: {
42
+ sm: '0.75rem',
43
+ md: '0.875rem',
44
+ lg: '1rem',
45
+ },
46
+ },
47
+ },
48
+ // Spacing (for consistency)
49
+ spacing: {
50
+ xs: '0.5rem',
51
+ sm: '0.75rem',
52
+ md: '1rem',
53
+ lg: '1.5rem',
54
+ xl: '2rem',
55
+ },
23
56
  };
24
57
  // Helper function to get gradient for buttons
25
58
  export const getButtonGradient = (color = THEME.primary.hex) => {
@@ -29,3 +62,5 @@ export const getButtonGradient = (color = THEME.primary.hex) => {
29
62
  export const getHeaderGradient = (color = THEME.primary.hex) => {
30
63
  return `linear-gradient(to right, ${color}, ${color}dd, ${color}bb)`;
31
64
  };
65
+ // Helper function to get darker shade for hover states
66
+ export const getHoverColor = () => THEME.primary.darker;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vezlo/assistant-chat",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "React component library for AI-powered chat widgets with RAG knowledge base integration and real-time streaming",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",