@apteva/apteva-kit 0.1.16 → 0.1.18

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.mts CHANGED
@@ -138,6 +138,22 @@ interface GalleryWidget extends Widget {
138
138
  layout?: 'grid' | 'carousel';
139
139
  };
140
140
  }
141
+ interface TableColumn {
142
+ key: string;
143
+ label: string;
144
+ align?: 'left' | 'center' | 'right';
145
+ width?: string;
146
+ }
147
+ interface TableWidget extends Widget {
148
+ type: 'table';
149
+ props: {
150
+ columns: TableColumn[];
151
+ rows: Array<Record<string, any>>;
152
+ caption?: string;
153
+ compact?: boolean;
154
+ striped?: boolean;
155
+ };
156
+ }
141
157
 
142
158
  interface Message {
143
159
  id: string;
@@ -162,6 +178,59 @@ interface SendMessageParams {
162
178
  metadata?: Record<string, any>;
163
179
  }
164
180
 
181
+ /**
182
+ * Widget definitions for context injection
183
+ * These are sent to the agent so it knows what UI widgets are available
184
+ */
185
+ declare const WIDGET_DEFINITIONS: {
186
+ readonly card: {
187
+ readonly description: "Displays a card with title and optional description, image, footer";
188
+ readonly schema: "{\"title\": \"string\", \"description?\": \"string\", \"image?\": \"url\", \"footer?\": \"string\"}";
189
+ readonly example: "@ui:card[{\"title\": \"Summary\", \"description\": \"Key findings from the analysis\"}]";
190
+ };
191
+ readonly list: {
192
+ readonly description: "Displays a list of items with title, subtitle, and optional description";
193
+ readonly schema: "{\"items\": [{\"id\": \"string\", \"title\": \"string\", \"subtitle?\": \"string\", \"description?\": \"string\", \"image?\": \"url\"}]}";
194
+ readonly example: "@ui:list[{\"items\": [{\"id\": \"1\", \"title\": \"First item\", \"subtitle\": \"Details\"}]}]";
195
+ };
196
+ readonly button_group: {
197
+ readonly description: "Displays action buttons. User clicks are sent back to you with the button id";
198
+ readonly schema: "{\"buttons\": [{\"id\": \"string\", \"label\": \"string\", \"variant?\": \"primary|secondary|outline\"}], \"layout?\": \"horizontal|vertical\"}";
199
+ readonly example: "@ui:button_group[{\"buttons\": [{\"id\": \"confirm\", \"label\": \"Confirm\", \"variant\": \"primary\"}, {\"id\": \"cancel\", \"label\": \"Cancel\"}]}]";
200
+ };
201
+ readonly form: {
202
+ readonly description: "Displays an input form. Submitted data is sent back to you";
203
+ readonly schema: "{\"title?\": \"string\", \"fields\": [{\"name\": \"string\", \"type\": \"text|number|select|checkbox|textarea|date\", \"label\": \"string\", \"required?\": boolean, \"placeholder?\": \"string\", \"options?\": [{\"label\": \"string\", \"value\": \"string\"}]}]}";
204
+ readonly example: "@ui:form[{\"title\": \"Contact\", \"fields\": [{\"name\": \"email\", \"type\": \"text\", \"label\": \"Email\", \"required\": true}]}]";
205
+ };
206
+ readonly image: {
207
+ readonly description: "Displays a single image with optional caption";
208
+ readonly schema: "{\"src\": \"url\", \"alt\": \"string\", \"caption?\": \"string\"}";
209
+ readonly example: "@ui:image[{\"src\": \"https://example.com/img.png\", \"alt\": \"Description\", \"caption\": \"Figure 1\"}]";
210
+ };
211
+ readonly gallery: {
212
+ readonly description: "Displays multiple images in a grid or carousel layout";
213
+ readonly schema: "{\"images\": [{\"id\": \"string\", \"src\": \"url\", \"alt\": \"string\", \"caption?\": \"string\"}], \"layout?\": \"grid|carousel\"}";
214
+ readonly example: "@ui:gallery[{\"images\": [{\"id\": \"1\", \"src\": \"https://example.com/1.png\", \"alt\": \"Image 1\"}], \"layout\": \"grid\"}]";
215
+ };
216
+ readonly chart: {
217
+ readonly description: "Displays a chart visualization (line, bar, pie, doughnut)";
218
+ readonly schema: "{\"chartType\": \"line|bar|pie|doughnut\", \"title?\": \"string\", \"data\": {\"labels\": [\"string\"], \"datasets\": [{\"label\": \"string\", \"data\": [number], \"backgroundColor?\": \"string|string[]\"}]}}";
219
+ readonly example: "@ui:chart[{\"chartType\": \"bar\", \"title\": \"Sales\", \"data\": {\"labels\": [\"Q1\", \"Q2\"], \"datasets\": [{\"label\": \"Revenue\", \"data\": [100, 150]}]}}]";
220
+ };
221
+ readonly map: {
222
+ readonly description: "Displays an interactive map with optional markers";
223
+ readonly schema: "{\"center\": {\"lat\": number, \"lng\": number}, \"zoom?\": number, \"markers?\": [{\"id\": \"string\", \"position\": {\"lat\": number, \"lng\": number}, \"title\": \"string\"}]}";
224
+ readonly example: "@ui:map[{\"center\": {\"lat\": 40.7128, \"lng\": -74.0060}, \"zoom\": 12, \"markers\": [{\"id\": \"1\", \"position\": {\"lat\": 40.7128, \"lng\": -74.0060}, \"title\": \"NYC\"}]}]";
225
+ };
226
+ readonly table: {
227
+ readonly description: "Displays structured data in rows and columns";
228
+ readonly schema: "{\"columns\": [{\"key\": \"string\", \"label\": \"string\", \"align?\": \"left|center|right\"}], \"rows\": [{\"id?\": \"string\", ...}], \"caption?\": \"string\", \"compact?\": boolean, \"striped?\": boolean}";
229
+ readonly example: "@ui:table[{\"columns\": [{\"key\": \"name\", \"label\": \"Name\"}, {\"key\": \"status\", \"label\": \"Status\"}], \"rows\": [{\"name\": \"Item 1\", \"status\": \"Active\"}, {\"name\": \"Item 2\", \"status\": \"Pending\"}]}]";
230
+ };
231
+ };
232
+ type WidgetType = keyof typeof WIDGET_DEFINITIONS;
233
+
165
234
  interface SuggestedPrompt {
166
235
  text: string;
167
236
  icon?: React.ReactNode;
@@ -195,12 +264,17 @@ interface ChatProps {
195
264
  onFileUpload?: (files: FileList) => void;
196
265
  onComplete?: (result: CommandResult) => void;
197
266
  onError?: (error: Error) => void;
267
+ onToolResult?: (toolName: string, result?: any) => void;
198
268
  theme?: 'light' | 'dark' | 'auto';
199
269
  placeholder?: string;
200
270
  showHeader?: boolean;
201
271
  headerTitle?: string;
202
272
  enableFileUpload?: boolean;
203
273
  enableMarkdown?: boolean;
274
+ enableWidgets?: boolean;
275
+ availableWidgets?: WidgetType[];
276
+ compactWidgetContext?: boolean;
277
+ onWidgetRender?: (widget: Widget) => void;
204
278
  className?: string;
205
279
  }
206
280
  interface CommandProps {
@@ -223,6 +297,7 @@ interface CommandProps {
223
297
  onError?: (error: Error) => void;
224
298
  onFileUpload?: (files: FileList) => void;
225
299
  onAction?: (action: ActionEvent) => void;
300
+ onToolResult?: (toolName: string, result?: any) => void;
226
301
  loadingText?: string;
227
302
  showProgress?: boolean;
228
303
  enableStreaming?: boolean;
@@ -304,7 +379,7 @@ interface UseAptevaKitReturn {
304
379
  error: Error | null;
305
380
  }
306
381
 
307
- declare function Chat({ agentId, threadId, initialMessages, context, apiUrl, apiKey, useMock, initialMode, showModeToggle, onModeChange, commandVariant, planMode, onPlanModeChange, enableStreaming, showProgress, loadingText, welcomeTitle, welcomeSubtitle, welcomeIcon, suggestedPrompts, welcomeVariant, onThreadChange, onMessageSent, onAction, onFileUpload, onComplete, onError, placeholder, showHeader, headerTitle, className, }: ChatProps): react_jsx_runtime.JSX.Element;
382
+ declare function Chat({ agentId, threadId, initialMessages, context, apiUrl, apiKey, useMock, initialMode, showModeToggle, onModeChange, commandVariant, planMode, onPlanModeChange, enableStreaming, showProgress, loadingText, welcomeTitle, welcomeSubtitle, welcomeIcon, suggestedPrompts, welcomeVariant, onThreadChange, onMessageSent, onAction, onFileUpload, onComplete, onError, onToolResult, placeholder, showHeader, headerTitle, enableWidgets, availableWidgets, compactWidgetContext, onWidgetRender, className, }: ChatProps): react_jsx_runtime.JSX.Element;
308
383
 
309
384
  declare function Command({ agentId, command: initialCommand, context, autoExecute, allowInput, placeholder, submitButtonText, variant, useMock, planMode, onPlanModeChange, enableFileUpload, onStart, onProgress, onChunk, onComplete, onError, onFileUpload, onAction, loadingText, showProgress, enableStreaming, resultRenderer, className, }: CommandProps): react_jsx_runtime.JSX.Element;
310
385
 
@@ -365,10 +440,11 @@ interface ChatResponse {
365
440
  widgets?: any[];
366
441
  }
367
442
  interface StreamChunk {
368
- type: 'start' | 'thread_id' | 'content' | 'token' | 'tool_call' | 'tool_input_delta' | 'tool_use' | 'tool_result' | 'stop' | 'widget' | 'complete' | 'done' | 'error';
443
+ type: 'start' | 'thread_id' | 'request_id' | 'content' | 'token' | 'tool_call' | 'tool_input_delta' | 'tool_use' | 'tool_result' | 'stop' | 'widget' | 'complete' | 'done' | 'error';
369
444
  content?: string;
370
445
  widget?: any;
371
446
  thread_id?: string;
447
+ request_id?: string;
372
448
  tool_id?: string;
373
449
  tool_name?: string;
374
450
  error?: string;
@@ -401,6 +477,10 @@ declare class AptevaClient {
401
477
  * Get thread messages
402
478
  */
403
479
  getThreadMessages(threadId: string): Promise<ChatMessage[]>;
480
+ /**
481
+ * Cancel an in-progress request
482
+ */
483
+ cancelRequest(agentId: string, requestId: string): Promise<void>;
404
484
  }
405
485
  declare const aptevaClient: AptevaClient;
406
486
 
@@ -410,4 +490,4 @@ declare const mockMessages: Message[];
410
490
  declare const mockThreads: Thread[];
411
491
  declare const mockWidgets: Widget[];
412
492
 
413
- export { type Action, type ActionEvent, AptevaClient, type AptevaClientConfig, type AptevaKitControl, Button, type ButtonGroupWidget, type ButtonWidget, Card, type CardWidget, type ChartWidget, Chat, type ChatMessage, type ChatProps, type ChatRequest, type ChatResponse, Command, type CommandProps, type CommandResult, type FormField, type FormWidget, type GalleryWidget, type ImageWidget, List, type ListItem, type ListWidget, type MapWidget, type Message, Prompt, type PromptProps, type SendMessageParams, Stream, type StreamChunk, type StreamProps, type SuggestedPrompt, type Thread, Threads, type ThreadsProps, type UseAptevaKitReturn, type Widget, Widgets, type WidgetsProps, aptevaClient, cn, getThemeScript, mockMessages, mockThreads, mockWidgets };
493
+ export { type Action, type ActionEvent, AptevaClient, type AptevaClientConfig, type AptevaKitControl, Button, type ButtonGroupWidget, type ButtonWidget, Card, type CardWidget, type ChartWidget, Chat, type ChatMessage, type ChatProps, type ChatRequest, type ChatResponse, Command, type CommandProps, type CommandResult, type FormField, type FormWidget, type GalleryWidget, type ImageWidget, List, type ListItem, type ListWidget, type MapWidget, type Message, Prompt, type PromptProps, type SendMessageParams, Stream, type StreamChunk, type StreamProps, type SuggestedPrompt, type TableColumn, type TableWidget, type Thread, Threads, type ThreadsProps, type UseAptevaKitReturn, type Widget, Widgets, type WidgetsProps, aptevaClient, cn, getThemeScript, mockMessages, mockThreads, mockWidgets };
package/dist/index.d.ts CHANGED
@@ -138,6 +138,22 @@ interface GalleryWidget extends Widget {
138
138
  layout?: 'grid' | 'carousel';
139
139
  };
140
140
  }
141
+ interface TableColumn {
142
+ key: string;
143
+ label: string;
144
+ align?: 'left' | 'center' | 'right';
145
+ width?: string;
146
+ }
147
+ interface TableWidget extends Widget {
148
+ type: 'table';
149
+ props: {
150
+ columns: TableColumn[];
151
+ rows: Array<Record<string, any>>;
152
+ caption?: string;
153
+ compact?: boolean;
154
+ striped?: boolean;
155
+ };
156
+ }
141
157
 
142
158
  interface Message {
143
159
  id: string;
@@ -162,6 +178,59 @@ interface SendMessageParams {
162
178
  metadata?: Record<string, any>;
163
179
  }
164
180
 
181
+ /**
182
+ * Widget definitions for context injection
183
+ * These are sent to the agent so it knows what UI widgets are available
184
+ */
185
+ declare const WIDGET_DEFINITIONS: {
186
+ readonly card: {
187
+ readonly description: "Displays a card with title and optional description, image, footer";
188
+ readonly schema: "{\"title\": \"string\", \"description?\": \"string\", \"image?\": \"url\", \"footer?\": \"string\"}";
189
+ readonly example: "@ui:card[{\"title\": \"Summary\", \"description\": \"Key findings from the analysis\"}]";
190
+ };
191
+ readonly list: {
192
+ readonly description: "Displays a list of items with title, subtitle, and optional description";
193
+ readonly schema: "{\"items\": [{\"id\": \"string\", \"title\": \"string\", \"subtitle?\": \"string\", \"description?\": \"string\", \"image?\": \"url\"}]}";
194
+ readonly example: "@ui:list[{\"items\": [{\"id\": \"1\", \"title\": \"First item\", \"subtitle\": \"Details\"}]}]";
195
+ };
196
+ readonly button_group: {
197
+ readonly description: "Displays action buttons. User clicks are sent back to you with the button id";
198
+ readonly schema: "{\"buttons\": [{\"id\": \"string\", \"label\": \"string\", \"variant?\": \"primary|secondary|outline\"}], \"layout?\": \"horizontal|vertical\"}";
199
+ readonly example: "@ui:button_group[{\"buttons\": [{\"id\": \"confirm\", \"label\": \"Confirm\", \"variant\": \"primary\"}, {\"id\": \"cancel\", \"label\": \"Cancel\"}]}]";
200
+ };
201
+ readonly form: {
202
+ readonly description: "Displays an input form. Submitted data is sent back to you";
203
+ readonly schema: "{\"title?\": \"string\", \"fields\": [{\"name\": \"string\", \"type\": \"text|number|select|checkbox|textarea|date\", \"label\": \"string\", \"required?\": boolean, \"placeholder?\": \"string\", \"options?\": [{\"label\": \"string\", \"value\": \"string\"}]}]}";
204
+ readonly example: "@ui:form[{\"title\": \"Contact\", \"fields\": [{\"name\": \"email\", \"type\": \"text\", \"label\": \"Email\", \"required\": true}]}]";
205
+ };
206
+ readonly image: {
207
+ readonly description: "Displays a single image with optional caption";
208
+ readonly schema: "{\"src\": \"url\", \"alt\": \"string\", \"caption?\": \"string\"}";
209
+ readonly example: "@ui:image[{\"src\": \"https://example.com/img.png\", \"alt\": \"Description\", \"caption\": \"Figure 1\"}]";
210
+ };
211
+ readonly gallery: {
212
+ readonly description: "Displays multiple images in a grid or carousel layout";
213
+ readonly schema: "{\"images\": [{\"id\": \"string\", \"src\": \"url\", \"alt\": \"string\", \"caption?\": \"string\"}], \"layout?\": \"grid|carousel\"}";
214
+ readonly example: "@ui:gallery[{\"images\": [{\"id\": \"1\", \"src\": \"https://example.com/1.png\", \"alt\": \"Image 1\"}], \"layout\": \"grid\"}]";
215
+ };
216
+ readonly chart: {
217
+ readonly description: "Displays a chart visualization (line, bar, pie, doughnut)";
218
+ readonly schema: "{\"chartType\": \"line|bar|pie|doughnut\", \"title?\": \"string\", \"data\": {\"labels\": [\"string\"], \"datasets\": [{\"label\": \"string\", \"data\": [number], \"backgroundColor?\": \"string|string[]\"}]}}";
219
+ readonly example: "@ui:chart[{\"chartType\": \"bar\", \"title\": \"Sales\", \"data\": {\"labels\": [\"Q1\", \"Q2\"], \"datasets\": [{\"label\": \"Revenue\", \"data\": [100, 150]}]}}]";
220
+ };
221
+ readonly map: {
222
+ readonly description: "Displays an interactive map with optional markers";
223
+ readonly schema: "{\"center\": {\"lat\": number, \"lng\": number}, \"zoom?\": number, \"markers?\": [{\"id\": \"string\", \"position\": {\"lat\": number, \"lng\": number}, \"title\": \"string\"}]}";
224
+ readonly example: "@ui:map[{\"center\": {\"lat\": 40.7128, \"lng\": -74.0060}, \"zoom\": 12, \"markers\": [{\"id\": \"1\", \"position\": {\"lat\": 40.7128, \"lng\": -74.0060}, \"title\": \"NYC\"}]}]";
225
+ };
226
+ readonly table: {
227
+ readonly description: "Displays structured data in rows and columns";
228
+ readonly schema: "{\"columns\": [{\"key\": \"string\", \"label\": \"string\", \"align?\": \"left|center|right\"}], \"rows\": [{\"id?\": \"string\", ...}], \"caption?\": \"string\", \"compact?\": boolean, \"striped?\": boolean}";
229
+ readonly example: "@ui:table[{\"columns\": [{\"key\": \"name\", \"label\": \"Name\"}, {\"key\": \"status\", \"label\": \"Status\"}], \"rows\": [{\"name\": \"Item 1\", \"status\": \"Active\"}, {\"name\": \"Item 2\", \"status\": \"Pending\"}]}]";
230
+ };
231
+ };
232
+ type WidgetType = keyof typeof WIDGET_DEFINITIONS;
233
+
165
234
  interface SuggestedPrompt {
166
235
  text: string;
167
236
  icon?: React.ReactNode;
@@ -195,12 +264,17 @@ interface ChatProps {
195
264
  onFileUpload?: (files: FileList) => void;
196
265
  onComplete?: (result: CommandResult) => void;
197
266
  onError?: (error: Error) => void;
267
+ onToolResult?: (toolName: string, result?: any) => void;
198
268
  theme?: 'light' | 'dark' | 'auto';
199
269
  placeholder?: string;
200
270
  showHeader?: boolean;
201
271
  headerTitle?: string;
202
272
  enableFileUpload?: boolean;
203
273
  enableMarkdown?: boolean;
274
+ enableWidgets?: boolean;
275
+ availableWidgets?: WidgetType[];
276
+ compactWidgetContext?: boolean;
277
+ onWidgetRender?: (widget: Widget) => void;
204
278
  className?: string;
205
279
  }
206
280
  interface CommandProps {
@@ -223,6 +297,7 @@ interface CommandProps {
223
297
  onError?: (error: Error) => void;
224
298
  onFileUpload?: (files: FileList) => void;
225
299
  onAction?: (action: ActionEvent) => void;
300
+ onToolResult?: (toolName: string, result?: any) => void;
226
301
  loadingText?: string;
227
302
  showProgress?: boolean;
228
303
  enableStreaming?: boolean;
@@ -304,7 +379,7 @@ interface UseAptevaKitReturn {
304
379
  error: Error | null;
305
380
  }
306
381
 
307
- declare function Chat({ agentId, threadId, initialMessages, context, apiUrl, apiKey, useMock, initialMode, showModeToggle, onModeChange, commandVariant, planMode, onPlanModeChange, enableStreaming, showProgress, loadingText, welcomeTitle, welcomeSubtitle, welcomeIcon, suggestedPrompts, welcomeVariant, onThreadChange, onMessageSent, onAction, onFileUpload, onComplete, onError, placeholder, showHeader, headerTitle, className, }: ChatProps): react_jsx_runtime.JSX.Element;
382
+ declare function Chat({ agentId, threadId, initialMessages, context, apiUrl, apiKey, useMock, initialMode, showModeToggle, onModeChange, commandVariant, planMode, onPlanModeChange, enableStreaming, showProgress, loadingText, welcomeTitle, welcomeSubtitle, welcomeIcon, suggestedPrompts, welcomeVariant, onThreadChange, onMessageSent, onAction, onFileUpload, onComplete, onError, onToolResult, placeholder, showHeader, headerTitle, enableWidgets, availableWidgets, compactWidgetContext, onWidgetRender, className, }: ChatProps): react_jsx_runtime.JSX.Element;
308
383
 
309
384
  declare function Command({ agentId, command: initialCommand, context, autoExecute, allowInput, placeholder, submitButtonText, variant, useMock, planMode, onPlanModeChange, enableFileUpload, onStart, onProgress, onChunk, onComplete, onError, onFileUpload, onAction, loadingText, showProgress, enableStreaming, resultRenderer, className, }: CommandProps): react_jsx_runtime.JSX.Element;
310
385
 
@@ -365,10 +440,11 @@ interface ChatResponse {
365
440
  widgets?: any[];
366
441
  }
367
442
  interface StreamChunk {
368
- type: 'start' | 'thread_id' | 'content' | 'token' | 'tool_call' | 'tool_input_delta' | 'tool_use' | 'tool_result' | 'stop' | 'widget' | 'complete' | 'done' | 'error';
443
+ type: 'start' | 'thread_id' | 'request_id' | 'content' | 'token' | 'tool_call' | 'tool_input_delta' | 'tool_use' | 'tool_result' | 'stop' | 'widget' | 'complete' | 'done' | 'error';
369
444
  content?: string;
370
445
  widget?: any;
371
446
  thread_id?: string;
447
+ request_id?: string;
372
448
  tool_id?: string;
373
449
  tool_name?: string;
374
450
  error?: string;
@@ -401,6 +477,10 @@ declare class AptevaClient {
401
477
  * Get thread messages
402
478
  */
403
479
  getThreadMessages(threadId: string): Promise<ChatMessage[]>;
480
+ /**
481
+ * Cancel an in-progress request
482
+ */
483
+ cancelRequest(agentId: string, requestId: string): Promise<void>;
404
484
  }
405
485
  declare const aptevaClient: AptevaClient;
406
486
 
@@ -410,4 +490,4 @@ declare const mockMessages: Message[];
410
490
  declare const mockThreads: Thread[];
411
491
  declare const mockWidgets: Widget[];
412
492
 
413
- export { type Action, type ActionEvent, AptevaClient, type AptevaClientConfig, type AptevaKitControl, Button, type ButtonGroupWidget, type ButtonWidget, Card, type CardWidget, type ChartWidget, Chat, type ChatMessage, type ChatProps, type ChatRequest, type ChatResponse, Command, type CommandProps, type CommandResult, type FormField, type FormWidget, type GalleryWidget, type ImageWidget, List, type ListItem, type ListWidget, type MapWidget, type Message, Prompt, type PromptProps, type SendMessageParams, Stream, type StreamChunk, type StreamProps, type SuggestedPrompt, type Thread, Threads, type ThreadsProps, type UseAptevaKitReturn, type Widget, Widgets, type WidgetsProps, aptevaClient, cn, getThemeScript, mockMessages, mockThreads, mockWidgets };
493
+ export { type Action, type ActionEvent, AptevaClient, type AptevaClientConfig, type AptevaKitControl, Button, type ButtonGroupWidget, type ButtonWidget, Card, type CardWidget, type ChartWidget, Chat, type ChatMessage, type ChatProps, type ChatRequest, type ChatResponse, Command, type CommandProps, type CommandResult, type FormField, type FormWidget, type GalleryWidget, type ImageWidget, List, type ListItem, type ListWidget, type MapWidget, type Message, Prompt, type PromptProps, type SendMessageParams, Stream, type StreamChunk, type StreamProps, type SuggestedPrompt, type TableColumn, type TableWidget, type Thread, Threads, type ThreadsProps, type UseAptevaKitReturn, type Widget, Widgets, type WidgetsProps, aptevaClient, cn, getThemeScript, mockMessages, mockThreads, mockWidgets };