@hsafa/ui-sdk 0.2.5 → 0.3.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.
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import * as react from 'react';
2
- import react__default, { ComponentType } from 'react';
1
+ import * as React$1 from 'react';
2
+ import React__default, { ComponentType } from 'react';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
 
5
5
  /**
6
6
  * Props for the Button component
7
7
  */
8
- interface ButtonProps extends react__default.ButtonHTMLAttributes<HTMLButtonElement> {
8
+ interface ButtonProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
9
9
  /** Visual style variant of the button */
10
10
  variant?: "primary" | "secondary" | "outline" | "ghost";
11
11
  /** Size of the button */
@@ -13,7 +13,7 @@ interface ButtonProps extends react__default.ButtonHTMLAttributes<HTMLButtonElem
13
13
  /** Whether the button is in a loading state */
14
14
  loading?: boolean;
15
15
  /** Content to be displayed inside the button */
16
- children: react__default.ReactNode;
16
+ children: React__default.ReactNode;
17
17
  }
18
18
  /**
19
19
  * A versatile button component with multiple variants, sizes, and states.
@@ -33,173 +33,7 @@ interface ButtonProps extends react__default.ButtonHTMLAttributes<HTMLButtonElem
33
33
  * <Button onClick={() => console.log('Clicked!')}>Click me</Button>
34
34
  * ```
35
35
  */
36
- declare const Button: react__default.FC<ButtonProps>;
37
-
38
- /**
39
- * Vercel AI SDK compatible message types
40
- * Based on https://sdk.vercel.ai/docs/ai-sdk-core/messages
41
- */
42
- type TextPart = {
43
- type: 'text';
44
- text: string;
45
- };
46
- type ImagePart = {
47
- type: 'image';
48
- image: string | URL;
49
- mediaType?: string;
50
- };
51
- type FilePart = {
52
- type: 'file';
53
- data: string | URL;
54
- mediaType: string;
55
- name?: string;
56
- };
57
- type UserContentPart = TextPart | ImagePart | FilePart;
58
- type AssistantTextPart = {
59
- type: 'text';
60
- text: string;
61
- };
62
- type ReasoningPart = {
63
- type: 'reasoning';
64
- text: string;
65
- };
66
- type AssistantFilePart = {
67
- type: 'file';
68
- data: string | URL;
69
- mediaType: string;
70
- filename?: string;
71
- };
72
- type ToolCallPart = {
73
- type: 'tool-call';
74
- toolCallId: string;
75
- toolName: string;
76
- input: any;
77
- };
78
- type AssistantContentPart = AssistantTextPart | ReasoningPart | AssistantFilePart | ToolCallPart;
79
- interface Attachment {
80
- id: string;
81
- name: string;
82
- url: string;
83
- mimeType: string;
84
- size: number;
85
- }
86
-
87
- /**
88
- * Type definitions for the HsafaChat component
89
- */
90
-
91
- type MainAgentAction$1 = {
92
- type: 'reasoning';
93
- reasoning: string;
94
- status: 'streaming' | 'finished';
95
- startDate?: number;
96
- endDate?: number;
97
- durationMs?: number;
98
- } | {
99
- type: 'tool-call';
100
- toolCallId?: string;
101
- toolName?: string;
102
- input?: any;
103
- inputText?: string;
104
- output?: any;
105
- status: 'input_streaming' | 'running' | 'finished' | 'error';
106
- error?: string;
107
- startDate?: number;
108
- endDate?: number;
109
- durationMs?: number;
110
- } | {
111
- type: 'step';
112
- stepNumber?: number;
113
- finishReason?: string;
114
- usage?: any;
115
- startDate?: number;
116
- endDate?: number;
117
- durationMs?: number;
118
- } | {
119
- type: 'text';
120
- text: string;
121
- status: 'streaming' | 'finished';
122
- startDate?: number;
123
- endDate?: number;
124
- durationMs?: number;
125
- } | {
126
- type: 'source';
127
- source: any;
128
- durationMs?: number;
129
- } | {
130
- type: 'file';
131
- file: any;
132
- durationMs?: number;
133
- } | {
134
- type: 'response';
135
- items: any[];
136
- [key: string]: any;
137
- startDate?: number;
138
- endDate?: number;
139
- durationMs?: number;
140
- };
141
- type ChatMessage = {
142
- id: string;
143
- role: 'user';
144
- content: string | UserContentPart[];
145
- createdAt?: number;
146
- text?: string;
147
- attachments?: Attachment[];
148
- } | {
149
- id: string;
150
- role: 'assistant';
151
- content?: string | AssistantContentPart[];
152
- items: any[];
153
- reasoning?: string;
154
- reasoningOpen?: boolean;
155
- reasoningTokens?: number;
156
- createdAt?: number;
157
- requestParams?: any;
158
- mcpToolCalls?: Array<{
159
- toolName: string;
160
- args: any;
161
- timestamp: number;
162
- status?: 'pending' | 'running' | 'completed' | 'failed';
163
- }>;
164
- mcpToolResults?: Record<string, any>;
165
- mainAgentActions?: MainAgentAction$1[];
166
- firstAgentMessage?: string;
167
- firstAgentContinue?: boolean;
168
- autoGenerated?: boolean;
169
- hidden?: boolean;
170
- turnIndex?: number;
171
- controlDecision?: 'continue' | 'done';
172
- followUpPrompt?: string;
173
- };
174
- interface HsafaChatProps {
175
- agentId: string;
176
- theme?: 'dark' | 'light';
177
- primaryColor?: string;
178
- backgroundColor?: string;
179
- borderColor?: string;
180
- textColor?: string;
181
- accentColor?: string;
182
- width?: number | string;
183
- maxWidth?: number | string;
184
- height?: string;
185
- expandable?: boolean;
186
- alwaysOpen?: boolean;
187
- defaultOpen?: boolean;
188
- floatingButtonPosition?: {
189
- bottom?: number | string;
190
- right?: number | string;
191
- top?: number | string;
192
- left?: number | string;
193
- };
194
- placeholder?: string;
195
- title?: string;
196
- className?: string;
197
- chatContainerClassName?: string;
198
- dir?: 'rtl' | 'ltr';
199
- language?: 'en' | 'ar';
200
- defaultReasoningOpen?: boolean;
201
- hideReasoningContent?: boolean;
202
- }
36
+ declare const Button: React__default.FC<ButtonProps>;
203
37
 
