import * as react_jsx_runtime from 'react/jsx-runtime'; import { ReactNode, ComponentType } from 'react'; import { StateStore, StateModel, VisibilityCondition, VisibilityContext, ActionHandler, ResolvedAction, ActionBinding, ActionConfirm, ValidationFunction, ValidationResult, ValidationConfig, Catalog, InferCatalogComponents, InferComponentProps, InferCatalogActions, InferActionParams, UIElement, SchemaDefinition, Spec, ComputedFunction, DirectiveDefinition, FlatElement } from '@json-render/core'; export { Spec, StateModel, StateStore, createStateStore } from '@json-render/core'; export { ElementTreeSchema, ElementTreeSpec, ReactSchema, ReactSpec, elementTreeSchema, schema } from './schema.mjs'; /** * State context value */ interface StateContextValue { /** The current state model */ state: StateModel; /** Get a value by path */ get: (path: string) => unknown; /** Set a value by path */ set: (path: string, value: unknown) => void; /** Update multiple values at once */ update: (updates: Record) => void; /** Return the live state snapshot from the underlying store (not the React render snapshot). */ getSnapshot: () => StateModel; } /** * Props for StateProvider */ interface StateProviderProps { /** * External store that owns the state. When provided, the provider operates * in **controlled mode** — `initialState` and `onStateChange` are ignored * and the store is the single source of truth. */ store?: StateStore; /** Initial state model (used only in uncontrolled mode) */ initialState?: StateModel; /** * Callback when state changes (used only in uncontrolled mode). * Called once per `set` or `update` with all changed entries. */ onStateChange?: (changes: Array<{ path: string; value: unknown; }>) => void; children: ReactNode; } /** * Provider for state model context. * * Supports two modes: * - **Controlled**: pass a `store` prop (e.g. backed by Redux / Zustand). * - **Uncontrolled** (default): omit `store` and optionally pass * `initialState` / `onStateChange`. */ declare function StateProvider({ store: externalStore, initialState, onStateChange, children, }: StateProviderProps): react_jsx_runtime.JSX.Element; /** * Hook to access the state context */ declare function useStateStore(): StateContextValue; /** * Hook to get a value from the state model */ declare function useStateValue(path: string): T | undefined; /** * Hook to get and set a value from the state model (like useState). * * @deprecated Use {@link useBoundProp} with `$bindState` expressions instead. * `useStateBinding` takes a raw state path string, while `useBoundProp` works * with the renderer's `bindings` map and supports both `$bindState` and * `$bindItem` expressions. */ declare function useStateBinding(path: string): [T | undefined, (value: T) => void]; /** * Visibility context value */ interface VisibilityContextValue { /** Evaluate a visibility condition */ isVisible: (condition: VisibilityCondition | undefined) => boolean; /** The underlying visibility context */ ctx: VisibilityContext; } /** * Props for VisibilityProvider */ interface VisibilityProviderProps { children: ReactNode; } /** * Provider for visibility evaluation */ declare function VisibilityProvider({ children }: VisibilityProviderProps): react_jsx_runtime.JSX.Element; /** * Hook to access visibility evaluation */ declare function useVisibility(): VisibilityContextValue; /** * Hook to check if a condition is visible */ declare function useIsVisible(condition: VisibilityCondition | undefined): boolean; /** * Pending confirmation state */ interface PendingConfirmation { /** The resolved action */ action: ResolvedAction; /** The action handler */ handler: ActionHandler; /** Resolve callback */ resolve: () => void; /** Reject callback */ reject: () => void; } /** * Action context value */ interface ActionContextValue { /** Registered action handlers */ handlers: Record; /** Currently loading action names */ loadingActions: Set; /** Pending confirmation dialog */ pendingConfirmation: PendingConfirmation | null; /** Execute an action binding */ execute: (binding: ActionBinding) => Promise; /** Confirm the pending action */ confirm: () => void; /** Cancel the pending action */ cancel: () => void; /** Register an action handler */ registerHandler: (name: string, handler: ActionHandler) => void; } /** * Props for ActionProvider */ interface ActionProviderProps { /** Initial action handlers */ handlers?: Record; /** Navigation function */ navigate?: (path: string) => void; children: ReactNode; } /** * Provider for action execution */ declare function ActionProvider({ handlers: initialHandlers, navigate, children, }: ActionProviderProps): react_jsx_runtime.JSX.Element; /** * Hook to access action context */ declare function useActions(): ActionContextValue; /** * Hook to execute an action binding */ declare function useAction(binding: ActionBinding): { execute: () => Promise; isLoading: boolean; }; /** * Props for ConfirmDialog component */ interface ConfirmDialogProps { /** The confirmation config */ confirm: ActionConfirm; /** Called when confirmed */ onConfirm: () => void; /** Called when cancelled */ onCancel: () => void; } /** * Default confirmation dialog component */ declare function ConfirmDialog({ confirm, onConfirm, onCancel, }: ConfirmDialogProps): react_jsx_runtime.JSX.Element; /** * Field validation state */ interface FieldValidationState { /** Whether the field has been touched */ touched: boolean; /** Whether the field has been validated */ validated: boolean; /** Validation result */ result: ValidationResult | null; } /** * Validation context value */ interface ValidationContextValue { /** Custom validation functions from catalog */ customFunctions: Record; /** Validation state by field path */ fieldStates: Record; /** Validate a field */ validate: (path: string, config: ValidationConfig) => ValidationResult; /** Mark field as touched */ touch: (path: string) => void; /** Clear validation for a field */ clear: (path: string) => void; /** Validate all fields */ validateAll: () => boolean; /** Register field config */ registerField: (path: string, config: ValidationConfig) => void; } /** * Props for ValidationProvider */ interface ValidationProviderProps { /** Custom validation functions from catalog */ customFunctions?: Record; children: ReactNode; } /** * Provider for validation */ declare function ValidationProvider({ customFunctions, children, }: ValidationProviderProps): react_jsx_runtime.JSX.Element; /** * Hook to access validation context */ declare function useValidation(): ValidationContextValue; /** * Non-throwing variant of useValidation. * Returns null when no ValidationProvider is present. */ declare function useOptionalValidation(): ValidationContextValue | null; /** * Hook to get validation state for a field */ declare function useFieldValidation(path: string, config?: ValidationConfig): { state: FieldValidationState; validate: () => ValidationResult; touch: () => void; clear: () => void; errors: string[]; isValid: boolean; }; /** * Repeat scope value provided to child elements inside a repeated element. */ interface RepeatScopeValue { /** The current array item object */ item: unknown; /** Index of the current item in the array */ index: number; /** Absolute state path to the current array item (e.g. "/todos/0") — used for statePath two-way binding */ basePath: string; } /** * Provides repeat scope to child elements so $item and $index expressions resolve correctly. */ declare function RepeatScopeProvider({ item, index, basePath, children, }: RepeatScopeValue & { children: ReactNode; }): react_jsx_runtime.JSX.Element; /** * Read the current repeat scope (or null if not inside a repeated element). */ declare function useRepeatScope(): RepeatScopeValue | null; /** * State setter function for updating application state */ type SetState = (updater: (prev: Record) => Record) => void; /** * Handle returned by the `on()` function for a specific event. * Provides metadata about the event binding and a method to fire it. * * @example * ```ts * const press = on("press"); * if (press.shouldPreventDefault) e.preventDefault(); * press.emit(); * ``` */ interface EventHandle { /** Fire the event (resolve action bindings) */ emit: () => void; /** Whether any binding requested preventDefault */ shouldPreventDefault: boolean; /** Whether any handler is bound to this event */ bound: boolean; } /** * Catalog-agnostic base type for component render function arguments. * Use this when building reusable component libraries (e.g. `@json-render/shadcn`) * that are not tied to a specific catalog. * * @example * ```ts * const Card = ({ props, children }: BaseComponentProps<{ title?: string }>) => ( *
{props.title}{children}
* ); * ``` */ interface BaseComponentProps

