@cuadra-ai/uikit 0.1.31 → 0.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 +142 -2
- package/dist/adapters/attachmentAdapter.d.ts +63 -4
- package/dist/adapters/attachmentAdapter.d.ts.map +1 -1
- package/dist/components/CuadraChat.d.ts +54 -108
- package/dist/components/CuadraChat.d.ts.map +1 -1
- package/dist/components/CuadraChatContext.d.ts +141 -0
- package/dist/components/CuadraChatContext.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.d.ts +79 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/index.cjs +425 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +52836 -2805
- package/dist/index.mjs.map +1 -1
- package/dist/lib/cuadraChatClient.d.ts +2 -1
- package/dist/lib/cuadraChatClient.d.ts.map +1 -1
- package/dist/magic-string.es-B81Zo59j.cjs +11 -0
- package/dist/magic-string.es-B81Zo59j.cjs.map +1 -0
- package/dist/magic-string.es-uPKorP4O.js +664 -0
- package/dist/magic-string.es-uPKorP4O.js.map +1 -0
- package/dist/test/fixtures/index.d.ts +7 -0
- package/dist/test/fixtures/index.d.ts.map +1 -0
- package/dist/test/fixtures/mockChats.d.ts +41 -0
- package/dist/test/fixtures/mockChats.d.ts.map +1 -0
- package/dist/test/fixtures/mockModels.d.ts +31 -0
- package/dist/test/fixtures/mockModels.d.ts.map +1 -0
- package/dist/test/fixtures/mockStreams.d.ts +60 -0
- package/dist/test/fixtures/mockStreams.d.ts.map +1 -0
- package/dist/test/utils/index.d.ts +6 -0
- package/dist/test/utils/index.d.ts.map +1 -0
- package/dist/test/utils/mockFetch.d.ts +67 -0
- package/dist/test/utils/mockFetch.d.ts.map +1 -0
- package/dist/test/utils/renderWithProviders.d.ts +136 -0
- package/dist/test/utils/renderWithProviders.d.ts.map +1 -0
- package/dist/types/props.d.ts +500 -0
- package/dist/types/props.d.ts.map +1 -0
- package/dist/uikit.css +1 -1
- package/dist/utils/sanitize.d.ts +90 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/widget/cuadra-uikit.css +1 -1
- package/dist/widget/cuadra-uikit.umd.js +24 -24
- package/dist/widget/cuadra-uikit.umd.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -113,7 +113,104 @@ function App() {
|
|
|
113
113
|
}
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
####
|
|
116
|
+
#### New V2 Props (Recommended)
|
|
117
|
+
|
|
118
|
+
The new V2 props API groups related options for better organization:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
import { CuadraChat } from '@cuadra-ai/uikit';
|
|
122
|
+
|
|
123
|
+
function App() {
|
|
124
|
+
return (
|
|
125
|
+
<div style={{ height: '100vh' }}>
|
|
126
|
+
<CuadraChat
|
|
127
|
+
connection={{
|
|
128
|
+
baseUrl: "https://api.cuadra.ai",
|
|
129
|
+
sessionToken: "your-session-token",
|
|
130
|
+
}}
|
|
131
|
+
chat={{
|
|
132
|
+
mode: "multiChat",
|
|
133
|
+
modelMode: "fixed",
|
|
134
|
+
modelId: "your-model-id",
|
|
135
|
+
enableReasoning: true,
|
|
136
|
+
}}
|
|
137
|
+
ui={{
|
|
138
|
+
theme: "system",
|
|
139
|
+
welcomeTitle: "Welcome to Chat",
|
|
140
|
+
welcomeSubtitle: "How can I help you today?",
|
|
141
|
+
suggestions: [
|
|
142
|
+
{ prompt: "What is Cuadra AI?" },
|
|
143
|
+
{ prompt: "How do I get started?" }
|
|
144
|
+
],
|
|
145
|
+
}}
|
|
146
|
+
callbacks={{
|
|
147
|
+
onChatCreated: (chatId) => console.log('Chat:', chatId),
|
|
148
|
+
onError: (error) => console.error(error),
|
|
149
|
+
}}
|
|
150
|
+
className="my-custom-class"
|
|
151
|
+
/>
|
|
152
|
+
</div>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
#### With Context Provider (External Control)
|
|
158
|
+
|
|
159
|
+
Use `CuadraChatProvider` to control the chat from anywhere in your component tree:
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import { CuadraChat, CuadraChatProvider, useCuadraChat } from '@cuadra-ai/uikit';
|
|
163
|
+
|
|
164
|
+
function ChatControls() {
|
|
165
|
+
const { controls, isReady } = useCuadraChat();
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<button
|
|
169
|
+
onClick={() => controls?.sendMessage('Hello!')}
|
|
170
|
+
disabled={!isReady}
|
|
171
|
+
>
|
|
172
|
+
Send Hello
|
|
173
|
+
</button>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function App() {
|
|
178
|
+
return (
|
|
179
|
+
<CuadraChatProvider>
|
|
180
|
+
<ChatControls />
|
|
181
|
+
<CuadraChat
|
|
182
|
+
connection={{ baseUrl: "https://api.cuadra.ai" }}
|
|
183
|
+
chat={{ modelId: "your-model-id" }}
|
|
184
|
+
/>
|
|
185
|
+
</CuadraChatProvider>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### With Error Boundary
|
|
191
|
+
|
|
192
|
+
CuadraChat includes built-in error handling:
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
import { CuadraChat } from '@cuadra-ai/uikit';
|
|
196
|
+
|
|
197
|
+
function App() {
|
|
198
|
+
return (
|
|
199
|
+
<CuadraChat
|
|
200
|
+
connection={{ baseUrl: "https://api.cuadra.ai" }}
|
|
201
|
+
chat={{ modelId: "your-model-id" }}
|
|
202
|
+
errorFallback={(error, reset) => (
|
|
203
|
+
<div>
|
|
204
|
+
<p>Something went wrong: {error.message}</p>
|
|
205
|
+
<button onClick={reset}>Retry</button>
|
|
206
|
+
</div>
|
|
207
|
+
)}
|
|
208
|
+
/>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### Legacy Props (Still Supported)
|
|
117
214
|
|
|
118
215
|
```tsx
|
|
119
216
|
import { CuadraChat } from '@cuadra-ai/uikit';
|
|
@@ -231,7 +328,50 @@ For detailed widget API documentation, see the [full documentation](https://docs
|
|
|
231
328
|
|
|
232
329
|
## API Reference
|
|
233
330
|
|
|
234
|
-
###
|
|
331
|
+
### V2 Props (Recommended)
|
|
332
|
+
|
|
333
|
+
| Prop Group | Prop | Type | Description |
|
|
334
|
+
|------------|------|------|-------------|
|
|
335
|
+
| `connection` | `baseUrl` | `string` | Cuadra API base URL |
|
|
336
|
+
| | `proxyUrl` | `string` | Proxy URL for backend auth |
|
|
337
|
+
| | `sessionToken` | `string \| null` | Bearer token |
|
|
338
|
+
| `chat` | `mode` | `'singleChat' \| 'multiChat'` | Chat mode (default: `'multiChat'`) |
|
|
339
|
+
| | `modelMode` | `'fixed' \| 'selector'` | Model selection mode (default: `'fixed'`) |
|
|
340
|
+
| | `modelId` | `string` | Model ID from dashboard |
|
|
341
|
+
| | `systemPrompt` | `string` | System prompt |
|
|
342
|
+
| | `ephemeral` | `boolean` | Auto-delete chats on close |
|
|
343
|
+
| | `enableReasoning` | `boolean` | Enable thinking output |
|
|
344
|
+
| | `enableAttachments` | `boolean` | Enable file attachments |
|
|
345
|
+
| `ui` | `theme` | `'light' \| 'dark' \| 'system'` | Theme mode (default: `'system'`) |
|
|
346
|
+
| | `showThemeToggle` | `boolean` | Show toggle (default: `true`) |
|
|
347
|
+
| | `welcomeTitle` | `string` | Welcome screen title |
|
|
348
|
+
| | `welcomeSubtitle` | `string` | Welcome screen subtitle |
|
|
349
|
+
| | `suggestions` | `Array<Suggestion>` | Welcome screen suggestions |
|
|
350
|
+
| | `inputPlaceholder` | `string` | Input field placeholder |
|
|
351
|
+
| `callbacks` | `onChatCreated` | `(id: string) => void` | Called when chat created |
|
|
352
|
+
| | `onError` | `(error: Error) => void` | Error callback |
|
|
353
|
+
| | `onModelChange` | `(id: string) => void` | Model change callback |
|
|
354
|
+
| `errorFallback` | | `ReactNode \| Function` | Custom error UI |
|
|
355
|
+
| `className` | | `string` | Container CSS class |
|
|
356
|
+
|
|
357
|
+
### Exported Hooks
|
|
358
|
+
|
|
359
|
+
| Hook | Description |
|
|
360
|
+
|------|-------------|
|
|
361
|
+
| `useCuadraChat()` | Access chat controls from context (requires `CuadraChatProvider`) |
|
|
362
|
+
| `useCuadraChatOptional()` | Same as above, returns null if no provider |
|
|
363
|
+
|
|
364
|
+
### Exported Utilities
|
|
365
|
+
|
|
366
|
+
| Utility | Description |
|
|
367
|
+
|---------|-------------|
|
|
368
|
+
| `sanitizeSystemPrompt()` | Remove injection patterns from prompts |
|
|
369
|
+
| `isValidUrl()` | Validate URL uses http/https |
|
|
370
|
+
| `validateBaseUrl()` | Validate API base URL with details |
|
|
371
|
+
| `generateSecureUUID()` | Crypto-secure UUID generation |
|
|
372
|
+
| `createAttachmentAdapter()` | Create file attachment adapter with validation |
|
|
373
|
+
|
|
374
|
+
### Legacy Props (Still Supported)
|
|
235
375
|
|
|
236
376
|
| Prop | Type | Required | Default | Description |
|
|
237
377
|
|------|------|----------|---------|-------------|
|
|
@@ -1,7 +1,66 @@
|
|
|
1
|
-
import type { AttachmentAdapter } from '@assistant-ui/react';
|
|
1
|
+
import type { AttachmentAdapter, PendingAttachment } from '@assistant-ui/react';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* Files are kept as File objects and sent with messages
|
|
3
|
+
* Attachment validation configuration
|
|
5
4
|
*/
|
|
6
|
-
export
|
|
5
|
+
export interface AttachmentValidationConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Maximum file size in bytes
|
|
8
|
+
* @default 10 * 1024 * 1024 (10MB)
|
|
9
|
+
*/
|
|
10
|
+
maxFileSizeBytes?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Allowed MIME types (e.g., ['image/png', 'image/jpeg'])
|
|
13
|
+
* If not provided, defaults to common document and image types
|
|
14
|
+
*/
|
|
15
|
+
allowedMimeTypes?: string[];
|
|
16
|
+
/**
|
|
17
|
+
* Allowed file extensions (e.g., ['.pdf', '.docx'])
|
|
18
|
+
* If not provided, defaults to common document and image extensions
|
|
19
|
+
*/
|
|
20
|
+
allowedExtensions?: string[];
|
|
21
|
+
/**
|
|
22
|
+
* Maximum number of attachments per message
|
|
23
|
+
* @default 5
|
|
24
|
+
*/
|
|
25
|
+
maxAttachments?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Whether to validate file content type matches extension
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
validateContentType?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Attachment validation error
|
|
34
|
+
*/
|
|
35
|
+
export declare class AttachmentValidationError extends Error {
|
|
36
|
+
readonly code: 'FILE_TOO_LARGE' | 'INVALID_TYPE' | 'TOO_MANY_FILES' | 'VALIDATION_FAILED';
|
|
37
|
+
readonly file?: File | undefined;
|
|
38
|
+
constructor(message: string, code: 'FILE_TOO_LARGE' | 'INVALID_TYPE' | 'TOO_MANY_FILES' | 'VALIDATION_FAILED', file?: File | undefined);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Attachment adapter options
|
|
42
|
+
*/
|
|
43
|
+
export interface AttachmentAdapterOptions {
|
|
44
|
+
/**
|
|
45
|
+
* Validation configuration
|
|
46
|
+
*/
|
|
47
|
+
validation?: AttachmentValidationConfig;
|
|
48
|
+
/**
|
|
49
|
+
* Callback when validation fails
|
|
50
|
+
* Allows custom error handling (e.g., show toast notification)
|
|
51
|
+
*/
|
|
52
|
+
onValidationError?: (error: AttachmentValidationError) => void;
|
|
53
|
+
/**
|
|
54
|
+
* Callback when attachment is added
|
|
55
|
+
*/
|
|
56
|
+
onAttachmentAdded?: (attachment: PendingAttachment) => void;
|
|
57
|
+
/**
|
|
58
|
+
* Callback when attachment is removed
|
|
59
|
+
*/
|
|
60
|
+
onAttachmentRemoved?: (attachmentId: string) => void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Create an attachment adapter with enhanced validation
|
|
64
|
+
*/
|
|
65
|
+
export declare function createAttachmentAdapter(options?: AttachmentAdapterOptions): AttachmentAdapter;
|
|
7
66
|
//# sourceMappingURL=attachmentAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachmentAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/attachmentAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,
|
|
1
|
+
{"version":3,"file":"attachmentAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/attachmentAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE5B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE7B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;aAGhC,IAAI,EAAE,gBAAgB,GAAG,cAAc,GAAG,gBAAgB,GAAG,mBAAmB;aAChF,IAAI,CAAC,EAAE,IAAI;gBAF3B,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,gBAAgB,GAAG,cAAc,GAAG,gBAAgB,GAAG,mBAAmB,EAChF,IAAI,CAAC,EAAE,IAAI,YAAA;CAK9B;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,UAAU,CAAC,EAAE,0BAA0B,CAAC;IAExC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,IAAI,CAAC;IAE/D;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAE5D;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;CACtD;AAiHD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,wBAA6B,GACrC,iBAAiB,CAwJnB"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type { CuadraTheme } from '../types/theme';
|
|
1
|
+
import { type CuadraChatProps } from '../types/props';
|
|
3
2
|
/**
|
|
4
3
|
* Handle for controlling CuadraChat externally
|
|
5
4
|
*/
|
|
@@ -17,121 +16,68 @@ export interface CuadraChatHandle {
|
|
|
17
16
|
/** Clear the current chat and start fresh */
|
|
18
17
|
clearChat: () => void;
|
|
19
18
|
}
|
|
20
|
-
export
|
|
21
|
-
/** Proxy URL for backend-handled authentication (e.g., '/api/chat' or 'http://localhost:3000') */
|
|
22
|
-
proxyUrl?: string;
|
|
23
|
-
/** Container className for styling */
|
|
24
|
-
className?: string;
|
|
25
|
-
/** Show theme toggle button */
|
|
26
|
-
showThemeToggle?: boolean;
|
|
27
|
-
/** Initial theme ('light' | 'dark' | 'system') */
|
|
28
|
-
theme?: 'light' | 'dark' | 'system';
|
|
29
|
-
/** Custom theme colors to override defaults */
|
|
30
|
-
customTheme?: CuadraTheme;
|
|
31
|
-
/** Language/locale for i18n (e.g., 'en', 'es', 'fr') */
|
|
32
|
-
language?: string;
|
|
33
|
-
/** Welcome screen title */
|
|
34
|
-
welcomeTitle?: string;
|
|
35
|
-
/** Welcome screen subtitle */
|
|
36
|
-
welcomeSubtitle?: string;
|
|
37
|
-
/** Extra top padding for thread viewport (e.g., '1rem', '2rem') */
|
|
38
|
-
extraTopPadding?: string;
|
|
39
|
-
/** Suggestions to show in welcome screen (with optional pre-made responses) */
|
|
40
|
-
suggestions?: Array<{
|
|
41
|
-
/** Suggestion prompt text */
|
|
42
|
-
prompt: string;
|
|
43
|
-
/** Pre-made response (optional) - if provided, response appears instantly with simulated streaming */
|
|
44
|
-
response?: string;
|
|
45
|
-
/** Delay before showing response in ms (overrides preMadeResponseDelay) */
|
|
46
|
-
responseDelay?: number;
|
|
47
|
-
}>;
|
|
48
|
-
/** Placeholder text for the input field */
|
|
49
|
-
inputPlaceholder?: string;
|
|
50
|
-
/** Default delay before pre-made responses in ms (default: 1000) */
|
|
51
|
-
preMadeResponseDelay?: number;
|
|
52
|
-
/** Speed of simulated streaming in ms per word (default: 50) */
|
|
53
|
-
streamingSpeed?: number;
|
|
54
|
-
/** Called when a user message is sent */
|
|
55
|
-
onUserMessage?: () => void;
|
|
56
|
-
/** Called when logout button is clicked */
|
|
57
|
-
onLogout?: () => void;
|
|
58
|
-
/** Enable file attachments in the chat input */
|
|
59
|
-
enableAttachments?: boolean;
|
|
60
|
-
/**
|
|
61
|
-
* Initial message to send automatically when chat loads
|
|
62
|
-
* (triggers normal API call after a short delay)
|
|
63
|
-
*/
|
|
64
|
-
initialMessage?: string;
|
|
65
|
-
/**
|
|
66
|
-
* Initial pre-made Q&A to display when chat loads
|
|
67
|
-
* (instant display with simulated streaming, no API call)
|
|
68
|
-
*/
|
|
69
|
-
initialPreMadeQA?: {
|
|
70
|
-
question: string;
|
|
71
|
-
answer: string;
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* Interceptor called before each outgoing API request.
|
|
75
|
-
* Return `true` to allow the request, `false` to block it.
|
|
76
|
-
* Can be async (e.g., to show a login modal).
|
|
77
|
-
* If not provided, all requests are allowed.
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* // Block requests and show login modal
|
|
81
|
-
* onBeforeRequest={async () => {
|
|
82
|
-
* if (!isLoggedIn) {
|
|
83
|
-
* showLoginModal();
|
|
84
|
-
* return false; // Block the request
|
|
85
|
-
* }
|
|
86
|
-
* return true; // Allow the request
|
|
87
|
-
* }}
|
|
88
|
-
*/
|
|
89
|
-
onBeforeRequest?: () => boolean | Promise<boolean>;
|
|
90
|
-
/**
|
|
91
|
-
* Mock response to show when onBeforeRequest returns false.
|
|
92
|
-
* If set, instead of throwing an error, this message will be streamed as a response.
|
|
93
|
-
* Can be a string or a function that returns a string (called each time a request is blocked).
|
|
94
|
-
* Useful for showing helpful messages like "Complete setup before chatting".
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
* // Show friendly message when chat is not ready (static)
|
|
98
|
-
* mockResponseOnBlocked="Complete the setup on the left before we can start chatting!"
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* // Show different messages each time (dynamic)
|
|
102
|
-
* const messages = ["First message", "Second message", "Third message"];
|
|
103
|
-
* let count = 0;
|
|
104
|
-
* mockResponseOnBlocked={() => messages[count++ % messages.length]}
|
|
105
|
-
*/
|
|
106
|
-
mockResponseOnBlocked?: string | (() => string);
|
|
107
|
-
}
|
|
19
|
+
export type { CuadraChatProps, CuadraChatPropsV2, CuadraChatPropsLegacy, CuadraConnectionConfig, CuadraChatConfig, CuadraUIConfig, CuadraCallbacks, CuadraInterceptors, CuadraPreMadeConfig, CuadraInitialState, CuadraSuggestion, } from '../types/props';
|
|
108
20
|
/**
|
|
109
21
|
* All-in-one Cuadra Chat component
|
|
110
22
|
*
|
|
111
|
-
*
|
|
112
|
-
* consistent styling and behavior with the widget version.
|
|
23
|
+
* Supports both V2 grouped props (recommended) and legacy flat props.
|
|
113
24
|
*
|
|
114
|
-
*
|
|
115
|
-
* import '@cuadra-ai/uikit/styles' if they need explicit control.
|
|
25
|
+
* ## V2 Props (Recommended)
|
|
116
26
|
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
27
|
+
* ```tsx
|
|
28
|
+
* <CuadraChat
|
|
29
|
+
* connection={{
|
|
30
|
+
* baseUrl: 'https://api.cuadra.ai',
|
|
31
|
+
* sessionToken: 'your-token',
|
|
32
|
+
* }}
|
|
33
|
+
* chat={{
|
|
34
|
+
* mode: 'multiChat',
|
|
35
|
+
* modelId: 'your-model-id',
|
|
36
|
+
* enableReasoning: true,
|
|
37
|
+
* }}
|
|
38
|
+
* ui={{
|
|
39
|
+
* theme: 'dark',
|
|
40
|
+
* welcomeTitle: 'Welcome!',
|
|
41
|
+
* suggestions: [{ prompt: 'What can you do?' }],
|
|
42
|
+
* }}
|
|
43
|
+
* callbacks={{
|
|
44
|
+
* onChatCreated: (id) => console.log('Chat:', id),
|
|
45
|
+
* }}
|
|
46
|
+
* />
|
|
47
|
+
* ```
|
|
120
48
|
*
|
|
121
|
-
*
|
|
122
|
-
* // With ref for external control
|
|
123
|
-
* const chatRef = useRef<CuadraChatHandle>(null);
|
|
124
|
-
* <CuadraChat ref={chatRef} ... />
|
|
125
|
-
* chatRef.current?.sendMessage("Hello!");
|
|
49
|
+
* ## Legacy Props (Still Supported)
|
|
126
50
|
*
|
|
127
|
-
*
|
|
128
|
-
* // With pre-made suggestions
|
|
51
|
+
* ```tsx
|
|
129
52
|
* <CuadraChat
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
53
|
+
* baseUrl="https://api.cuadra.ai"
|
|
54
|
+
* sessionToken="your-token"
|
|
55
|
+
* mode="multiChat"
|
|
56
|
+
* modelId="your-model-id"
|
|
57
|
+
* enableReasoning={true}
|
|
58
|
+
* theme="dark"
|
|
59
|
+
* welcomeTitle="Welcome!"
|
|
134
60
|
* />
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* ## External Control
|
|
64
|
+
*
|
|
65
|
+
* Use `CuadraChatProvider` and `useCuadraChat()` hook for context-based control:
|
|
66
|
+
*
|
|
67
|
+
* ```tsx
|
|
68
|
+
* <CuadraChatProvider>
|
|
69
|
+
* <CuadraChat connection={{ baseUrl: '...' }} />
|
|
70
|
+
* <MyControlsComponent /> {/* Can use useCuadraChat() *\/}
|
|
71
|
+
* </CuadraChatProvider>
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* Or use a ref for direct control:
|
|
75
|
+
*
|
|
76
|
+
* ```tsx
|
|
77
|
+
* const chatRef = useRef<CuadraChatHandle>(null);
|
|
78
|
+
* <CuadraChat ref={chatRef} connection={{ baseUrl: '...' }} />
|
|
79
|
+
* chatRef.current?.sendMessage('Hello!');
|
|
80
|
+
* ```
|
|
135
81
|
*/
|
|
136
82
|
export declare const CuadraChat: import("react").ForwardRefExoticComponent<CuadraChatProps & import("react").RefAttributes<CuadraChatHandle>>;
|
|
137
83
|
//# sourceMappingURL=CuadraChat.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CuadraChat.d.ts","sourceRoot":"","sources":["../../src/components/CuadraChat.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CuadraChat.d.ts","sourceRoot":"","sources":["../../src/components/CuadraChat.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,eAAe,EAA6D,MAAM,gBAAgB,CAAC;AAEjH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC;;;OAGG;IACH,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACjH,6CAA6C;IAC7C,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAGD,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAkHxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,eAAO,MAAM,UAAU,8GAyBtB,CAAC"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { type ReactNode, type RefObject } from 'react';
|
|
2
|
+
import type { CuadraChatHandle } from './CuadraChat';
|
|
3
|
+
/**
|
|
4
|
+
* Context for accessing CuadraChat controls from any child component
|
|
5
|
+
*
|
|
6
|
+
* This provides a React-idiomatic way to control the chat component
|
|
7
|
+
* from anywhere in your component tree without prop drilling.
|
|
8
|
+
*
|
|
9
|
+
* @example Using in a parent component
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { CuadraChat, CuadraChatProvider, useCuadraChat } from '@cuadra-ai/uikit';
|
|
12
|
+
*
|
|
13
|
+
* function App() {
|
|
14
|
+
* return (
|
|
15
|
+
* <CuadraChatProvider>
|
|
16
|
+
* <CuadraChat connection={{ baseUrl: '...' }} />
|
|
17
|
+
* <MyCustomControls />
|
|
18
|
+
* </CuadraChatProvider>
|
|
19
|
+
* );
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* function MyCustomControls() {
|
|
23
|
+
* const { controls } = useCuadraChat();
|
|
24
|
+
*
|
|
25
|
+
* return (
|
|
26
|
+
* <button onClick={() => controls?.sendMessage('Hello!')}>
|
|
27
|
+
* Send Hello
|
|
28
|
+
* </button>
|
|
29
|
+
* );
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export interface CuadraChatContextValue {
|
|
34
|
+
/**
|
|
35
|
+
* Reference to the CuadraChat controls
|
|
36
|
+
* May be null before the CuadraChat component mounts
|
|
37
|
+
*/
|
|
38
|
+
controls: CuadraChatHandle | null;
|
|
39
|
+
/**
|
|
40
|
+
* Internal: Reference setter for CuadraChat to register itself
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
registerControls: (controls: CuadraChatHandle) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Internal: Reference clearer for CuadraChat to unregister on unmount
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
unregisterControls: () => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Context for CuadraChat controls
|
|
52
|
+
*
|
|
53
|
+
* Default value is null - use CuadraChatProvider to provide an actual value.
|
|
54
|
+
* Consumers can check if context is null to detect missing provider.
|
|
55
|
+
*/
|
|
56
|
+
export declare const CuadraChatContext: import("react").Context<CuadraChatContextValue | null>;
|
|
57
|
+
/**
|
|
58
|
+
* Hook to access CuadraChat controls from any child component
|
|
59
|
+
*
|
|
60
|
+
* @returns Object containing `controls` (CuadraChatHandle | null) and `isReady` boolean
|
|
61
|
+
* @throws Error if used outside of CuadraChatProvider
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* function MyComponent() {
|
|
66
|
+
* const { controls, isReady } = useCuadraChat();
|
|
67
|
+
*
|
|
68
|
+
* if (!isReady) {
|
|
69
|
+
* return <span>Chat is loading...</span>;
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* return (
|
|
73
|
+
* <button onClick={() => controls.sendMessage('Hi!')}>
|
|
74
|
+
* Send Message
|
|
75
|
+
* </button>
|
|
76
|
+
* );
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function useCuadraChat(): {
|
|
81
|
+
controls: CuadraChatHandle | null;
|
|
82
|
+
isReady: boolean;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Hook to optionally access CuadraChat controls
|
|
86
|
+
*
|
|
87
|
+
* Unlike useCuadraChat, this doesn't throw if the provider is missing.
|
|
88
|
+
* Returns null if CuadraChatProvider is not present.
|
|
89
|
+
*
|
|
90
|
+
* @returns Object with controls and isReady, or null if no provider
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```tsx
|
|
94
|
+
* function OptionalChatControl() {
|
|
95
|
+
* const chat = useCuadraChatOptional();
|
|
96
|
+
*
|
|
97
|
+
* if (!chat) {
|
|
98
|
+
* // No CuadraChatProvider in tree - gracefully handle
|
|
99
|
+
* return null;
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* return chat.isReady ? (
|
|
103
|
+
* <button onClick={() => chat.controls?.sendMessage('Hi!')}>Send</button>
|
|
104
|
+
* ) : null;
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export declare function useCuadraChatOptional(): {
|
|
109
|
+
controls: CuadraChatHandle | null;
|
|
110
|
+
isReady: boolean;
|
|
111
|
+
} | null;
|
|
112
|
+
/**
|
|
113
|
+
* Provider component for CuadraChat context
|
|
114
|
+
*
|
|
115
|
+
* Wrap your component tree with this to enable useCuadraChat hook
|
|
116
|
+
* access from any descendant component.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```tsx
|
|
120
|
+
* function App() {
|
|
121
|
+
* return (
|
|
122
|
+
* <CuadraChatProvider>
|
|
123
|
+
* <Header />
|
|
124
|
+
* <CuadraChat connection={{ baseUrl: '...' }} />
|
|
125
|
+
* <Sidebar />
|
|
126
|
+
* </CuadraChatProvider>
|
|
127
|
+
* );
|
|
128
|
+
* }
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
export interface CuadraChatProviderProps {
|
|
132
|
+
children: ReactNode;
|
|
133
|
+
}
|
|
134
|
+
export declare function CuadraChatProvider({ children }: CuadraChatProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
135
|
+
/**
|
|
136
|
+
* Helper to create a ref object that syncs with context
|
|
137
|
+
* Used internally by CuadraChat to register itself with the context
|
|
138
|
+
* @internal
|
|
139
|
+
*/
|
|
140
|
+
export declare function createContextualRef(registerControls: (controls: CuadraChatHandle) => void, unregisterControls: () => void): RefObject<CuadraChatHandle | null>;
|
|
141
|
+
//# sourceMappingURL=CuadraChatContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CuadraChatContext.d.ts","sourceRoot":"","sources":["../../src/components/CuadraChatContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAE,KAAK,SAAS,EAAqC,MAAM,OAAO,CAAC;AACzG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAElC;;;OAGG;IACH,gBAAgB,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAEvD;;;OAGG;IACH,kBAAkB,EAAE,MAAM,IAAI,CAAC;CAChC;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,wDAAqD,CAAC;AAIpF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,IAAI;IAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAcvF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,qBAAqB,IAAI;IAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAWtG;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,EAAE,uBAAuB,2CAsBvE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,EACtD,kBAAkB,EAAE,MAAM,IAAI,GAC7B,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAgBpC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Component, type ErrorInfo, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for CuadraErrorBoundary
|
|
4
|
+
*/
|
|
5
|
+
export interface CuadraErrorBoundaryProps {
|
|
6
|
+
/** Child components to wrap */
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* Custom fallback UI or render function
|
|
10
|
+
* If not provided, DefaultErrorFallback is used
|
|
11
|
+
*/
|
|
12
|
+
fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
|
|
13
|
+
/**
|
|
14
|
+
* Callback when an error is caught
|
|
15
|
+
* Use for logging, analytics, etc.
|
|
16
|
+
*/
|
|
17
|
+
onError?: (error: Error, errorInfo: ErrorInfo) => void;
|
|
18
|
+
}
|
|
19
|
+
interface ErrorBoundaryState {
|
|
20
|
+
hasError: boolean;
|
|
21
|
+
error: Error | null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Error boundary component for CuadraChat
|
|
25
|
+
*
|
|
26
|
+
* Catches JavaScript errors in child component tree and displays
|
|
27
|
+
* a fallback UI instead of crashing the entire application.
|
|
28
|
+
*
|
|
29
|
+
* @example Basic usage (uses default fallback)
|
|
30
|
+
* ```tsx
|
|
31
|
+
* <CuadraErrorBoundary>
|
|
32
|
+
* <CuadraChat {...props} />
|
|
33
|
+
* </CuadraErrorBoundary>
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example With custom fallback
|
|
37
|
+
* ```tsx
|
|
38
|
+
* <CuadraErrorBoundary
|
|
39
|
+
* fallback={<div>Oops! Something went wrong.</div>}
|
|
40
|
+
* >
|
|
41
|
+
* <CuadraChat {...props} />
|
|
42
|
+
* </CuadraErrorBoundary>
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example With render function fallback
|
|
46
|
+
* ```tsx
|
|
47
|
+
* <CuadraErrorBoundary
|
|
48
|
+
* fallback={(error, reset) => (
|
|
49
|
+
* <div>
|
|
50
|
+
* <p>Error: {error.message}</p>
|
|
51
|
+
* <button onClick={reset}>Retry</button>
|
|
52
|
+
* </div>
|
|
53
|
+
* )}
|
|
54
|
+
* onError={(error, info) => {
|
|
55
|
+
* console.error('Chat error:', error);
|
|
56
|
+
* analytics.track('chat_error', { message: error.message });
|
|
57
|
+
* }}
|
|
58
|
+
* >
|
|
59
|
+
* <CuadraChat {...props} />
|
|
60
|
+
* </CuadraErrorBoundary>
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare class CuadraErrorBoundary extends Component<CuadraErrorBoundaryProps, ErrorBoundaryState> {
|
|
64
|
+
constructor(props: CuadraErrorBoundaryProps);
|
|
65
|
+
static getDerivedStateFromError(error: Error): ErrorBoundaryState;
|
|
66
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
|
|
67
|
+
/**
|
|
68
|
+
* Reset the error state and attempt to re-render children
|
|
69
|
+
*/
|
|
70
|
+
reset: () => void;
|
|
71
|
+
render(): ReactNode;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Hook-friendly wrapper for error boundary
|
|
75
|
+
* Use when you need to reset error boundary from a child component
|
|
76
|
+
*/
|
|
77
|
+
export declare function withErrorBoundary<P extends object>(WrappedComponent: React.ComponentType<P>, errorBoundaryProps?: Omit<CuadraErrorBoundaryProps, 'children'>): React.FC<P>;
|
|
78
|
+
export {};
|
|
79
|
+
//# sourceMappingURL=ErrorBoundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/components/ErrorBoundary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,+BAA+B;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAC,CAAC;IACxE;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;CACxD;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAiDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,mBAAoB,SAAQ,SAAS,CAAC,wBAAwB,EAAE,kBAAkB,CAAC;gBAClF,KAAK,EAAE,wBAAwB;IAK3C,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,kBAAkB;IAIjE,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI;IAI3D;;OAEG;IACH,KAAK,QAAO,IAAI,CAEd;IAEF,MAAM,IAAI,SAAS;CAqBpB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAChD,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EACxC,kBAAkB,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,GAC9D,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAUb"}
|