204
38
  declare const themeColors: {
205
39
  dark: {
@@ -227,57 +61,6 @@ declare const themeColors: {
227
61
  };
228
62
  type ThemeColors = typeof themeColors.dark;
229
63
 
230
- type TranslationKeys = {
231
- 'header.maximize': string;
232
- 'header.minimize': string;
233
- 'header.new': string;
234
- 'header.history': string;
235
- 'header.close': string;
236
- 'input.placeholder': string;
237
- 'input.attachFiles': string;
238
- 'input.insertLink': string;
239
- 'input.send': string;
240
- 'input.stop': string;
241
- 'input.uploadingFiles': string;
242
- 'input.previewImage': string;
243
- 'input.removeFile': string;
244
- 'editor.cancel': string;
245
- 'editor.saveAndRegenerate': string;
246
- 'editor.clickToEdit': string;
247
- 'messages.empty': string;
248
- 'messages.error': string;
249
- 'history.search': string;
250
- 'history.noChatsFound': string;
251
- 'history.untitledChat': string;
252
- 'history.deleteChat': string;
253
- 'general.agent': string;
254
- };
255
-
256
- interface MessageListProps {
257
- messages: ChatMessage[];
258
- streaming: boolean;
259
- editingMessageId: string | null;
260
- editingMessageText: string;
261
- editingAttachments?: Attachment[];
262
- error: string | null;
263
- actionStatuses: Map<string, 'executing' | 'executed'>;
264
- components: Map<string, react__default.ComponentType<any>>;
265
- theme: 'light' | 'dark';
266
- resolvedColors: ThemeColors;
267
- onEditingTextChange: (text: string) => void;
268
- onRemoveAttachment?: (id: string) => void;
269
- onAddAttachments?: (files: FileList) => void;
270
- uploading?: boolean;
271
- onStartEdit: (messageId: string, text: string) => void;
272
- onCancelEdit: () => void;
273
- onSaveEdit: (messageId: string, text: string) => void;
274
- onToggleReasoning: (messageId: string) => void;
275
- scrollAnchorRef: react__default.RefObject<HTMLDivElement>;
276
- hideReasoningContent?: boolean;
277
- t: (key: keyof TranslationKeys) => string;
278
- }
279
- declare function MessageList({ messages, streaming, editingMessageId, editingMessageText, editingAttachments, error, actionStatuses, components, theme, resolvedColors, onEditingTextChange, onRemoveAttachment, onAddAttachments, uploading, onStartEdit, onCancelEdit, onSaveEdit, onToggleReasoning, scrollAnchorRef, hideReasoningContent, t }: MessageListProps): react_jsx_runtime.JSX.Element;
280
-
281
64
  interface FloatingChatButtonProps {
282
65
  show: boolean;
283
66
  onClick: () => void;
@@ -291,26 +74,67 @@ interface FloatingChatButtonProps {
291
74
  }
292
75
  declare function FloatingChatButton({ show, onClick, resolvedColors, floatingButtonPosition }: FloatingChatButtonProps): react_jsx_runtime.JSX.Element | null;
293
76
 
294
- interface UseToggleReturn {
295
- /** Current toggle state */
296
- on: boolean;
297
- /** Toggle the state */
298
- toggle: () => void;
299
- /** Set the state directly */
300
- setOn: (value: boolean | ((prev: boolean) => boolean)) => void;
301
- /** Set state to true */
302
- setTrue: () => void;
303
- /** Set state to false */
304
- setFalse: () => void;
305
- }
77
+ declare function useAutoScroll<T extends HTMLElement>(shouldScroll?: boolean): React$1.MutableRefObject<T | null>;
78
+
306
79
  /**
307
- * A hook for managing boolean toggle state
308
- * @param initial - Initial state value (default: false)
309
- * @returns Object with toggle state and control functions
80
+ * Type definitions for the Hsafa SDK - minimal exports used across the SDK
310
81
  */
311
- declare function useToggle(initial?: boolean): UseToggleReturn;
82
+ type Attachment = {
83
+ id: string;
84
+ name?: string;
85
+ url: string;
86
+ mimeType?: string;
87
+ size?: number;
88
+ };
89
+ type HsafaTool = ((input: any) => any | Promise<any>) | {
90
+ tool: (input: any) => any | Promise<any>;
91
+ executeEachToken?: boolean;
92
+ };
93
+ interface HsafaChatProps {
94
+ agentId: string;
95
+ theme?: 'dark' | 'light';
96
+ primaryColor?: string;
97
+ primaryColorDark?: string;
98
+ primaryColorLight?: string;
99
+ backgroundColor?: string;
100
+ borderColor?: string;
101
+ textColor?: string;
102
+ accentColor?: string;
103
+ width?: number | string;
104
+ maxWidth?: number | string;
105
+ height?: string;
106
+ expandable?: boolean;
107
+ alwaysOpen?: boolean;
108
+ defaultOpen?: boolean;
109
+ floatingButtonPosition?: {
110
+ bottom?: number | string;
111
+ right?: number | string;
112
+ top?: number | string;
113
+ left?: number | string;
114
+ };
115
+ placeholder?: string;
116
+ title?: string;
117
+ className?: string;
118
+ chatContainerClassName?: string;
119
+ dir?: 'rtl' | 'ltr';
120
+ language?: 'en' | 'ar';
121
+ defaultReasoningOpen?: boolean;
122
+ hideReasoningContent?: boolean;
123
+ UIComponents?: Record<string, React.ComponentType<any>>;
124
+ HsafaTools?: Record<string, HsafaTool>;
125
+ }
312
126
 
313
- declare function useAutoScroll<T extends HTMLElement>(): react.MutableRefObject<T | null>;
127
+ declare function useFileUpload(baseUrl: string): {
128
+ attachments: Attachment[];
129
+ uploading: boolean;
130
+ fileInputRef: React$1.MutableRefObject<HTMLInputElement | null>;
131
+ formatBytes: (bytes: number) => string;
132
+ handleRemoveAttachment: (id: string) => void;
133
+ handleFileSelection: (fileList: FileList | File[] | null, setError: (error: string | null) => void) => Promise<void>;
134
+ buildUserContent: (text: string, attachments: Attachment[]) => any[];
135
+ clearAttachments: () => void;
136
+ MAX_UPLOAD_SIZE: number;
137
+ };
314
138
 
315
139
  /**
316
140
  * Handler function for custom actions that can be triggered by the AI agent
@@ -333,6 +157,10 @@ type HsafaActionHandler = (params: any, meta: {
333
157
  interface HsafaConfig {
334
158
  /** Base URL for agent API calls, e.g. "" (same origin) or "https://example.com" */
335
159
  baseUrl?: string;
160
+ /** Default text direction for SDK components */
161
+ dir?: 'ltr' | 'rtl';
162
+ /** Default theme for SDK components */
163
+ theme?: 'dark' | 'light';
336
164
  }
337
165
  /**
338
166
  * Context value provided by HsafaProvider
@@ -341,15 +169,15 @@ interface HsafaContextValue extends HsafaConfig {
341
169
  /** Registered custom actions */
342
170
  actions: Map<string, HsafaActionHandler>;
343
171
  /** Registered custom components */
344
- components: Map<string, react__default.ComponentType<any>>;
172
+ components: Map<string, React__default.ComponentType<any>>;
345
173
  /** Register a custom action handler */
346
174
  registerAction: (name: string, handler: HsafaActionHandler) => () => void;
347
175
  /** Unregister a custom action handler */
348
176
  unregisterAction: (name: string, handler?: HsafaActionHandler) => void;
349
177
  /** Register a custom component */
350
- registerComponent: (name: string, component: react__default.ComponentType<any>) => () => void;
178
+ registerComponent: (name: string, component: React__default.ComponentType<any>) => () => void;
351
179
  /** Unregister a custom component */
352
- unregisterComponent: (name: string, component?: react__default.ComponentType<any>) => void;
180
+ unregisterComponent: (name: string, component?: React__default.ComponentType<any>) => void;
353
181
  /** Global streaming state - true if any chat is streaming */
354
182
  isAnyStreaming: boolean;
355
183
  /** Set streaming state for a specific chat instance */
@@ -364,7 +192,7 @@ interface HsafaContextValue extends HsafaConfig {
364
192
  */
365
193
  interface HsafaProviderProps extends HsafaConfig {
366
194
  /** Child components that will have access to the Hsafa context */
367
- children: react__default.ReactNode;
195
+ children: React__default.ReactNode;
368
196
  }
369
197
  /**
370
198
  * Provider component that sets up the Hsafa context for the SDK.
@@ -377,7 +205,7 @@ interface HsafaProviderProps extends HsafaConfig {
377
205
  * </HsafaProvider>
378
206
  * ```
379
207
  */
380
- declare function HsafaProvider({ baseUrl, children }: HsafaProviderProps): react_jsx_runtime.JSX.Element;
208
+ declare function HsafaProvider({ baseUrl, dir, theme, children }: HsafaProviderProps): react_jsx_runtime.JSX.Element;
381
209
  /**
382
210
  * Hook to access the Hsafa context.
383
211
  * Must be used within a HsafaProvider.
@@ -404,187 +232,14 @@ declare function HsafaProvider({ baseUrl, children }: HsafaProviderProps): react
404
232
  */
405
233
  declare function useHsafa(): HsafaContextValue;
406
234
 
407
- /**
408
- * Register an action handler by name within the nearest HsafaProvider.
409
- * The handler will be automatically unregistered on unmount.
410
- *
411
- * @param name - Unique name for the action
412
- * @param handler - Function to execute when action is triggered
413
- *
414
- * @example
415
- * ```tsx
416
- * useHsafaAction('submitForm', async (params, meta) => {
417
- * console.log('Form submitted:', params);
418
- * return { success: true };
419
- * });
420
- * ```
421
- */
422
- declare function useHsafaAction(name: string, handler: HsafaActionHandler): void;
423
-
424
- /**
425
- * Register a UI component by name within the nearest HsafaProvider.
426
- * The component will be automatically unregistered on unmount.
427
- *
428
- * @param name - Unique name for the component (matches agent's component field)
429
- * @param component - React component to render when agent requests this component
430
- *
431
- * @example
432
- * ```tsx
433
- * function ProductCard({ name, price }: { name: string; price: number }) {
434
- * return <div>{name}: ${price}</div>;
435
- * }
436
- *
437
- * useHsafaComponent('ProductCard', ProductCard);
438
- * ```
439
- */
440
- declare function useHsafaComponent<T = any>(name: string, component: ComponentType<T>): void;
441
-
442
- interface ChatMeta {
443
- id: string;
444
- title: string;
445
- createdAt: number;
446
- updatedAt: number;
447
- }
448
- interface ChatData {
449
- id: string;
450
- messages: ChatMessage[];
451
- agentId?: string;
452
- }
453
- declare function useChatStorage(agentId: string): {
454
- currentChatId: string | null;
455
- setCurrentChatId: react.Dispatch<react.SetStateAction<string | null>>;
456
- hasChatRecordRef: react.MutableRefObject<boolean>;
457
- pendingFirstTitleRef: react.MutableRefObject<string | null>;
458
- loadChatsIndex: () => ChatMeta[];
459
- loadChat: (id: string) => ChatData | null;
460
- saveChat: (data: ChatData) => void;
461
- deleteChat: (id: string, onChatDeleted?: (wasCurrentChat: boolean) => void) => void;
462
- loadChatPreferences: () => ChatMessage[];
463
- persistChatData: (messages: ChatMessage[]) => void;
464
- createNewChat: (firstMessage?: string) => string;
465
- upsertChatMeta: (meta: ChatMeta) => void;
466
- showChatKey: string;
467
- };
468
-
469
- declare function useStreaming(): {
470
- streaming: boolean;
471
- setStreaming: react.Dispatch<react.SetStateAction<boolean>>;
472
- error: string | null;
473
- setError: react.Dispatch<react.SetStateAction<string | null>>;
474
- actionStatuses: Map<string, "executing" | "executed">;
475
- setActionStatuses: react.Dispatch<react.SetStateAction<Map<string, "executing" | "executed">>>;
476
- abortControllerRef: react.MutableRefObject<AbortController | null>;
477
- actionExecMapRef: react.MutableRefObject<Record<string, boolean>>;
478
- assistantMsgIdRef: react.MutableRefObject<string | undefined>;
479
- calledFinalActionsRef: react.MutableRefObject<Set<string>>;
480
- actionParamsHistoryRef: react.MutableRefObject<Map<string, any[]>>;
481
- actionExecutionStatusRef: react.MutableRefObject<Map<string, "executing" | "executed">>;
482
- processActions: (items: any[] | undefined, trigger: "partial" | "final", actions: Map<string, any>, currentChatId: string | null) => void;
483
- handleStop: () => void;
484
- resetActionTracking: () => void;
485
- cleanupTimeouts: () => void;
486
- hasActionParamsStabilized: (actionKey: string, currentParams: any) => boolean;
487
- };
488
-
489
- declare function useFileUpload(baseUrl: string): {
490
- attachments: Attachment[];
491
- uploading: boolean;
492
- fileInputRef: react.MutableRefObject<HTMLInputElement | null>;
493
- formatBytes: (bytes: number) => string;
494
- handleRemoveAttachment: (id: string) => void;
495
- handleFileSelection: (fileList: FileList | File[] | null, setError: (error: string | null) => void) => Promise<void>;
496
- buildUserContent: (text: string, attachments: Attachment[]) => any[];
497
- clearAttachments: () => void;
498
- MAX_UPLOAD_SIZE: number;
499
- };
500
-
501
- /**
502
- * Types matching the structure from getAgentStreamingResponse
503
- */
504
- type FirstAgentData = {
505
- message: string;
506
- continue: boolean;
507
- startDate?: number;
508
- endDate?: number;
509
- durationMs?: number;
510
- };
511
- type MainAgentAction = {
512
- type: 'reasoning';
513
- reasoning: string;
514
- status: 'streaming' | 'finished';
515
- startDate?: number;
516
- endDate?: number;
517
- durationMs?: number;
518
- } | {
519
- type: 'tool-call';
520
- toolCallId?: string;
521
- toolName?: string;
522
- input?: any;
523
- inputText?: string;
524
- output?: any;
525
- status: 'input_streaming' | 'running' | 'finished' | 'error';
526
- error?: string;
527
- startDate?: number;
528
- endDate?: number;
529
- durationMs?: number;
530
- } | {
531
- type: 'step';
532
- stepNumber?: number;
533
- finishReason?: string;
534
- usage?: any;
535
- startDate?: number;
536
- endDate?: number;
537
- durationMs?: number;
538
- } | {
539
- type: 'text';
540
- text: string;
541
- status: 'streaming' | 'finished';
542
- startDate?: number;
543
- endDate?: number;
544
- durationMs?: number;
545
- } | {
546
- type: 'source';
547
- source: any;
548
- durationMs?: number;
549
- } | {
550
- type: 'file';
551
- file: any;
552
- durationMs?: number;
553
- } | {
554
- type: 'response';
555
- items: any[];
556
- [key: string]: any;
557
- startDate?: number;
558
- endDate?: number;
559
- durationMs?: number;
560
- };
561
- type AgentStreamData = {
562
- first_agent: FirstAgentData;
563
- main_agent: MainAgentAction[];
564
- };
565
- /**
566
- * Hook to handle agent streaming responses
567
- * Returns streaming state and a function to start streaming
568
- */
569
- declare function useAgentStreaming(): {
570
- streaming: boolean;
571
- error: string | null;
572
- streamData: AgentStreamData | null;
573
- startStreaming: ({ agentId, body, baseUrl, onUpdate, signal, }: {
574
- agentId: string;
575
- body: any;
576
- baseUrl?: string;
577
- onUpdate?: (data: AgentStreamData) => void;
578
- signal?: AbortSignal;
579
- }) => Promise<AgentStreamData | null>;
580
- stopStreaming: () => void;
581
- reset: () => void;
582
- };
583
-
584
- declare function HsafaChat(props: HsafaChatProps): react__default.ReactPortal | null;
235
+ declare function HsafaChat({ agentId, theme, primaryColor, primaryColorDark, primaryColorLight, backgroundColor, borderColor, textColor, accentColor, baseUrl, initialMessages, onMessagesChange, defaultOpen, floatingButtonPosition, UIComponents, HsafaTools, }: HsafaChatProps & {
236
+ baseUrl?: string;
237
+ initialMessages?: any[];
238
+ onMessagesChange?: (messages: any[]) => void;
239
+ }): react_jsx_runtime.JSX.Element;
585
240
 
586
241
  interface ContentContainerProps {
587
- children: react__default.ReactNode;
242
+ children: React__default.ReactNode;
588
243
  theme?: "dark" | "light";
589
244
  primaryColor?: string;
590
245
  backgroundColor?: string;
@@ -642,4 +297,264 @@ interface ContentContainerProps {
642
297
  */
643
298
  declare function ContentContainer({ children, theme, primaryColor, backgroundColor, borderColor, textColor, mutedTextColor, enableBorderAnimation, borderRadius, enableContentBorder, className, enableMargin, chatWidth, dir, }: ContentContainerProps): react_jsx_runtime.JSX.Element;
644
299
 
645
- export { type AgentStreamData, Button, type ButtonProps, type ChatData, type ChatMeta, ContentContainer, type ContentContainerProps, type FirstAgentData, FloatingChatButton, HsafaChat, HsafaProvider, type MainAgentAction, MessageList, type UseToggleReturn, useAgentStreaming, useAutoScroll, useChatStorage, useFileUpload, useHsafa, useHsafaAction, useHsafaComponent, useStreaming, useToggle };
300
+ /**
301
+ * Component Registry for custom UI components
302
+ * Allows users to register their own React components to be rendered in chat responses
303
+ */
304
+
305
+ interface UIComponentProps {
306
+ props: any;
307
+ resolvedColors?: any;
308
+ }
309
+ declare class ComponentRegistry {
310
+ private components;
311
+ /**
312
+ * Register a custom UI component
313
+ * @param name - The component name (should match the 'component' field from the agent response)
314
+ * @param component - The React component to render
315
+ */
316
+ register(name: string, component: ComponentType<UIComponentProps>): void;
317
+ /**
318
+ * Unregister a component
319
+ * @param name - The component name to remove
320
+ */
321
+ unregister(name: string): void;
322
+ /**
323
+ * Get a registered component
324
+ * @param name - The component name
325
+ * @returns The component or undefined if not found
326
+ */
327
+ get(name: string): ComponentType<UIComponentProps> | undefined;
328
+ /**
329
+ * Check if a component is registered
330
+ * @param name - The component name
331
+ */
332
+ has(name: string): boolean;
333
+ /**
334
+ * Clear all registered components
335
+ */
336
+ clear(): void;
337
+ /**
338
+ * Get all registered component names
339
+ */
340
+ getRegisteredNames(): string[];
341
+ }
342
+ declare const registry: ComponentRegistry;
343
+
344
+ /**
345
+ * getDomComponents - Scan and analyze all interactive DOM elements inside ContentContainer
346
+ *
347
+ * Returns a structured list of all inputs, buttons, links, and interactive elements
348
+ * that the agent can interact with using the web controller tools.
349
+ */
350
+ interface DomComponent {
351
+ id: string | null;
352
+ tag: string;
353
+ type?: string;
354
+ name?: string;
355
+ label?: string;
356
+ placeholder?: string;
357
+ value?: string | boolean | string[];
358
+ options?: Array<{
359
+ value: string;
360
+ label: string;
361
+ selected: boolean;
362
+ disabled: boolean;
363
+ }>;
364
+ checked?: boolean;
365
+ disabled?: boolean;
366
+ required?: boolean;
367
+ className?: string;
368
+ text?: string;
369
+ href?: string;
370
+ role?: string;
371
+ ariaLabel?: string;
372
+ selector?: string;
373
+ isVisible: boolean;
374
+ isInteractive: boolean;
375
+ }
376
+ interface GetDomComponentsOptions {
377
+ includeHidden?: boolean;
378
+ selector?: string;
379
+ what?: 'inputs' | 'content';
380
+ limit?: number;
381
+ }
382
+ interface GetDomComponentsResult {
383
+ ok: boolean;
384
+ components: DomComponent[];
385
+ count: number;
386
+ total: number;
387
+ truncated?: boolean;
388
+ containerFound: boolean;
389
+ error?: string;
390
+ }
391
+ declare function getDomComponents(options?: GetDomComponentsOptions): Promise<GetDomComponentsResult>;
392
+
393
+ /**
394
+ * CursorController
395
+ *
396
+ * Mount this component once on a page (e.g. in the demo at `/demo`). It registers a
397
+ * global function `window.__cursorGuide(stepsOrTarget, options?)` that moves a fake
398
+ * cursor to a target and optionally performs actions (click, drag).
399
+ *
400
+ * In `app/demo/page.tsx`, a convenience wrapper `guideCursorTo(targetOrSteps, options?)`
401
+ * is also exported and exposed globally as `window.guideCursorTo`.
402
+ *
403
+ * Quick examples (run in DevTools on /demo):
404
+ * ```js
405
+ * // Move to a screen position
406
+ * await window.guideCursorTo({ position: { x: 140, y: 160 } }, { durationMs: 700 });
407
+ *
408
+ * // Click an element by selector or id
409
+ * await window.guideCursorTo('#submitBtn', { action: 'click', anchor: 'center' });
410
+ *
411
+ * // Drag from one element to another
412
+ * await window.guideCursorTo({ selector: '#cardBacklog0' }, { action: 'drag', dragTo: '#doingDrop' });
413
+ *
414
+ * // Multi-step sequence
415
+ * await window.guideCursorTo([
416
+ * { target: '#tabStats', action: 'click', options: { durationMs: 600 } },
417
+ * { target: { position: { x: 100, y: 120 } } },
418
+ * { target: '#progressStartBtn', action: 'click' },
419
+ * ]);
420
+ * ```
421
+ *
422
+ * Options highlights (see `GuideOptions`):
423
+ * - action: 'none' | 'click' | 'drag'
424
+ * - durationMs, easing: control motion speed/curve
425
+ * - path: 'straight' | 'curve', curveStrength, curveDirection
426
+ * - anchor: where inside the element to aim (e.g. 'center', 'top-left' or {x:0..1,y:0..1})
427
+ * - cursorHotspot: px offset to the click location
428
+ * - dragTo: target for drag action
429
+ */
430
+ type GuideAction = "none" | "click" | "drag";
431
+ type GuideTarget = string | Element | {
432
+ selector: string;
433
+ nth?: number;
434
+ within?: Element | string;
435
+ } | {
436
+ position: {
437
+ x: number;
438
+ y: number;
439
+ };
440
+ };
441
+ type Anchor = "center" | "top-left" | "bottom-right" | {
442
+ x: number;
443
+ y: number;
444
+ };
445
+ type GuideOptions = {
446
+ action?: GuideAction;
447
+ durationMs?: number;
448
+ easing?: "ease" | "ease-in" | "ease-out" | "ease-in-out" | "linear";
449
+ offset?: {
450
+ x?: number;
451
+ y?: number;
452
+ };
453
+ highlight?: boolean;
454
+ path?: "straight" | "curve";
455
+ curveStrength?: number;
456
+ curveDirection?: "auto" | "left" | "right";
457
+ anchor?: Anchor;
458
+ cursorHotspot?: {
459
+ x?: number;
460
+ y?: number;
461
+ };
462
+ dragTo?: GuideTarget;
463
+ };
464
+ type GuideStep = {
465
+ target: GuideTarget;
466
+ action?: GuideAction;
467
+ options?: GuideOptions;
468
+ };
469
+ type GuideStepResult = {
470
+ ok: boolean;
471
+ action: GuideAction;
472
+ targetKind: "element" | "position";
473
+ durationMs: number;
474
+ clickedElementId?: string | null;
475
+ error?: string;
476
+ };
477
+ type GuideRunResult = {
478
+ ok: boolean;
479
+ steps: GuideStepResult[];
480
+ };
481
+ declare function CursorController(): null;
482
+
483
+ /**
484
+ * guideCursor - Wrapper for window.__cursorGuide
485
+ *
486
+ * Move the visual cursor to elements and perform click/drag actions.
487
+ * Requires CursorController component to be mounted on the page.
488
+ */
489
+
490
+ interface GuideCursorOptions extends GuideOptions {
491
+ }
492
+ /**
493
+ * Guide the cursor to a target element or position
494
+ *
495
+ * @example
496
+ * ```ts
497
+ * // Move to an element and click it
498
+ * await guideCursor('#submitBtn', { action: 'click' });
499
+ *
500
+ * // Move to a position
501
+ * await guideCursor({ position: { x: 100, y: 200 } });
502
+ *
503
+ * // Drag from one element to another
504
+ * await guideCursor('#item1', { action: 'drag', dragTo: '#dropzone' });
505
+ * ```
506
+ */
507
+ declare function guideCursor(target: GuideTarget, options?: GuideCursorOptions): Promise<GuideRunResult>;
508
+
509
+ /**
510
+ * FillInput utilities
511
+ *
512
+ * Exports two helpers for programmatically filling inputs while dispatching the
513
+ * same DOM events a user would normally trigger (input/change/click):
514
+ *
515
+ * - FillInput(inputId, value, options?)
516
+ * Fill a single field by its element id with the provided value.
517
+ *
518
+ * - FillActiveInput(value, options?)
519
+ * Fill the currently focused field without needing its id.
520
+ *
521
+ * Basic example:
522
+ * ```ts
523
+ * import { FillInput, FillActiveInput } from "./FillInput";
524
+ *
525
+ * // Fill individual fields by id
526
+ * await FillInput("fi_name", "Jane Doe");
527
+ * await FillInput("fi_email", "jane@example.com");
528
+ * await FillInput("fi_role_admin", true); // radio -> check this option
529
+ * await FillInput("fi_country2", "sa"); // select value
530
+ * await FillInput("fi_tags", ["a", "c"]); // multi-select values
531
+ * await FillInput("fi_newsletter", true); // checkbox
532
+ * await FillInput("fi_dob", "1995-05-15"); // date input
533
+ * await FillInput("about", "Hello there"); // contenteditable by id
534
+ *
535
+ * // Fill the currently focused field
536
+ * (document.getElementById("fi_name") as HTMLElement)?.focus();
537
+ * await FillActiveInput("Alice");
538
+ * ```
539
+ *
540
+ * Notes:
541
+ * - Scrolling is disabled; these helpers will not scroll the page.
542
+ * - typingDelayMs is ignored; filling is instantaneous.
543
+ * - For file inputs, pass a File or File[]; browsers may restrict programmatic assignment.
544
+ */
545
+ type FillInputOptions = {
546
+ typingDelayMs?: number;
547
+ scrollIntoView?: boolean;
548
+ };
549
+ type FillResult = {
550
+ ok: boolean;
551
+ filled: Array<{
552
+ key: string;
553
+ status: "ok" | "skipped" | "error";
554
+ message?: string;
555
+ }>;
556
+ errors?: string[];
557
+ };
558
+ declare function FillActiveInput(value: any, options?: FillInputOptions): Promise<FillResult>;
559
+
560
+ export { type Anchor, Button, type ButtonProps, ContentContainer, type ContentContainerProps, CursorController, type DomComponent, FillActiveInput, type FillInputOptions, type FillResult, FloatingChatButton, type GetDomComponentsOptions, type GetDomComponentsResult, type GuideAction, type GuideCursorOptions, type GuideOptions, type GuideRunResult, type GuideStep, type GuideStepResult, type GuideTarget, HsafaChat, type HsafaChatProps, HsafaProvider, type UIComponentProps, registry as componentRegistry, guideCursor as controlCursor, getDomComponents, guideCursor, useAutoScroll, useFileUpload, useHsafa };