@wotnak/json-render-react 0.0.0-pr.slots.9c5563f

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.
@@ -0,0 +1,663 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode, ComponentType } from 'react';
3
+ import { StateModel, VisibilityCondition, VisibilityContext, ActionHandler, ResolvedAction, ActionBinding, ActionConfirm, ValidationFunction, ValidationResult, ValidationConfig, Catalog, InferCatalogComponents, InferComponentProps, InferCatalogActions, InferActionParams, UIElement, SchemaDefinition, Spec, FlatElement } from '@json-render/core';
4
+ export { Spec, StateModel } from '@json-render/core';
5
+ export { ElementTreeSchema, ElementTreeSpec, ReactSchema, ReactSpec, elementTreeSchema, schema } from './schema.mjs';
6
+
7
+ /**
8
+ * State context value
9
+ */
10
+ interface StateContextValue {
11
+ /** The current state model */
12
+ state: StateModel;
13
+ /** Get a value by path */
14
+ get: (path: string) => unknown;
15
+ /** Set a value by path */
16
+ set: (path: string, value: unknown) => void;
17
+ /** Update multiple values at once */
18
+ update: (updates: Record<string, unknown>) => void;
19
+ }
20
+ /**
21
+ * Props for StateProvider
22
+ */
23
+ interface StateProviderProps {
24
+ /** Initial state model */
25
+ initialState?: StateModel;
26
+ /** Callback when state changes */
27
+ onStateChange?: (path: string, value: unknown) => void;
28
+ children: ReactNode;
29
+ }
30
+ /**
31
+ * Provider for state model context
32
+ */
33
+ declare function StateProvider({ initialState, onStateChange, children, }: StateProviderProps): react_jsx_runtime.JSX.Element;
34
+ /**
35
+ * Hook to access the state context
36
+ */
37
+ declare function useStateStore(): StateContextValue;
38
+ /**
39
+ * Hook to get a value from the state model
40
+ */
41
+ declare function useStateValue<T>(path: string): T | undefined;
42
+ /**
43
+ * Hook to get and set a value from the state model (like useState).
44
+ *
45
+ * @deprecated Use {@link useBoundProp} with `$bindState` expressions instead.
46
+ * `useStateBinding` takes a raw state path string, while `useBoundProp` works
47
+ * with the renderer's `bindings` map and supports both `$bindState` and
48
+ * `$bindItem` expressions.
49
+ */
50
+ declare function useStateBinding<T>(path: string): [T | undefined, (value: T) => void];
51
+
52
+ /**
53
+ * Visibility context value
54
+ */
55
+ interface VisibilityContextValue {
56
+ /** Evaluate a visibility condition */
57
+ isVisible: (condition: VisibilityCondition | undefined) => boolean;
58
+ /** The underlying visibility context */
59
+ ctx: VisibilityContext;
60
+ }
61
+ /**
62
+ * Props for VisibilityProvider
63
+ */
64
+ interface VisibilityProviderProps {
65
+ children: ReactNode;
66
+ }
67
+ /**
68
+ * Provider for visibility evaluation
69
+ */
70
+ declare function VisibilityProvider({ children }: VisibilityProviderProps): react_jsx_runtime.JSX.Element;
71
+ /**
72
+ * Hook to access visibility evaluation
73
+ */
74
+ declare function useVisibility(): VisibilityContextValue;
75
+ /**
76
+ * Hook to check if a condition is visible
77
+ */
78
+ declare function useIsVisible(condition: VisibilityCondition | undefined): boolean;
79
+
80
+ /**
81
+ * Pending confirmation state
82
+ */
83
+ interface PendingConfirmation {
84
+ /** The resolved action */
85
+ action: ResolvedAction;
86
+ /** The action handler */
87
+ handler: ActionHandler;
88
+ /** Resolve callback */
89
+ resolve: () => void;
90
+ /** Reject callback */
91
+ reject: () => void;
92
+ }
93
+ /**
94
+ * Action context value
95
+ */
96
+ interface ActionContextValue {
97
+ /** Registered action handlers */
98
+ handlers: Record<string, ActionHandler>;
99
+ /** Currently loading action names */
100
+ loadingActions: Set<string>;
101
+ /** Pending confirmation dialog */
102
+ pendingConfirmation: PendingConfirmation | null;
103
+ /** Execute an action binding */
104
+ execute: (binding: ActionBinding) => Promise<void>;
105
+ /** Confirm the pending action */
106
+ confirm: () => void;
107
+ /** Cancel the pending action */
108
+ cancel: () => void;
109
+ /** Register an action handler */
110
+ registerHandler: (name: string, handler: ActionHandler) => void;
111
+ }
112
+ /**
113
+ * Props for ActionProvider
114
+ */
115
+ interface ActionProviderProps {
116
+ /** Initial action handlers */
117
+ handlers?: Record<string, ActionHandler>;
118
+ /** Navigation function */
119
+ navigate?: (path: string) => void;
120
+ children: ReactNode;
121
+ }
122
+ /**
123
+ * Provider for action execution
124
+ */
125
+ declare function ActionProvider({ handlers: initialHandlers, navigate, children, }: ActionProviderProps): react_jsx_runtime.JSX.Element;
126
+ /**
127
+ * Hook to access action context
128
+ */
129
+ declare function useActions(): ActionContextValue;
130
+ /**
131
+ * Hook to execute an action binding
132
+ */
133
+ declare function useAction(binding: ActionBinding): {
134
+ execute: () => Promise<void>;
135
+ isLoading: boolean;
136
+ };
137
+ /**
138
+ * Props for ConfirmDialog component
139
+ */
140
+ interface ConfirmDialogProps {
141
+ /** The confirmation config */
142
+ confirm: ActionConfirm;
143
+ /** Called when confirmed */
144
+ onConfirm: () => void;
145
+ /** Called when cancelled */
146
+ onCancel: () => void;
147
+ }
148
+ /**
149
+ * Default confirmation dialog component
150
+ */
151
+ declare function ConfirmDialog({ confirm, onConfirm, onCancel, }: ConfirmDialogProps): react_jsx_runtime.JSX.Element;
152
+
153
+ /**
154
+ * Field validation state
155
+ */
156
+ interface FieldValidationState {
157
+ /** Whether the field has been touched */
158
+ touched: boolean;
159
+ /** Whether the field has been validated */
160
+ validated: boolean;
161
+ /** Validation result */
162
+ result: ValidationResult | null;
163
+ }
164
+ /**
165
+ * Validation context value
166
+ */
167
+ interface ValidationContextValue {
168
+ /** Custom validation functions from catalog */
169
+ customFunctions: Record<string, ValidationFunction>;
170
+ /** Validation state by field path */
171
+ fieldStates: Record<string, FieldValidationState>;
172
+ /** Validate a field */
173
+ validate: (path: string, config: ValidationConfig) => ValidationResult;
174
+ /** Mark field as touched */
175
+ touch: (path: string) => void;
176
+ /** Clear validation for a field */
177
+ clear: (path: string) => void;
178
+ /** Validate all fields */
179
+ validateAll: () => boolean;
180
+ /** Register field config */
181
+ registerField: (path: string, config: ValidationConfig) => void;
182
+ }
183
+ /**
184
+ * Props for ValidationProvider
185
+ */
186
+ interface ValidationProviderProps {
187
+ /** Custom validation functions from catalog */
188
+ customFunctions?: Record<string, ValidationFunction>;
189
+ children: ReactNode;
190
+ }
191
+ /**
192
+ * Provider for validation
193
+ */
194
+ declare function ValidationProvider({ customFunctions, children, }: ValidationProviderProps): react_jsx_runtime.JSX.Element;
195
+ /**
196
+ * Hook to access validation context
197
+ */
198
+ declare function useValidation(): ValidationContextValue;
199
+ /**
200
+ * Hook to get validation state for a field
201
+ */
202
+ declare function useFieldValidation(path: string, config?: ValidationConfig): {
203
+ state: FieldValidationState;
204
+ validate: () => ValidationResult;
205
+ touch: () => void;
206
+ clear: () => void;
207
+ errors: string[];
208
+ isValid: boolean;
209
+ };
210
+
211
+ /**
212
+ * Repeat scope value provided to child elements inside a repeated element.
213
+ */
214
+ interface RepeatScopeValue {
215
+ /** The current array item object */
216
+ item: unknown;
217
+ /** Index of the current item in the array */
218
+ index: number;
219
+ /** Absolute state path to the current array item (e.g. "/todos/0") — used for statePath two-way binding */
220
+ basePath: string;
221
+ }
222
+ /**
223
+ * Provides repeat scope to child elements so $item and $index expressions resolve correctly.
224
+ */
225
+ declare function RepeatScopeProvider({ item, index, basePath, children, }: RepeatScopeValue & {
226
+ children: ReactNode;
227
+ }): react_jsx_runtime.JSX.Element;
228
+ /**
229
+ * Read the current repeat scope (or null if not inside a repeated element).
230
+ */
231
+ declare function useRepeatScope(): RepeatScopeValue | null;
232
+
233
+ /**
234
+ * State setter function for updating application state
235
+ */
236
+ type SetState = (updater: (prev: Record<string, unknown>) => Record<string, unknown>) => void;
237
+ /**
238
+ * Context passed to component render functions
239
+ * @example
240
+ * const Button: ComponentFn<typeof catalog, 'Button'> = (ctx) => {
241
+ * return <button onClick={() => ctx.emit("press")}>{ctx.props.label}</button>
242
+ * }
243
+ */
244
+ interface ComponentContext<C extends Catalog, K extends keyof InferCatalogComponents<C>> {
245
+ props: InferComponentProps<C, K>;
246
+ children?: ReactNode;
247
+ slots?: Record<string, ReactNode>;
248
+ /** Emit a named event. The renderer resolves the event to an action binding from the element's `on` field. */
249
+ emit: (event: string) => void;
250
+ /**
251
+ * Two-way binding paths resolved from `$bindState` / `$bindItem` expressions.
252
+ * Maps prop name → absolute state path for write-back.
253
+ */
254
+ bindings?: Record<string, string>;
255
+ loading?: boolean;
256
+ }
257
+ /**
258
+ * Component render function type for React
259
+ * @example
260
+ * const Button: ComponentFn<typeof catalog, 'Button'> = ({ props, emit }) => (
261
+ * <button onClick={() => emit("press")}>{props.label}</button>
262
+ * );
263
+ */
264
+ type ComponentFn<C extends Catalog, K extends keyof InferCatalogComponents<C>> = (ctx: ComponentContext<C, K>) => ReactNode;
265
+ /**
266
+ * Registry of all component render functions for a catalog
267
+ * @example
268
+ * const components: Components<typeof myCatalog> = {
269
+ * Button: ({ props }) => <button>{props.label}</button>,
270
+ * Input: ({ props }) => <input placeholder={props.placeholder} />,
271
+ * };
272
+ */
273
+ type Components<C extends Catalog> = {
274
+ [K in keyof InferCatalogComponents<C>]: ComponentFn<C, K>;
275
+ };
276
+ /**
277
+ * Action handler function type
278
+ * @example
279
+ * const viewCustomers: ActionFn<typeof catalog, 'viewCustomers'> = async (params, setState) => {
280
+ * const data = await fetch('/api/customers');
281
+ * setState(prev => ({ ...prev, customers: data }));
282
+ * };
283
+ */
284
+ type ActionFn<C extends Catalog, K extends keyof InferCatalogActions<C>> = (params: InferActionParams<C, K> | undefined, setState: SetState, state: StateModel) => Promise<void>;
285
+ /**
286
+ * Registry of all action handlers for a catalog
287
+ * @example
288
+ * const actions: Actions<typeof myCatalog> = {
289
+ * viewCustomers: async (params, setState) => { ... },
290
+ * createCustomer: async (params, setState) => { ... },
291
+ * };
292
+ */
293
+ type Actions<C extends Catalog> = {
294
+ [K in keyof InferCatalogActions<C>]: ActionFn<C, K>;
295
+ };
296
+
297
+ /**
298
+ * Props passed to component renderers
299
+ */
300
+ interface ComponentRenderProps<P = Record<string, unknown>> {
301
+ /** The element being rendered */
302
+ element: UIElement<string, P>;
303
+ /** Rendered children (default slot) */
304
+ children?: ReactNode;
305
+ /** Named slots - maps slot names to rendered children */
306
+ slots?: Record<string, ReactNode>;
307
+ /** Emit a named event. The renderer resolves the event to action binding(s) from the element's `on` field. Always provided by the renderer. */
308
+ emit: (event: string) => void;
309
+ /**
310
+ * Two-way binding paths resolved from `$bindState` / `$bindItem` expressions.
311
+ * Maps prop name → absolute state path for write-back.
312
+ * Only present when at least one prop uses `{ $bindState: "..." }` or `{ $bindItem: "..." }`.
313
+ */
314
+ bindings?: Record<string, string>;
315
+ /** Whether the parent is loading */
316
+ loading?: boolean;
317
+ }
318
+ /**
319
+ * Component renderer type
320
+ */
321
+ type ComponentRenderer<P = Record<string, unknown>> = ComponentType<ComponentRenderProps<P>>;
322
+ /**
323
+ * Registry of component renderers
324
+ */
325
+ type ComponentRegistry = Record<string, ComponentRenderer<any>>;
326
+ /**
327
+ * Props for the Renderer component
328
+ */
329
+ interface RendererProps {
330
+ /** The UI spec to render */
331
+ spec: Spec | null;
332
+ /** Component registry */
333
+ registry: ComponentRegistry;
334
+ /** Whether the spec is currently loading/streaming */
335
+ loading?: boolean;
336
+ /** Fallback component for unknown types */
337
+ fallback?: ComponentRenderer;
338
+ }
339
+ /**
340
+ * Main renderer component
341
+ */
342
+ declare function Renderer({ spec, registry, loading, fallback }: RendererProps): react_jsx_runtime.JSX.Element | null;
343
+ /**
344
+ * Props for JSONUIProvider
345
+ */
346
+ interface JSONUIProviderProps {
347
+ /** Component registry */
348
+ registry: ComponentRegistry;
349
+ /** Initial state model */
350
+ initialState?: Record<string, unknown>;
351
+ /** Action handlers */
352
+ handlers?: Record<string, (params: Record<string, unknown>) => Promise<unknown> | unknown>;
353
+ /** Navigation function */
354
+ navigate?: (path: string) => void;
355
+ /** Custom validation functions */
356
+ validationFunctions?: Record<string, (value: unknown, args?: Record<string, unknown>) => boolean>;
357
+ /** Callback when state changes */
358
+ onStateChange?: (path: string, value: unknown) => void;
359
+ children: ReactNode;
360
+ }
361
+ /**
362
+ * Combined provider for all JSONUI contexts
363
+ */
364
+ declare function JSONUIProvider({ registry, initialState, handlers, navigate, validationFunctions, onStateChange, children, }: JSONUIProviderProps): react_jsx_runtime.JSX.Element;
365
+ /**
366
+ * Result returned by defineRegistry
367
+ */
368
+ interface DefineRegistryResult {
369
+ /** Component registry for `<Renderer registry={...} />` */
370
+ registry: ComponentRegistry;
371
+ /**
372
+ * Create ActionProvider-compatible handlers.
373
+ * Accepts getter functions so handlers always read the latest state/setState
374
+ * (e.g. from React refs).
375
+ */
376
+ handlers: (getSetState: () => SetState | undefined, getState: () => StateModel) => Record<string, (params: Record<string, unknown>) => Promise<void>>;
377
+ /**
378
+ * Execute an action by name imperatively
379
+ * (for use outside the React tree, e.g. initial state loading).
380
+ */
381
+ executeAction: (actionName: string, params: Record<string, unknown> | undefined, setState: SetState, state?: StateModel) => Promise<void>;
382
+ }
383
+ /**
384
+ * Create a registry from a catalog with components and/or actions.
385
+ *
386
+ * @example
387
+ * ```tsx
388
+ * // Components only
389
+ * const { registry } = defineRegistry(catalog, {
390
+ * components: {
391
+ * Card: ({ props, children }) => (
392
+ * <div className="card">{props.title}{children}</div>
393
+ * ),
394
+ * },
395
+ * });
396
+ *
397
+ * // Actions only
398
+ * const { handlers, executeAction } = defineRegistry(catalog, {
399
+ * actions: {
400
+ * viewCustomers: async (params, setState) => { ... },
401
+ * },
402
+ * });
403
+ *
404
+ * // Both
405
+ * const { registry, handlers, executeAction } = defineRegistry(catalog, {
406
+ * components: { ... },
407
+ * actions: { ... },
408
+ * });
409
+ * ```
410
+ */
411
+ declare function defineRegistry<C extends Catalog>(catalog: C, options: {
412
+ components?: Components<C>;
413
+ actions?: Actions<C>;
414
+ }): DefineRegistryResult;
415
+ /**
416
+ * Props for renderers created with createRenderer
417
+ */
418
+ interface CreateRendererProps {
419
+ /** The spec to render (AI-generated JSON) */
420
+ spec: Spec | null;
421
+ /** State context for dynamic values */
422
+ state?: Record<string, unknown>;
423
+ /** Action handler */
424
+ onAction?: (actionName: string, params?: Record<string, unknown>) => void;
425
+ /** Callback when state changes (e.g., from form inputs) */
426
+ onStateChange?: (path: string, value: unknown) => void;
427
+ /** Whether the spec is currently loading/streaming */
428
+ loading?: boolean;
429
+ /** Fallback component for unknown types */
430
+ fallback?: ComponentRenderer;
431
+ }
432
+ /**
433
+ * Component map type - maps component names to React components
434
+ */
435
+ type ComponentMap<TComponents extends Record<string, {
436
+ props: unknown;
437
+ }>> = {
438
+ [K in keyof TComponents]: ComponentType<ComponentRenderProps<TComponents[K]["props"] extends {
439
+ _output: infer O;
440
+ } ? O : Record<string, unknown>>>;
441
+ };
442
+ /**
443
+ * Create a renderer from a catalog
444
+ *
445
+ * @example
446
+ * ```typescript
447
+ * const DashboardRenderer = createRenderer(dashboardCatalog, {
448
+ * Card: ({ element, children }) => <div className="card">{children}</div>,
449
+ * Metric: ({ element }) => <span>{element.props.value}</span>,
450
+ * });
451
+ *
452
+ * // Usage
453
+ * <DashboardRenderer spec={aiGeneratedSpec} state={state} />
454
+ * ```
455
+ */
456
+ declare function createRenderer<TDef extends SchemaDefinition, TCatalog extends {
457
+ components: Record<string, {
458
+ props: unknown;
459
+ }>;
460
+ }>(catalog: Catalog<TDef, TCatalog>, components: ComponentMap<TCatalog["components"]>): ComponentType<CreateRendererProps>;
461
+
462
+ /**
463
+ * Token usage metadata from AI generation
464
+ */
465
+ interface TokenUsage {
466
+ promptTokens: number;
467
+ completionTokens: number;
468
+ totalTokens: number;
469
+ }
470
+ /**
471
+ * Options for useUIStream
472
+ */
473
+ interface UseUIStreamOptions {
474
+ /** API endpoint */
475
+ api: string;
476
+ /** Callback when complete */
477
+ onComplete?: (spec: Spec) => void;
478
+ /** Callback on error */
479
+ onError?: (error: Error) => void;
480
+ }
481
+ /**
482
+ * Return type for useUIStream
483
+ */
484
+ interface UseUIStreamReturn {
485
+ /** Current UI spec */
486
+ spec: Spec | null;
487
+ /** Whether currently streaming */
488
+ isStreaming: boolean;
489
+ /** Error if any */
490
+ error: Error | null;
491
+ /** Token usage from the last generation */
492
+ usage: TokenUsage | null;
493
+ /** Raw JSONL lines received from the stream (JSON patch lines) */
494
+ rawLines: string[];
495
+ /** Send a prompt to generate UI */
496
+ send: (prompt: string, context?: Record<string, unknown>) => Promise<void>;
497
+ /** Clear the current spec */
498
+ clear: () => void;
499
+ }
500
+ /**
501
+ * Hook for streaming UI generation
502
+ */
503
+ declare function useUIStream({ api, onComplete, onError, }: UseUIStreamOptions): UseUIStreamReturn;
504
+ /**
505
+ * Convert a flat element list to a Spec.
506
+ * Input elements use key/parentKey to establish identity and relationships.
507
+ * Output spec uses the map-based format where key is the map entry key
508
+ * and parent-child relationships are expressed through children arrays.
509
+ */
510
+ declare function flatToTree(elements: FlatElement[]): Spec;
511
+ /**
512
+ * Hook for two-way bound props. Returns `[value, setValue]` where:
513
+ *
514
+ * - `value` is the already-resolved prop value (passed through from render props)
515
+ * - `setValue` writes back to the bound state path (no-op if not bound)
516
+ *
517
+ * Designed to work with the `bindings` map that the renderer provides when
518
+ * a prop uses `{ $bindState: "/path" }` or `{ $bindItem: "field" }`.
519
+ *
520
+ * @example
521
+ * ```tsx
522
+ * import { useBoundProp } from "@json-render/react";
523
+ *
524
+ * const Input: ComponentRenderer = ({ props, bindings }) => {
525
+ * const [value, setValue] = useBoundProp<string>(props.value, bindings?.value);
526
+ * return <input value={value ?? ""} onChange={(e) => setValue(e.target.value)} />;
527
+ * };
528
+ * ```
529
+ */
530
+ declare function useBoundProp<T>(propValue: T | undefined, bindingPath: string | undefined): [T | undefined, (value: T) => void];
531
+ /**
532
+ * A single part from the AI SDK's `message.parts` array. This is a minimal
533
+ * structural type so that library helpers do not depend on the AI SDK.
534
+ * Fields are optional because different part types carry different data:
535
+ * - Text parts have `text`
536
+ * - Data parts have `data`
537
+ */
538
+ interface DataPart {
539
+ type: string;
540
+ text?: string;
541
+ data?: unknown;
542
+ }
543
+ declare function buildSpecFromParts(parts: DataPart[]): Spec | null;
544
+ /**
545
+ * Extract and join all text content from a message's parts array.
546
+ *
547
+ * Filters for parts with `type === "text"`, trims each one, and joins them
548
+ * with double newlines so that text from separate agent steps renders as
549
+ * distinct paragraphs in markdown.
550
+ *
551
+ * Has no AI SDK dependency — operates on a generic `DataPart[]`.
552
+ *
553
+ * @example
554
+ * ```tsx
555
+ * const text = getTextFromParts(message.parts);
556
+ * if (text) {
557
+ * return <Streamdown>{text}</Streamdown>;
558
+ * }
559
+ * ```
560
+ */
561
+ declare function getTextFromParts(parts: DataPart[]): string;
562
+ /**
563
+ * Hook that extracts both the json-render spec and text content from a
564
+ * message's parts array. Combines `buildSpecFromParts` and `getTextFromParts`
565
+ * into a single call with memoized results.
566
+ *
567
+ * **Memoization behavior:** Results are recomputed only when the `parts` array
568
+ * reference changes **and** either the length differs or the last element is a
569
+ * different object. This is optimized for the typical AI SDK streaming pattern
570
+ * where parts are appended incrementally. Mid-array edits (e.g. replacing an
571
+ * earlier part without appending) may not trigger recomputation. If you need to
572
+ * force a recompute after such edits, pass a new array reference with a
573
+ * different last element.
574
+ *
575
+ * @example
576
+ * ```tsx
577
+ * import { useJsonRenderMessage } from "@json-render/react";
578
+ *
579
+ * function MessageBubble({ message }) {
580
+ * const { spec, text, hasSpec } = useJsonRenderMessage(message.parts);
581
+ *
582
+ * return (
583
+ * <div>
584
+ * {text && <Markdown>{text}</Markdown>}
585
+ * {hasSpec && <MyRenderer spec={spec} />}
586
+ * </div>
587
+ * );
588
+ * }
589
+ * ```
590
+ */
591
+ declare function useJsonRenderMessage(parts: DataPart[]): {
592
+ spec: Spec | null;
593
+ text: string;
594
+ hasSpec: boolean;
595
+ };
596
+ /**
597
+ * A single message in the chat, which may contain text, a rendered UI spec, or both.
598
+ */
599
+ interface ChatMessage {
600
+ /** Unique message ID */
601
+ id: string;
602
+ /** Who sent this message */
603
+ role: "user" | "assistant";
604
+ /** Text content (conversational prose) */
605
+ text: string;
606
+ /** json-render Spec built from JSONL patches (null if no UI was generated) */
607
+ spec: Spec | null;
608
+ }
609
+ /**
610
+ * Options for useChatUI
611
+ */
612
+ interface UseChatUIOptions {
613
+ /** API endpoint that accepts `{ messages: Array<{ role, content }> }` and returns a text stream */
614
+ api: string;
615
+ /** Callback when streaming completes for a message */
616
+ onComplete?: (message: ChatMessage) => void;
617
+ /** Callback on error */
618
+ onError?: (error: Error) => void;
619
+ }
620
+ /**
621
+ * Return type for useChatUI
622
+ */
623
+ interface UseChatUIReturn {
624
+ /** All messages in the conversation */
625
+ messages: ChatMessage[];
626
+ /** Whether currently streaming an assistant response */
627
+ isStreaming: boolean;
628
+ /** Error from the last request, if any */
629
+ error: Error | null;
630
+ /** Send a user message */
631
+ send: (text: string) => Promise<void>;
632
+ /** Clear all messages and reset the conversation */
633
+ clear: () => void;
634
+ }
635
+ /**
636
+ * Hook for chat + GenUI experiences.
637
+ *
638
+ * Manages a multi-turn conversation where each assistant message can contain
639
+ * both conversational text and a json-render UI spec. The hook sends the full
640
+ * message history to the API endpoint, reads the streamed response, and
641
+ * separates text lines from JSONL patch lines using `createMixedStreamParser`.
642
+ *
643
+ * @example
644
+ * ```tsx
645
+ * const { messages, isStreaming, send, clear } = useChatUI({
646
+ * api: "/api/chat",
647
+ * });
648
+ *
649
+ * // Send a message
650
+ * await send("Compare weather in NYC and Tokyo");
651
+ *
652
+ * // Render messages
653
+ * {messages.map((msg) => (
654
+ * <div key={msg.id}>
655
+ * {msg.text && <p>{msg.text}</p>}
656
+ * {msg.spec && <MyRenderer spec={msg.spec} />}
657
+ * </div>
658
+ * ))}
659
+ * ```
660
+ */
661
+ declare function useChatUI({ api, onComplete, onError, }: UseChatUIOptions): UseChatUIReturn;
662
+
663
+ export { type ActionContextValue, type ActionFn, ActionProvider, type ActionProviderProps, type Actions, type ChatMessage, type ComponentContext, type ComponentFn, type ComponentMap, type ComponentRegistry, type ComponentRenderProps, type ComponentRenderer, type Components, ConfirmDialog, type ConfirmDialogProps, type CreateRendererProps, type DataPart, type DefineRegistryResult, type FieldValidationState, JSONUIProvider, type JSONUIProviderProps, type PendingConfirmation, Renderer, type RendererProps, RepeatScopeProvider, type RepeatScopeValue, type SetState, type StateContextValue, StateProvider, type StateProviderProps, type TokenUsage, type UseChatUIOptions, type UseChatUIReturn, type UseUIStreamOptions, type UseUIStreamReturn, type ValidationContextValue, ValidationProvider, type ValidationProviderProps, type VisibilityContextValue, VisibilityProvider, type VisibilityProviderProps, buildSpecFromParts, createRenderer, defineRegistry, flatToTree, getTextFromParts, useAction, useActions, useBoundProp, useChatUI, useFieldValidation, useIsVisible, useJsonRenderMessage, useRepeatScope, useStateBinding, useStateStore, useStateValue, useUIStream, useValidation, useVisibility };