> { props: P; children?: ReactNode; /** Simple event emitter (shorthand). Fires the event and returns void. */ emit: (event: string) => void; /** Get an event handle with metadata. Use when you need shouldPreventDefault or bound checks. */ on: (event: string) => EventHandle; /** * Two-way binding paths resolved from `$bindState` / `$bindItem` expressions. * Maps prop name → absolute state path for write-back. */ bindings?: Record; loading?: boolean; } /** * Context passed to component render functions * @example * const Button: ComponentFn = (ctx) => { * return * } */ interface ComponentContext> extends BaseComponentProps> { } /** * Component render function type for React * @example * const Button: ComponentFn = ({ props, emit }) => ( * * ); */ type ComponentFn> = (ctx: ComponentContext) => ReactNode; /** * Registry of all component render functions for a catalog * @example * const components: Components = { * Button: ({ props }) => , * Input: ({ props }) => , * }; */ type Components = { [K in keyof InferCatalogComponents]: ComponentFn; }; /** * Action handler function type * @example * const viewCustomers: ActionFn = async (params, setState) => { * const data = await fetch('/api/customers'); * setState(prev => ({ ...prev, customers: data })); * }; */ type ActionFn> = (params: InferActionParams | undefined, setState: SetState, state: StateModel) => Promise; /** * Registry of all action handlers for a catalog * @example * const actions: Actions = { * viewCustomers: async (params, setState) => { ... }, * createCustomer: async (params, setState) => { ... }, * }; */ type Actions = { [K in keyof InferCatalogActions]: ActionFn; }; /** * True when the catalog declares at least one action, false otherwise. * Used by defineRegistry to conditionally require the `actions` field. */ type CatalogHasActions = [ InferCatalogActions ] extends [never] ? false : [keyof InferCatalogActions] extends [never] ? false : true; /** * Props passed to component renderers */ interface ComponentRenderProps

