Compare commits

...
Author SHA1 Message Date
Chris Tate 1fcc670a21 v0.7.0 docs 2026-02-17 01:46:19 -06:00
7 changed files with 154 additions and 12 deletions
+3 -3
View File
@@ -22,7 +22,7 @@ json-render is a **Generative UI** framework: AI generates interfaces from natur
- **Predictable** - JSON output matches your schema, every time
- **Fast** - Stream and render progressively as the model responds
- **Cross-Platform** - React (web) and React Native (mobile) from the same catalog
- **Batteries Included** - 30+ pre-built shadcn/ui components ready to use
- **Batteries Included** - 36 pre-built shadcn/ui components ready to use
## Quick Start
@@ -108,7 +108,7 @@ function Dashboard({ spec }) {
|---------|-------------|
| `@json-render/core` | Schemas, catalogs, AI prompts, dynamic props, SpecStream utilities |
| `@json-render/react` | React renderer, contexts, hooks |
| `@json-render/shadcn` | 30+ pre-built shadcn/ui components (Radix UI + Tailwind CSS) |
| `@json-render/shadcn` | 36 pre-built shadcn/ui components (Radix UI + Tailwind CSS) |
| `@json-render/react-native` | React Native renderer with standard mobile components |
| `@json-render/remotion` | Remotion video renderer, timeline schema |
@@ -150,7 +150,7 @@ import { schema, defineRegistry, Renderer } from "@json-render/react";
import { shadcnComponentDefinitions } from "@json-render/shadcn/catalog";
import { shadcnComponents } from "@json-render/shadcn";
// Pick components from the 30+ standard definitions
// Pick components from the 36 standard definitions
const catalog = defineCatalog(schema, {
components: {
Card: shadcnComponentDefinitions.Card,
+26
View File
@@ -157,6 +157,14 @@ const spec = compileSpecStream<MySpec>(jsonlString);
| `defineSchema(builder, options?)` | Create a schema with spec/catalog structure |
| `SchemaBuilder` | Builder with `s.object()`, `s.array()`, `s.map()`, etc. |
Schema options:
| Option | Purpose |
|--------|---------|
| `promptTemplate` | Custom AI prompt generator |
| `defaultRules` | Default rules injected before custom rules in prompts |
| `builtInActions` | Actions always available at runtime, auto-injected into prompts (e.g. `setState`) |
### Catalog
| Export | Purpose |
@@ -196,12 +204,30 @@ const spec = compileSpecStream<MySpec>(jsonlString);
| `autoFixSpec(spec)` | Auto-fix common spec issues (returns corrected copy) |
| `formatSpecIssues(issues)` | Format validation issues as readable strings |
### Actions
| Export | Purpose |
|--------|---------|
| `ActionBinding` | Action binding with `action`, `params`, `confirm`, `preventDefault`, etc. |
| `BuiltInAction` | Built-in action definition with `name` and `description` |
### Chat Mode (Mixed Streams)
| Export | Purpose |
|--------|---------|
| `createJsonRenderTransform()` | TransformStream that separates text from JSONL patches in a mixed stream |
| `pipeJsonRender()` | Server-side helper to pipe a mixed stream through the transform |
| `SPEC_DATA_PART` / `SPEC_DATA_PART_TYPE` | Constants for filtering spec data parts |
The transform splits text blocks around spec data by emitting `text-end`/`text-start` pairs, ensuring the AI SDK creates separate text parts and preserving correct interleaving of prose and UI in `message.parts`.
### Types
| Export | Purpose |
|--------|---------|
| `Spec` | Base spec type |
| `Catalog` | Catalog type |
| `BuiltInAction` | Built-in action type (`name` + `description`) |
| `VisibilityCondition` | Visibility condition type (used by `$cond`) |
| `VisibilityContext` | Context for evaluating visibility and prop expressions |
| `SpecStreamLine` | Single patch operation |
+67 -2
View File
@@ -51,6 +51,8 @@ export const catalog = defineCatalog(schema, {
### 2. Define Component Implementations
`defineRegistry` conditionally requires the `actions` field only when the catalog declares actions. Catalogs with `actions: {}` can omit it entirely.
```tsx
import { defineRegistry, useBoundProp } from "@json-render/react";
import { catalog } from "./catalog";
@@ -297,7 +299,7 @@ See [@json-render/core](../core/README.md) for full expression syntax.
## Built-in Actions
The `setState`, `pushState`, and `removeState` actions are handled automatically by `ActionProvider`. They update the state model, which triggers re-evaluation of visibility conditions and dynamic prop expressions:
The `setState`, `pushState`, and `removeState` actions are built into the React schema and handled automatically by `ActionProvider`. They are injected into AI prompts without needing to be declared in your catalog's `actions`. They update the state model, which triggers re-evaluation of visibility conditions and dynamic prop expressions:
```json
{
@@ -321,14 +323,52 @@ When using `defineRegistry`, components receive these props:
interface ComponentContext<P> {
props: P; // Typed props from the catalog (expressions resolved)
children?: React.ReactNode; // Rendered children
emit?: (event: string) => void; // Emit a named event
emit: (event: string) => void; // Emit a named event (always defined)
on: (event: string) => EventHandle; // Get event handle with metadata
loading?: boolean; // Whether the parent is loading
bindings?: Record<string, string>; // State paths for $bindState/$bindItem expressions (e.g. bindings.value)
}
interface EventHandle {
emit: () => void; // Fire the event
shouldPreventDefault: boolean; // Whether any binding requested preventDefault
bound: boolean; // Whether any handler is bound
}
```
Use `emit("press")` for simple event firing. Use `on("click")` when you need to check metadata like `shouldPreventDefault` or `bound`:
```tsx
Link: ({ props, on }) => {
const click = on("click");
return (
<a
href={props.href}
onClick={(e) => {
if (click.shouldPreventDefault) e.preventDefault();
click.emit();
}}
>
{props.label}
</a>
);
},
```
Use `bindings?.value`, `bindings?.checked`, etc. with `useBoundProp()` for two-way bound form components.
### `BaseComponentProps`
For building reusable component libraries that are not tied to a specific catalog (e.g. `@json-render/shadcn`), use the catalog-agnostic `BaseComponentProps` type:
```typescript
import type { BaseComponentProps } from "@json-render/react";
const Card = ({ props, children }: BaseComponentProps<{ title?: string }>) => (
<div>{props.title}{children}</div>
);
```
## Generate AI Prompts
```typescript
@@ -374,3 +414,28 @@ function App() {
return <Renderer spec={spec} registry={registry} />;
}
```
## Key Exports
| Export | Purpose |
|--------|---------|
| `defineRegistry` | Create a type-safe component registry from a catalog |
| `Renderer` | Render a spec using a registry |
| `schema` | Element tree schema (includes built-in actions: `setState`, `pushState`, `removeState`) |
| `useStateStore` | Access state context |
| `useStateValue` | Get single value from state |
| `useBoundProp` | Two-way binding for `$bindState`/`$bindItem` expressions |
| `useActions` | Access actions context |
| `useAction` | Get a single action dispatch function |
| `useUIStream` | Stream specs from an API endpoint |
### Types
| Export | Purpose |
|--------|---------|
| `ComponentContext` | Typed component render function context (catalog-aware) |
| `BaseComponentProps` | Catalog-agnostic base type for reusable component libraries |
| `EventHandle` | Event handle with `emit()`, `shouldPreventDefault`, `bound` |
| `ComponentFn` | Component render function type |
| `SetState` | State setter type |
| `StateModel` | State model type |
+1 -1
View File
@@ -1,6 +1,6 @@
# @json-render/shadcn
Pre-built [shadcn/ui](https://ui.shadcn.com/) components for json-render. Drop-in catalog definitions and React implementations for 30+ components built on Radix UI + Tailwind CSS.
Pre-built [shadcn/ui](https://ui.shadcn.com/) components for json-render. Drop-in catalog definitions and React implementations for 36 components built on Radix UI + Tailwind CSS.
## Installation
+17
View File
@@ -157,6 +157,20 @@ visibility.always // true
visibility.never // false
```
## Built-in Actions in Schema
Schemas can declare `builtInActions` -- actions that are always available at runtime and auto-injected into prompts:
```typescript
const schema = defineSchema(builder, {
builtInActions: [
{ name: "setState", description: "Update a value in the state model" },
],
});
```
These appear in prompts as `[built-in]` and don't require handlers in `defineRegistry`.
## Key Exports
| Export | Purpose |
@@ -169,5 +183,8 @@ visibility.never // false
| `validateSpec` | Validate spec structure |
| `autoFixSpec` | Auto-fix common spec issues |
| `createSpecStreamCompiler` | Stream JSONL patches into spec |
| `createJsonRenderTransform` | TransformStream separating text from JSONL in mixed streams |
| `parseSpecStreamLine` | Parse single JSONL line |
| `applySpecStreamPatch` | Apply patch to object |
| `BuiltInAction` | Type for built-in action definitions (`name` + `description`) |
| `ActionBinding` | Action binding type (includes `preventDefault` field) |
+39 -5
View File
@@ -118,13 +118,24 @@ Components receive already-resolved props. For two-way bound props, use the `use
## Event System
Components use `emit` to fire named events. The element's `on` field maps events to action bindings:
Components use `emit` to fire named events, or `on()` to get an event handle with metadata. The element's `on` field maps events to action bindings:
```tsx
// Component emits a named event
// Simple event firing
Button: ({ props, emit }) => (
<button onClick={() => emit("press")}>{props.label}</button>
),
// Event handle with metadata (e.g. preventDefault)
Link: ({ props, on }) => {
const click = on("click");
return (
<a href={props.href} onClick={(e) => {
if (click.shouldPreventDefault) e.preventDefault();
click.emit();
}}>{props.label}</a>
);
},
```
```json
@@ -135,12 +146,16 @@ Button: ({ props, emit }) => (
}
```
The `EventHandle` returned by `on()` has: `emit()`, `shouldPreventDefault` (boolean), and `bound` (boolean).
## Built-in Actions
The `setState` action is handled automatically by `ActionProvider` and updates the state model directly, which re-evaluates visibility conditions and dynamic prop expressions:
The `setState`, `pushState`, and `removeState` actions are built into the React schema and handled automatically by `ActionProvider`. They are injected into AI prompts without needing to be declared in catalog `actions`:
```json
{ "action": "setState", "actionParams": { "statePath": "/activeTab", "value": "home" } }
{ "action": "setState", "params": { "statePath": "/activeTab", "value": "home" } }
{ "action": "pushState", "params": { "statePath": "/items", "value": { "text": "New" } } }
{ "action": "removeState", "params": { "statePath": "/items", "index": 0 } }
```
Note: `statePath` in action params (e.g. `setState.statePath`) targets the mutation path. Two-way binding in component props uses `{ "$bindState": "/path" }` on the value prop, not `statePath`.
@@ -168,16 +183,35 @@ Input: ({ element, bindings }) => {
`useBoundProp(propValue, bindingPath)` returns `[value, setValue]`. The `value` is the resolved prop; `setValue` writes back to the bound state path (no-op if not bound).
## BaseComponentProps
For building reusable component libraries not tied to a specific catalog (e.g. `@json-render/shadcn`):
```typescript
import type { BaseComponentProps } from "@json-render/react";
const Card = ({ props, children }: BaseComponentProps<{ title?: string }>) => (
<div>{props.title}{children}</div>
);
```
## defineRegistry
`defineRegistry` conditionally requires the `actions` field only when the catalog declares actions. Catalogs with `actions: {}` can omit it.
## Key Exports
| Export | Purpose |
|--------|---------|
| `defineRegistry` | Create a type-safe component registry from a catalog |
| `Renderer` | Render a spec using a registry |
| `schema` | Element tree schema |
| `schema` | Element tree schema (includes built-in state actions) |
| `useStateStore` | Access state context |
| `useStateValue` | Get single value from state |
| `useBoundProp` | Two-way binding for `$bindState`/`$bindItem` expressions |
| `useActions` | Access actions context |
| `useAction` | Get a single action dispatch function |
| `useUIStream` | Stream specs from an API endpoint |
| `BaseComponentProps` | Catalog-agnostic base type for reusable component libraries |
| `EventHandle` | Event handle type (`emit`, `shouldPreventDefault`, `bound`) |
| `ComponentContext` | Typed component context (catalog-aware) |
+1 -1
View File
@@ -5,7 +5,7 @@ description: Pre-built shadcn/ui components for json-render. Use when working wi
# @json-render/shadcn
Pre-built shadcn/ui component definitions and implementations for json-render. Provides 30+ components built on Radix UI + Tailwind CSS.
Pre-built shadcn/ui component definitions and implementations for json-render. Provides 36 components built on Radix UI + Tailwind CSS.
## Two Entry Points