@chainai/react 1.0.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 ADDED
@@ -0,0 +1,227 @@
1
+ # @chain-ai/react
2
+
3
+ React components for Chain AI - Embeddable blockchain AI assistant.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @chain-ai/react @chain-ai/core
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { ChainAI } from '@chain-ai/react';
15
+
16
+ function App() {
17
+ return (
18
+ <ChainAI
19
+ config={{ apiKey: 'sk_dev_123_...' }}
20
+ height="600px"
21
+ placeholder="Ask me anything about blockchain..."
22
+ />
23
+ );
24
+ }
25
+ ```
26
+
27
+ ## Features
28
+
29
+ - ✅ **Simplified Components** - 94% reduction from 2,556 lines to ~360 lines
30
+ - ✅ **Customizable Theming** - Dark/light themes with full CSS customization
31
+ - ✅ **Real-time Streaming** - Word-by-word response streaming
32
+ - ✅ **Type Safe** - Full TypeScript support
33
+ - ✅ **Responsive** - Works on all screen sizes
34
+ - ✅ **Accessible** - Keyboard navigation support
35
+
36
+ ## Basic Usage
37
+
38
+ ### Standalone Component
39
+
40
+ ```typescript
41
+ import { ChainAI } from '@chain-ai/react';
42
+
43
+ function App() {
44
+ return (
45
+ <ChainAI
46
+ config={{
47
+ apiKey: 'sk_dev_123_...',
48
+ host: 'https://icp0.io', // optional
49
+ }}
50
+ height="600px"
51
+ theme={darkTheme}
52
+ placeholder="Message Chain AI..."
53
+ showHeader={true}
54
+ headerTitle="Blockchain Assistant"
55
+ onMessage={(msg) => console.log('User sent:', msg)}
56
+ />
57
+ );
58
+ }
59
+ ```
60
+
61
+ ### Advanced Usage with Provider
62
+
63
+ ```typescript
64
+ import { ChainAIProvider, useChainAI, useChat } from '@chain-ai/react';
65
+
66
+ function App() {
67
+ return (
68
+ <ChainAIProvider
69
+ config={{
70
+ apiKey: 'sk_dev_123_...',
71
+ }}
72
+ >
73
+ <MyCustomChat />
74
+ </ChainAIProvider>
75
+ );
76
+ }
77
+
78
+ function MyCustomChat() {
79
+ const { messages, sendMessage, isLoading } = useChat();
80
+
81
+ return (
82
+ <div>
83
+ {messages.map(msg => (
84
+ <div key={msg.id}>{msg.content}</div>
85
+ ))}
86
+ <button onClick={() => sendMessage('What is BTC price?')}>
87
+ Get BTC Price
88
+ </button>
89
+ </div>
90
+ );
91
+ }
92
+ ```
93
+
94
+ ## Props
95
+
96
+ ### ChainAI Component
97
+
98
+ | Prop | Type | Default | Description |
99
+ |------|------|---------|-------------|
100
+ | `config` | `ChainAIConfig` | **required** | API key and configuration |
101
+ | `conversationId` | `string` | `'default'` | Unique conversation identifier |
102
+ | `theme` | `Theme` | `defaultTheme` | Color scheme and styling |
103
+ | `className` | `string` | `''` | Additional CSS classes |
104
+ | `height` | `string \| number` | `'600px'` | Component height |
105
+ | `placeholder` | `string` | `'Ask me anything...'` | Input placeholder text |
106
+ | `showHeader` | `boolean` | `true` | Show/hide header bar |
107
+ | `headerTitle` | `string` | `'Chain AI'` | Header title text |
108
+ | `onMessage` | `(msg: string) => void` | - | Callback when user sends message |
109
+
110
+ ## Theming
111
+
112
+ ### Built-in Themes
113
+
114
+ ```typescript
115
+ import { ChainAI, darkTheme, lightTheme } from '@chain-ai/react';
116
+
117
+ // Dark theme
118
+ <ChainAI config={config} theme={darkTheme} />
119
+
120
+ // Light theme
121
+ <ChainAI config={config} theme={lightTheme} />
122
+ ```
123
+
124
+ ### Custom Theme
125
+
126
+ ```typescript
127
+ import { ChainAI, Theme } from '@chain-ai/react';
128
+
129
+ const customTheme: Theme = {
130
+ colors: {
131
+ primary: '#6366f1',
132
+ primaryText: '#ffffff',
133
+ background: '#0f172a',
134
+ text: '#f8fafc',
135
+ border: '#1e293b',
136
+ userMessage: '#6366f1',
137
+ userMessageText: '#ffffff',
138
+ assistantMessage: '#1e293b',
139
+ assistantMessageText: '#f8fafc',
140
+ inputBackground: '#1e293b',
141
+ headerBackground: '#020617',
142
+ headerText: '#f8fafc',
143
+ },
144
+ fonts: {
145
+ body: 'Inter, sans-serif',
146
+ heading: 'Inter, sans-serif',
147
+ },
148
+ spacing: {
149
+ small: '8px',
150
+ medium: '16px',
151
+ large: '24px',
152
+ },
153
+ };
154
+
155
+ <ChainAI config={config} theme={customTheme} />
156
+ ```
157
+
158
+ ## Hooks
159
+
160
+ ### useChainAI()
161
+
162
+ Access the Chain AI client and customization settings.
163
+
164
+ ```typescript
165
+ const { client, isReady, error, customization, updateCustomization } = useChainAI();
166
+ ```
167
+
168
+ ### useChat(conversationId?)
169
+
170
+ Manage chat messages and state.
171
+
172
+ ```typescript
173
+ const { messages, isLoading, error, sendMessage, clearMessages } = useChat('my-conversation');
174
+ ```
175
+
176
+ ## Components
177
+
178
+ ### Individual Components
179
+
180
+ You can use individual components for custom layouts:
181
+
182
+ ```typescript
183
+ import {
184
+ ChainAIProvider,
185
+ ChatMessage,
186
+ ChatInput,
187
+ ChatHeader,
188
+ useChat,
189
+ defaultTheme,
190
+ } from '@chain-ai/react';
191
+
192
+ function CustomLayout() {
193
+ const { messages, sendMessage, isLoading } = useChat();
194
+
195
+ return (
196
+ <div>
197
+ <ChatHeader title="My Custom Chat" theme={defaultTheme} />
198
+ {messages.map(msg => (
199
+ <ChatMessage key={msg.id} message={msg} theme={defaultTheme} />
200
+ ))}
201
+ <ChatInput
202
+ onSend={sendMessage}
203
+ disabled={isLoading}
204
+ theme={defaultTheme}
205
+ />
206
+ </div>
207
+ );
208
+ }
209
+ ```
210
+
211
+ ## TypeScript
212
+
213
+ Full TypeScript support with exported types:
214
+
215
+ ```typescript
216
+ import type {
217
+ ChainAIProps,
218
+ Theme,
219
+ Message,
220
+ ChainAIConfig,
221
+ ResponseCustomization,
222
+ } from '@chain-ai/react';
223
+ ```
224
+
225
+ ## License
226
+
227
+ MIT
@@ -0,0 +1,22 @@
1
+ /**
2
+ * ActionPrompt - UI for handling incomplete actions
3
+ *
4
+ * Displays missing fields and allows users to fill them in
5
+ */
6
+ import React from 'react';
7
+ import type { Theme } from '../styles/themes';
8
+ export interface ActionPromptProps {
9
+ /** The action type (e.g., 'send', 'swap') */
10
+ action: string;
11
+ /** List of missing required fields */
12
+ missing: string[];
13
+ /** AI-generated prompt asking for the missing fields */
14
+ prompt: string;
15
+ /** Called when user submits a field value */
16
+ onSubmit: (field: string, value: string) => void;
17
+ /** Theme configuration */
18
+ theme: Theme;
19
+ /** Additional CSS class */
20
+ className?: string;
21
+ }
22
+ export declare const ActionPrompt: React.FC<ActionPromptProps>;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ /**
3
+ * ActionPrompt - UI for handling incomplete actions
4
+ *
5
+ * Displays missing fields and allows users to fill them in
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.ActionPrompt = void 0;
42
+ const react_1 = __importStar(require("react"));
43
+ // Field-specific input configurations
44
+ const fieldConfig = {
45
+ amount: { type: 'number', placeholder: '0.00', label: 'Amount' },
46
+ recipient: { type: 'text', placeholder: '0x... or wallet address', label: 'Recipient Address' },
47
+ token: { type: 'text', placeholder: 'ETH, BTC, USDC...', label: 'Token' },
48
+ address: { type: 'text', placeholder: '0x... or wallet address', label: 'Address' },
49
+ fee: { type: 'text', placeholder: 'low, medium, or high', label: 'Fee Priority' },
50
+ memo: { type: 'text', placeholder: 'Optional note', label: 'Memo' },
51
+ chain: { type: 'text', placeholder: 'Ethereum, Bitcoin...', label: 'Chain' },
52
+ slippage: { type: 'number', placeholder: '0.5', label: 'Slippage %' },
53
+ };
54
+ // Action icons
55
+ const ActionIcon = ({ action }) => {
56
+ switch (action) {
57
+ case 'send':
58
+ return (react_1.default.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
59
+ react_1.default.createElement("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
60
+ react_1.default.createElement("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })));
61
+ case 'swap':
62
+ return (react_1.default.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
63
+ react_1.default.createElement("polyline", { points: "17 1 21 5 17 9" }),
64
+ react_1.default.createElement("path", { d: "M3 11V9a4 4 0 0 1 4-4h14" }),
65
+ react_1.default.createElement("polyline", { points: "7 23 3 19 7 15" }),
66
+ react_1.default.createElement("path", { d: "M21 13v2a4 4 0 0 1-4 4H3" })));
67
+ default:
68
+ return (react_1.default.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
69
+ react_1.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
70
+ react_1.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
71
+ react_1.default.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })));
72
+ }
73
+ };
74
+ const ActionPrompt = ({ action, missing, prompt, onSubmit, theme, className = '', }) => {
75
+ const [values, setValues] = (0, react_1.useState)({});
76
+ const [focusedField, setFocusedField] = (0, react_1.useState)(null);
77
+ const handleChange = (field, value) => {
78
+ setValues((prev) => ({ ...prev, [field]: value }));
79
+ };
80
+ const handleSubmit = (e) => {
81
+ e.preventDefault();
82
+ // Submit all filled values
83
+ const filledFields = Object.entries(values).filter(([_, v]) => v.trim());
84
+ if (filledFields.length > 0) {
85
+ // Send as a combined message
86
+ const message = filledFields.map(([k, v]) => `${k}: ${v}`).join(', ');
87
+ onSubmit(filledFields[0][0], message);
88
+ }
89
+ };
90
+ const handleQuickSelect = (field, value) => {
91
+ setValues((prev) => ({ ...prev, [field]: value }));
92
+ onSubmit(field, `${field}: ${value}`);
93
+ };
94
+ // Quick selection options for certain fields
95
+ const quickOptions = {
96
+ fee: ['low', 'medium', 'high'],
97
+ token: ['ETH', 'BTC', 'USDC', 'USDT'],
98
+ chain: ['Ethereum', 'Bitcoin', 'Solana', 'ICP'],
99
+ };
100
+ return (react_1.default.createElement("div", { className: `chain-ai-action-prompt ${className}` },
101
+ react_1.default.createElement("div", { className: "chain-ai-action-prompt-header" },
102
+ react_1.default.createElement("div", { className: "chain-ai-action-prompt-icon", style: { color: theme.colors.primary } },
103
+ react_1.default.createElement(ActionIcon, { action: action })),
104
+ react_1.default.createElement("div", { className: "chain-ai-action-prompt-title" },
105
+ react_1.default.createElement("span", { className: "chain-ai-action-prompt-action" }, action.toUpperCase()),
106
+ react_1.default.createElement("span", { className: "chain-ai-action-prompt-label" }, "Missing information"))),
107
+ react_1.default.createElement("p", { className: "chain-ai-action-prompt-message" }, prompt),
108
+ react_1.default.createElement("form", { onSubmit: handleSubmit, className: "chain-ai-action-prompt-form" },
109
+ missing.map((field) => {
110
+ const config = fieldConfig[field] || {
111
+ type: 'text',
112
+ placeholder: `Enter ${field}`,
113
+ label: field.charAt(0).toUpperCase() + field.slice(1),
114
+ };
115
+ return (react_1.default.createElement("div", { key: field, className: `chain-ai-action-prompt-field ${focusedField === field ? 'focused' : ''}` },
116
+ react_1.default.createElement("label", { className: "chain-ai-action-prompt-field-label" }, config.label),
117
+ quickOptions[field] && (react_1.default.createElement("div", { className: "chain-ai-action-prompt-quick-options" }, quickOptions[field].map((option) => (react_1.default.createElement("button", { key: option, type: "button", className: "chain-ai-action-prompt-quick-btn", onClick: () => handleQuickSelect(field, option), style: {
118
+ borderColor: theme.colors.border,
119
+ color: theme.colors.text,
120
+ } }, option))))),
121
+ react_1.default.createElement("input", { type: config.type, className: "chain-ai-action-prompt-input", placeholder: config.placeholder, value: values[field] || '', onChange: (e) => handleChange(field, e.target.value), onFocus: () => setFocusedField(field), onBlur: () => setFocusedField(null), style: {
122
+ borderColor: focusedField === field ? theme.colors.primary : theme.colors.border,
123
+ } })));
124
+ }),
125
+ react_1.default.createElement("button", { type: "submit", className: "chain-ai-action-prompt-submit", disabled: Object.values(values).every((v) => !v.trim()), style: {
126
+ backgroundColor: theme.colors.primary,
127
+ color: theme.colors.primaryText,
128
+ } }, "Continue"))));
129
+ };
130
+ exports.ActionPrompt = ActionPrompt;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * ChainAI - Main chat component (simplified from 2,556-line playground)
3
+ */
4
+ import React from 'react';
5
+ import type { ChainAIConfig } from '@chainai/core';
6
+ import type { Theme } from '../styles/themes';
7
+ import '../styles/default.css';
8
+ export interface ChainAIProps {
9
+ config: ChainAIConfig;
10
+ conversationId?: string;
11
+ theme?: Theme;
12
+ className?: string;
13
+ height?: string | number;
14
+ placeholder?: string;
15
+ showHeader?: boolean;
16
+ headerTitle?: string;
17
+ onMessage?: (message: string) => void;
18
+ }
19
+ export declare const ChainAI: React.FC<ChainAIProps>;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ /**
3
+ * ChainAI - Main chat component (simplified from 2,556-line playground)
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ChainAI = void 0;
40
+ const react_1 = __importStar(require("react"));
41
+ const ChainAIProvider_1 = require("../context/ChainAIProvider");
42
+ const useChat_1 = require("../hooks/useChat");
43
+ const ChatMessage_1 = require("./ChatMessage");
44
+ const ChatInput_1 = require("./ChatInput");
45
+ const ChatHeader_1 = require("./ChatHeader");
46
+ const themes_1 = require("../styles/themes");
47
+ require("../styles/default.css");
48
+ const ChainAIInner = ({ conversationId, theme = themes_1.defaultTheme, className = '', height = '600px', placeholder = 'Ask me anything about blockchain...', showHeader = true, headerTitle = 'Chain AI', onMessage, }) => {
49
+ const { isReady, error: clientError } = (0, ChainAIProvider_1.useChainAI)();
50
+ const { messages, isLoading, error, sendMessage } = (0, useChat_1.useChat)(conversationId);
51
+ const messagesEndRef = (0, react_1.useRef)(null);
52
+ // Auto-scroll to bottom when new messages arrive
53
+ (0, react_1.useEffect)(() => {
54
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
55
+ }, [messages]);
56
+ const handleSend = async (text) => {
57
+ onMessage?.(text);
58
+ await sendMessage(text);
59
+ };
60
+ if (!isReady) {
61
+ return (react_1.default.createElement("div", { className: `chain-ai-container ${className}`, style: { height } },
62
+ react_1.default.createElement("div", { className: "chain-ai-loading" }, "Initializing Chain AI...")));
63
+ }
64
+ if (clientError) {
65
+ return (react_1.default.createElement("div", { className: `chain-ai-container ${className}`, style: { height } },
66
+ react_1.default.createElement("div", { className: "chain-ai-error" },
67
+ "Error: ",
68
+ clientError)));
69
+ }
70
+ return (react_1.default.createElement("div", { className: `chain-ai-container ${className}`, style: {
71
+ height,
72
+ backgroundColor: theme.colors.background,
73
+ color: theme.colors.text,
74
+ } },
75
+ showHeader && react_1.default.createElement(ChatHeader_1.ChatHeader, { title: headerTitle, theme: theme }),
76
+ react_1.default.createElement("div", { className: "chain-ai-messages" },
77
+ messages.length === 0 && (react_1.default.createElement("div", { className: "chain-ai-welcome" },
78
+ react_1.default.createElement("h2", null, "Welcome to Chain AI"),
79
+ react_1.default.createElement("p", null, "Ask me anything about blockchain operations"))),
80
+ messages.map((message) => (react_1.default.createElement(ChatMessage_1.ChatMessage, { key: message.id, message: message, theme: theme }))),
81
+ error && react_1.default.createElement("div", { className: "chain-ai-error" }, error),
82
+ react_1.default.createElement("div", { ref: messagesEndRef })),
83
+ react_1.default.createElement(ChatInput_1.ChatInput, { onSend: handleSend, placeholder: placeholder, disabled: isLoading, theme: theme })));
84
+ };
85
+ const ChainAI = ({ config, ...props }) => {
86
+ return (react_1.default.createElement(ChainAIProvider_1.ChainAIProvider, { config: config },
87
+ react_1.default.createElement(ChainAIInner, { ...props })));
88
+ };
89
+ exports.ChainAI = ChainAI;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * ChainAIWidget - Fully customizable floating chat widget
3
+ *
4
+ * Features:
5
+ * - Floating action button (FAB) that expands to chat
6
+ * - Full branding customization (logo, colors, text)
7
+ * - CSS variables for easy styling
8
+ * - Works in any context (web, extension, mobile)
9
+ */
10
+ import React from 'react';
11
+ import type { ChainAIConfig } from '@chainai/core';
12
+ import type { Theme } from '../styles/themes';
13
+ import '../styles/widget.css';
14
+ /** Branding configuration for white-labeling */
15
+ export interface BrandingConfig {
16
+ /** Company/product name shown in header */
17
+ name?: string;
18
+ /** Logo as image URL or React component */
19
+ logo?: string | React.ReactNode;
20
+ /** Avatar shown next to AI messages (URL or React component) */
21
+ avatar?: string | React.ReactNode;
22
+ /** Welcome screen title */
23
+ welcomeTitle?: string;
24
+ /** Welcome screen message */
25
+ welcomeMessage?: string;
26
+ /** Custom welcome screen content (replaces default) */
27
+ welcomeContent?: React.ReactNode;
28
+ /** Show "Powered by Chain AI" badge */
29
+ showPoweredBy?: boolean;
30
+ /** Custom FAB icon when closed */
31
+ fabIcon?: React.ReactNode;
32
+ /** Custom FAB icon when open */
33
+ fabIconOpen?: React.ReactNode;
34
+ /** Custom send button icon */
35
+ sendIcon?: React.ReactNode;
36
+ /** Custom header content (replaces default header) */
37
+ headerContent?: React.ReactNode;
38
+ /** Gradient colors for avatar background [start, end] */
39
+ avatarGradient?: [string, string];
40
+ }
41
+ /** Dimension configuration for the widget */
42
+ export interface DimensionConfig {
43
+ /** FAB button size in pixels */
44
+ fabSize?: number;
45
+ /** Chat window width */
46
+ windowWidth?: number | string;
47
+ /** Chat window height */
48
+ windowHeight?: number | string;
49
+ /** Border radius for FAB */
50
+ fabBorderRadius?: number | string;
51
+ /** Border radius for window */
52
+ windowBorderRadius?: number | string;
53
+ /** Offset from edge (applies to position) */
54
+ offset?: number;
55
+ }
56
+ export interface ChainAIWidgetProps {
57
+ config: ChainAIConfig;
58
+ /** Branding/white-label configuration */
59
+ branding?: BrandingConfig;
60
+ /** Dimension/size configuration */
61
+ dimensions?: DimensionConfig;
62
+ /** Initial open state */
63
+ defaultOpen?: boolean;
64
+ /** Position of the widget */
65
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
66
+ /** Custom position (overrides position preset) */
67
+ customPosition?: {
68
+ top?: number | string;
69
+ right?: number | string;
70
+ bottom?: number | string;
71
+ left?: number | string;
72
+ };
73
+ /** Custom theme colors */
74
+ theme?: Partial<Theme>;
75
+ /** Additional CSS class for the container */
76
+ className?: string;
77
+ /** Placeholder text for input */
78
+ placeholder?: string;
79
+ /** Z-index for the widget */
80
+ zIndex?: number;
81
+ /** Called when widget opens/closes */
82
+ onToggle?: (isOpen: boolean) => void;
83
+ /** Called when user sends a message */
84
+ onMessage?: (message: string) => void;
85
+ }
86
+ export declare const ChainAIWidget: React.FC<ChainAIWidgetProps>;