> { /** The element being rendered */ element: UIElement; /** Rendered children */ children?: ReactNode; /** Emit a named event. The renderer resolves the event to action binding(s) from the element's `on` field. Always provided by the renderer. */ emit: (event: string) => void; /** Get an event handle with metadata (shouldPreventDefault, bound). Use when you need to inspect event bindings. */ on: (event: string) => EventHandle; /** * Two-way binding paths resolved from `$bindState` / `$bindItem` expressions. * Maps prop name → absolute state path for write-back. * Only present when at least one prop uses `{ $bindState: "..." }` or `{ $bindItem: "..." }`. */ bindings?: Record; /** Whether the parent is loading */ loading?: boolean; } /** * Component renderer type */ type ComponentRenderer

> = ComponentType>; /** * Registry of component renderers */ type ComponentRegistry = Record>; /** * Props for the Renderer component */ interface RendererProps { /** The UI spec to render */ spec: Spec | null; /** Component registry */ registry: ComponentRegistry; /** Whether the spec is currently loading/streaming */ loading?: boolean; /** Fallback component for unknown types */ fallback?: ComponentRenderer; } /** * Main renderer component */ declare function Renderer({ spec, registry, loading, fallback }: RendererProps): react_jsx_runtime.JSX.Element | null; /** * Props for JSONUIProvider */ interface JSONUIProviderProps { /** Component registry */ registry: ComponentRegistry; /** * External store (controlled mode). When provided, `initialState` and * `onStateChange` are ignored. */ store?: StateStore; /** Initial state model (uncontrolled mode) */ initialState?: Record; /** Action handlers */ handlers?: Record) => Promise | unknown>; /** Navigation function */ navigate?: (path: string) => void; /** Custom validation functions */ validationFunctions?: Record) => boolean>; /** Named functions for `$computed` expressions in props */ functions?: Record; /** Custom directives for user-defined `$`-prefixed dynamic values */ directives?: DirectiveDefinition[]; /** Callback when state changes (uncontrolled mode) */ onStateChange?: (changes: Array<{ path: string; value: unknown; }>) => void; children: ReactNode; } /** * Combined provider for all JSONUI contexts */ declare function JSONUIProvider({ registry, store, initialState, handlers, navigate, validationFunctions, functions, directives, onStateChange, children, }: JSONUIProviderProps): react_jsx_runtime.JSX.Element; /** * Result returned by defineRegistry */ interface DefineRegistryResult { /** Component registry for `` */ registry: ComponentRegistry; /** * Create ActionProvider-compatible handlers. * Accepts getter functions so handlers always read the latest state/setState * (e.g. from React refs). */ handlers: (getSetState: () => SetState | undefined, getState: () => StateModel) => Record) => Promise>; /** * Execute an action by name imperatively * (for use outside the React tree, e.g. initial state loading). */ executeAction: (actionName: string, params: Record | undefined, setState: SetState, state?: StateModel) => Promise; } /** * Options for defineRegistry. * * When the catalog declares actions, the `actions` field is required. * When the catalog has no actions (or `actions: {}`), the field is optional. */ type DefineRegistryOptions = { components?: Components; } & (CatalogHasActions extends true ? { actions: Actions; } : { actions?: Actions; }); /** * Create a registry from a catalog with components and/or actions. * * When the catalog declares actions, the `actions` field is required. * * @example * ```tsx * // Components only (catalog has no actions) * const { registry } = defineRegistry(catalog, { * components: { * Card: ({ props, children }) => ( *

{props.title}{children}
* ), * }, * }); * * // Both (catalog declares actions) * const { registry, handlers, executeAction } = defineRegistry(catalog, { * components: { ... }, * actions: { ... }, * }); * ``` */ declare function defineRegistry(_catalog: C, options: DefineRegistryOptions): DefineRegistryResult; /** * Props for renderers created with createRenderer */ interface CreateRendererProps { /** The spec to render (AI-generated JSON) */ spec: Spec | null; /** * External store (controlled mode). When provided, `state` and * `onStateChange` are ignored. */ store?: StateStore; /** State context for dynamic values (uncontrolled mode) */ state?: Record; /** Action handler */ onAction?: (actionName: string, params?: Record) => void; /** Callback when state changes (uncontrolled mode) */ onStateChange?: (changes: Array<{ path: string; value: unknown; }>) => void; /** Named functions for `$computed` expressions in props */ functions?: Record; /** Custom directives for user-defined `$`-prefixed dynamic values */ directives?: DirectiveDefinition[]; /** Whether the spec is currently loading/streaming */ loading?: boolean; /** Fallback component for unknown types */ fallback?: ComponentRenderer; } /** * Component map type - maps component names to React components */ type ComponentMap> = { [K in keyof TComponents]: ComponentType>>; }; /** * Create a renderer from a catalog * * @example * ```typescript * const DashboardRenderer = createRenderer(dashboardCatalog, { * Card: ({ element, children }) =>
{children}
, * Metric: ({ element }) => {element.props.value}, * }); * * // Usage * * ``` */ declare function createRenderer; }>(catalog: Catalog, components: ComponentMap): ComponentType; /** * Token usage metadata from AI generation */ interface TokenUsage { promptTokens: number; completionTokens: number; totalTokens: number; } /** * Options for useUIStream */ interface UseUIStreamOptions { /** API endpoint */ api: string; /** Callback when complete */ onComplete?: (spec: Spec) => void; /** Callback on error */ onError?: (error: Error) => void; } /** * Return type for useUIStream */ interface UseUIStreamReturn { /** Current UI spec */ spec: Spec | null; /** Whether currently streaming */ isStreaming: boolean; /** Error if any */ error: Error | null; /** Token usage from the last generation */ usage: TokenUsage | null; /** Raw JSONL lines received from the stream (JSON patch lines) */ rawLines: string[]; /** Send a prompt to generate UI */ send: (prompt: string, context?: Record) => Promise; /** Clear the current spec */ clear: () => void; } /** * Hook for streaming UI generation */ declare function useUIStream({ api, onComplete, onError, }: UseUIStreamOptions): UseUIStreamReturn; /** * Convert a flat element list to a Spec. * Input elements use key/parentKey to establish identity and relationships. * Output spec uses the map-based format where key is the map entry key * and parent-child relationships are expressed through children arrays. */ declare function flatToTree(elements: FlatElement[]): Spec; /** * Hook for two-way bound props. Returns `[value, setValue]` where: * * - `value` is the already-resolved prop value (passed through from render props) * - `setValue` writes back to the bound state path (no-op if not bound) * * Designed to work with the `bindings` map that the renderer provides when * a prop uses `{ $bindState: "/path" }` or `{ $bindItem: "field" }`. * * @example * ```tsx * import { useBoundProp } from "@json-render/react"; * * const Input: ComponentRenderer = ({ props, bindings }) => { * const [value, setValue] = useBoundProp(props.value, bindings?.value); * return setValue(e.target.value)} />; * }; * ``` */ declare function useBoundProp(propValue: T | undefined, bindingPath: string | undefined): [T | undefined, (value: T) => void]; /** * A single part from the AI SDK's `message.parts` array. This is a minimal * structural type so that library helpers do not depend on the AI SDK. * Fields are optional because different part types carry different data: * - Text parts have `text` * - Data parts have `data` */ interface DataPart { type: string; text?: string; data?: unknown; } declare function buildSpecFromParts(parts: DataPart[]): Spec | null; /** * Extract and join all text content from a message's parts array. * * Filters for parts with `type === "text"`, trims each one, and joins them * with double newlines so that text from separate agent steps renders as * distinct paragraphs in markdown. * * Has no AI SDK dependency — operates on a generic `DataPart[]`. * * @example * ```tsx * const text = getTextFromParts(message.parts); * if (text) { * return {text}; * } * ``` */ declare function getTextFromParts(parts: DataPart[]): string; /** * Hook that extracts both the json-render spec and text content from a * message's parts array. Combines `buildSpecFromParts` and `getTextFromParts` * into a single call with memoized results. * * **Memoization behavior:** Results are recomputed only when the `parts` array * reference changes **and** either the length differs or the last element is a * different object. This is optimized for the typical AI SDK streaming pattern * where parts are appended incrementally. Mid-array edits (e.g. replacing an * earlier part without appending) may not trigger recomputation. If you need to * force a recompute after such edits, pass a new array reference with a * different last element. * * @example * ```tsx * import { useJsonRenderMessage } from "@json-render/react"; * * function MessageBubble({ message }) { * const { spec, text, hasSpec } = useJsonRenderMessage(message.parts); * * return ( *
* {text && {text}} * {hasSpec && } *
* ); * } * ``` */ declare function useJsonRenderMessage(parts: DataPart[]): { spec: Spec | null; text: string; hasSpec: boolean; }; /** * A single message in the chat, which may contain text, a rendered UI spec, or both. */ interface ChatMessage { /** Unique message ID */ id: string; /** Who sent this message */ role: "user" | "assistant"; /** Text content (conversational prose) */ text: string; /** json-render Spec built from JSONL patches (null if no UI was generated) */ spec: Spec | null; } /** * Options for useChatUI */ interface UseChatUIOptions { /** API endpoint that accepts `{ messages: Array<{ role, content }> }` and returns a text stream */ api: string; /** Callback when streaming completes for a message */ onComplete?: (message: ChatMessage) => void; /** Callback on error */ onError?: (error: Error) => void; } /** * Return type for useChatUI */ interface UseChatUIReturn { /** All messages in the conversation */ messages: ChatMessage[]; /** Whether currently streaming an assistant response */ isStreaming: boolean; /** Error from the last request, if any */ error: Error | null; /** Send a user message */ send: (text: string) => Promise; /** Clear all messages and reset the conversation */ clear: () => void; } /** * Hook for chat + GenUI experiences. * * Manages a multi-turn conversation where each assistant message can contain * both conversational text and a json-render UI spec. The hook sends the full * message history to the API endpoint, reads the streamed response, and * separates text lines from JSONL patch lines using `createMixedStreamParser`. * * @example * ```tsx * const { messages, isStreaming, send, clear } = useChatUI({ * api: "/api/chat", * }); * * // Send a message * await send("Compare weather in NYC and Tokyo"); * * // Render messages * {messages.map((msg) => ( *
* {msg.text &&

{msg.text}

} * {msg.spec && } *
* ))} * ``` */ declare function useChatUI({ api, onComplete, onError, }: UseChatUIOptions): UseChatUIReturn; export { type ActionContextValue, type ActionFn, ActionProvider, type ActionProviderProps, type Actions, type BaseComponentProps, 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 EventHandle, 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, useOptionalValidation, useRepeatScope, useStateBinding, useStateStore, useStateValue, useUIStream, useValidation, useVisibility };