| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- import { pageMetadata } from "@/lib/page-metadata";
- export const metadata = pageMetadata("docs/api/solid");
- # @json-render/solid
- SolidJS components, providers, and hooks for rendering json-render specs.
- ## Installation
- <PackageInstall packages="@json-render/core @json-render/solid" />
- Peer dependencies: `solid-js ^1.9.0` and `zod ^4.0.0`.
- <PackageInstall packages="solid-js zod" />
- ## Providers
- ### StateProvider
- ```tsx
- <StateProvider
- initialState={{}}
- onStateChange={(changes) => console.log(changes)}
- >
- {/* children */}
- </StateProvider>
- ```
- <table>
- <thead>
- <tr>
- <th>Prop</th>
- <th>Type</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>
- <code>store</code>
- </td>
- <td>
- <code>StateStore</code>
- </td>
- <td>
- External store (controlled mode). When provided,{" "}
- <code>initialState</code> and <code>onStateChange</code> are ignored.
- </td>
- </tr>
- <tr>
- <td>
- <code>initialState</code>
- </td>
- <td>
- <code>Record<string, unknown></code>
- </td>
- <td>Initial state model for uncontrolled mode.</td>
- </tr>
- <tr>
- <td>
- <code>onStateChange</code>
- </td>
- <td>
- <code>
- {"(changes: Array<{ path: string; value: unknown }>) => void"}
- </code>
- </td>
- <td>Called for uncontrolled state updates.</td>
- </tr>
- </tbody>
- </table>
- ### ActionProvider
- ```tsx
- <ActionProvider
- handlers={{ submit: async (params) => {} }}
- navigate={(path) => {}}
- >
- {/* children */}
- </ActionProvider>
- ```
- ### VisibilityProvider
- ```tsx
- <VisibilityProvider>{/* children */}</VisibilityProvider>
- ```
- ### ValidationProvider
- ```tsx
- <ValidationProvider customFunctions={{ custom: (value) => Boolean(value) }}>
- {/* children */}
- </ValidationProvider>
- ```
- ### JSONUIProvider
- Combined provider wrapper for state, visibility, validation, and actions.
- ```tsx
- <JSONUIProvider
- registry={registry}
- initialState={{}}
- handlers={handlers}
- validationFunctions={validationFunctions}
- >
- <Renderer spec={spec} registry={registry} />
- </JSONUIProvider>
- ```
- ## defineRegistry
- Create a typed component registry and action helpers from a catalog.
- ```tsx
- const { registry, handlers, executeAction } = defineRegistry(catalog, {
- components: {
- Card: (renderProps) => <div>{renderProps.children}</div>,
- Button: (renderProps) => (
- <button onClick={() => renderProps.emit("press")}>
- {renderProps.element.props.label as string}
- </button>
- ),
- },
- actions: {
- submit: async (params, setState, state) => {
- // custom action logic
- },
- },
- });
- ```
- ## Components
- ### Renderer
- ```tsx
- <Renderer spec={spec} registry={registry} loading={false} />
- ```
- Renders a `Spec` tree using your registry.
- ### createRenderer
- Build an app-level renderer from catalog + components:
- ```tsx
- const AppRenderer = createRenderer(catalog, {
- Card: (renderProps) => <div>{renderProps.children}</div>,
- });
- <AppRenderer spec={spec} state={{}} onAction={(name, params) => {}} />;
- ```
- ## Hooks
- - `useStateStore()`
- - `useStateValue(path)` - returns an accessor
- - `useStateBinding(path)` - returns `[Accessor<T | undefined>, setValue]`
- - `useVisibility()` / `useIsVisible(condition)`
- - `useActions()` / `useAction(binding)`
- - `useValidation()` / `useOptionalValidation()`
- - `useFieldValidation(path, config)` - returns accessor-backed `state`, `errors`, and `isValid`
- - `useBoundProp(value, bindingPath)`
- - `useUIStream(options)`
- - `useChatUI(options)`
- ## Built-in Actions
- `ActionProvider` handles these built-in actions:
- - `setState`
- - `pushState`
- - `removeState`
- - `validateForm`
- ## Component Props
- Registry components receive:
- ```ts
- interface ComponentRenderProps<P = Record<string, unknown>> {
- element: UIElement<string, P>;
- children?: JSX.Element;
- emit: (event: string) => void;
- on: (event: string) => EventHandle;
- bindings?: Record<string, string>;
- loading?: boolean;
- }
- ```
- Use `emit("event")` to dispatch event bindings. Use `on("event")` to access `EventHandle` metadata (`bound`, `shouldPreventDefault`, `emit`).
- ## Reactivity Notes
- - Keep changing reads in JSX expressions, `createMemo`, or `createEffect`.
- - Avoid props destructuring in component signatures when you need live updates.
- - `StateProvider` and other contexts expose getter-backed values so consumers read live signals.
- - `useStateValue`, `useStateBinding`, and `useFieldValidation` expose reactive accessors; call them as functions.
|