Compare commits

..
Author SHA1 Message Date
Chris Tate 25001ac0e2 fix tests 2026-02-09 01:29:38 -06:00
Chris Tate 2e72fdb599 fix lint 2026-02-09 01:26:37 -06:00
Chris Tate 11bfd1073d fix lint 2026-02-09 01:22:44 -06:00
Chris Tate ef3e2dbeb1 fix lint 2026-02-09 01:20:08 -06:00
Chris Tate 16b64e63f1 fix build 2026-02-09 01:18:37 -06:00
Chris Tate 3a487f0558 fixes 2026-02-09 01:13:59 -06:00
Chris Tate ffcb188f87 fixes 2026-02-09 00:18:22 -06:00
Chris Tate 52aaa303c9 fix ... 2026-02-09 00:11:11 -06:00
Chris Tate 6b7fdd966a fixes 2026-02-08 23:34:58 -06:00
Chris Tate 46b549e4a1 great 2026-02-08 23:33:45 -06:00
Chris Tate ec51ddfa1b fixes 2026-02-08 23:31:58 -06:00
Chris Tate 13a01aa4d9 use haiku 2026-02-08 23:26:31 -06:00
Chris Tate 83f33e3590 fixes 2026-02-08 23:25:15 -06:00
Chris Tate a17f8187e6 streamdown 2026-02-08 23:17:15 -06:00
Chris Tate 847b9828bf fixes 2026-02-08 23:15:25 -06:00
Chris Tate 34afc7de80 fix mdx 2026-02-08 23:05:04 -06:00
Chris Tate 1d86165fc9 mdx 2026-02-08 23:02:54 -06:00
Chris Tate 1d8f4764cc mobile playground 2026-02-08 22:46:14 -06:00
Chris Tate dadaa0070b fixes 2026-02-08 22:36:46 -06:00
Chris Tate 59dfdfcdcc fixes 2026-02-08 22:31:59 -06:00
Chris Tate 36242cd8ed fixes 2026-02-08 22:30:55 -06:00
Chris Tate 5a89d426be fixes 2026-02-08 22:27:51 -06:00
Chris Tate d8218351d2 nested 2026-02-08 22:23:47 -06:00
Chris Tate f2a36a0961 fixes 2026-02-08 22:17:40 -06:00
Chris Tate 08113f2848 404 2026-02-08 22:08:18 -06:00
Chris Tate 0d89afe4a5 mv 2026-02-08 22:07:16 -06:00
Chris Tate a60552a739 refactor 2026-02-08 22:06:16 -06:00
Chris Tate 46acfac24b fixes 2026-02-08 22:01:45 -06:00
Chris Tate 895eaedca9 fixes 2026-02-08 21:56:58 -06:00
Chris Tate c3c34d47cf more catalog 2026-02-08 21:55:14 -06:00
Chris Tate 75eaf1ee8e fixes 2026-02-08 21:43:40 -06:00
Chris Tate ecf2396288 catalog on homepage 2026-02-08 21:26:57 -06:00
Chris Tate 3986cf43c9 accordion 2026-02-08 21:24:51 -06:00
Chris Tate a4d7a156c9 sonner 2026-02-08 21:20:59 -06:00
Chris Tate 2afe371671 dialog 2026-02-08 21:18:33 -06:00
Chris Tate aa721103f3 fixes 2026-02-08 11:56:48 -06:00
Chris Tate bad0b5b3e8 fixes 2026-02-08 11:54:18 -06:00
Chris Tate 0cb9dd4094 fixes 2026-02-08 11:51:17 -06:00
Chris Tate f7c1eaa92e catalog 2026-02-08 11:46:20 -06:00
Chris Tate 11adca259b better stream 2026-02-08 11:33:05 -06:00
Chris Tate 342f78c9b1 fixes 2026-02-08 11:19:36 -06:00
Chris Tate f18153f22b fixes 2026-02-08 11:11:42 -06:00
Chris Tate b80f210b95 fixes 2026-02-08 10:50:08 -06:00
Chris Tate 7ed07725b7 fix docs 2026-02-08 10:48:43 -06:00
Chris Tate 056710ce1c repeat 2026-02-08 10:20:37 -06:00
Chris Tate c426040841 better actions 2026-02-08 10:02:30 -06:00
Chris Tate 23ac3cd9f7 combine catalog.ts 2026-02-08 09:39:38 -06:00
Chris Tate 185ebdc086 $id 2026-02-08 09:36:53 -06:00
Chris Tate d26564c176 fixes 2026-02-08 09:34:15 -06:00
Chris Tate aa62208e91 user prompt 2026-02-08 09:27:44 -06:00
Chris Tate f776f14e8c fixes 2026-02-08 09:15:38 -06:00
Chris Tate 58c59b7e35 fixes 2026-02-08 09:06:30 -06:00
Chris Tate 047df9e942 remove . tsbuildinfo 2026-02-08 08:57:59 -06:00
Chris Tate d17c729719 rename data -> state 2026-02-08 08:56:57 -06:00
Chris Tate e39ba6811d fixes 2026-02-08 08:37:16 -06:00
Chris Tate 85234407dc pop/push 2026-02-08 01:06:56 -06:00
Chris Tate 18ea9e701f fixes 2026-02-08 00:04:49 -06:00
Chris Tate 5f7545342d react native 2026-02-07 18:41:32 -06:00
24 changed files with 31 additions and 452 deletions
+6 -30
View File
@@ -6,8 +6,6 @@ Let end users generate dashboards, widgets, apps, and videos from prompts — sa
```bash
npm install @json-render/core @json-render/react
# or for mobile
npm install @json-render/core @json-render/react-native
# or for video
npm install @json-render/core @json-render/remotion
```
@@ -77,8 +75,8 @@ const { registry } = defineRegistry(catalog, {
<span>{format(props.value, props.format)}</span>
</div>
),
Button: ({ props, emit }) => (
<button onClick={() => emit?.("press")}>
Button: ({ props, onAction }) => (
<button onClick={() => onAction?.({ name: props.action })}>
{props.label}
</button>
),
@@ -131,27 +129,6 @@ const { registry } = defineRegistry(catalog, { components });
<Renderer spec={spec} registry={registry} />
```
### React Native (Mobile)
```tsx
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/react-native/schema";
import {
standardComponentDefinitions,
standardActionDefinitions,
} from "@json-render/react-native/catalog";
import { defineRegistry, Renderer } from "@json-render/react-native";
// 25+ standard components included
const catalog = defineCatalog(schema, {
components: { ...standardComponentDefinitions },
actions: standardActionDefinitions,
});
const { registry } = defineRegistry(catalog, { components: {} });
<Renderer spec={spec} registry={registry} />
```
### Remotion (Video)
```tsx
@@ -252,7 +229,7 @@ Components can trigger actions, including the built-in `setState` action:
}
```
The `setState` action updates the state model directly, which re-evaluates visibility conditions and dynamic prop expressions.
The `setState` action updates the data model directly, which re-evaluates visibility conditions and dynamic prop expressions.
---
@@ -265,10 +242,9 @@ pnpm install
pnpm dev
```
- http://localhost:3000 -- Docs & Playground
- http://localhost:3001 -- Example Dashboard
- http://localhost:3002 -- Remotion Video Example
- React Native example: run `npx expo start` in `examples/react-native`
- http://localhost:3000 — Docs & Playground
- http://localhost:3001 — Example Dashboard
- http://localhost:3002 — Remotion Video Example
## How It Works
@@ -1,167 +0,0 @@
export const metadata = { title: "@json-render/react-native API" }
# @json-render/react-native
React Native renderer with standard components, providers, and hooks.
## Standard Components
### Layout
| Component | Props | Description |
|-----------|-------|-------------|
| `Container` | `padding`, `background`, `borderRadius`, `borderColor`, `flex` | Basic wrapper with styling |
| `Row` | `gap`, `align`, `justify`, `flex`, `wrap` | Horizontal flex layout |
| `Column` | `gap`, `align`, `justify`, `flex` | Vertical flex layout |
| `ScrollContainer` | `direction` | Scrollable area (vertical or horizontal) |
| `SafeArea` | `edges` | Safe area insets for notch/home indicator |
| `Pressable` | `action`, `actionParams` | Touchable wrapper that triggers actions |
| `Spacer` | `size`, `flex` | Fixed or flexible spacing |
| `Divider` | `color`, `thickness` | Thin line separator |
### Content
| Component | Props | Description |
|-----------|-------|-------------|
| `Heading` | `text`, `level`, `align`, `color` | Heading text (levels 1-6) |
| `Paragraph` | `text`, `align`, `color` | Body text |
| `Label` | `text`, `color`, `bold` | Small label text |
| `Image` | `uri`, `width`, `height`, `resizeMode`, `borderRadius` | Image display |
| `Avatar` | `uri`, `size`, `fallback` | Circular avatar |
| `Badge` | `label`, `color`, `textColor` | Status badge |
| `Chip` | `label`, `selected`, `color` | Tag/chip |
### Input
| Component | Props | Description |
|-----------|-------|-------------|
| `Button` | `label`, `variant`, `size`, `disabled`, `action`, `actionParams` | Pressable button |
| `TextInput` | `placeholder`, `statePath`, `secure`, `keyboardType`, `multiline` | Text input field |
| `Switch` | `statePath`, `label` | Toggle switch |
| `Checkbox` | `statePath`, `label` | Checkbox with label |
| `Slider` | `statePath`, `min`, `max`, `step` | Range slider |
| `SearchBar` | `placeholder`, `statePath` | Search input |
### Feedback
| Component | Props | Description |
|-----------|-------|-------------|
| `Spinner` | `size`, `color` | Loading indicator |
| `ProgressBar` | `progress`, `color`, `trackColor` | Progress indicator |
### Composite
| Component | Props | Description |
|-----------|-------|-------------|
| `Card` | `title`, `subtitle`, `padding` | Card container |
| `ListItem` | `title`, `subtitle`, `leading`, `trailing`, `action`, `actionParams` | List row |
| `Modal` | `visible`, `title` | Bottom sheet modal |
## Providers
### StateProvider
```tsx
<StateProvider initialState={object}>
{children}
</StateProvider>
```
### ActionProvider
```tsx
<ActionProvider handlers={Record<string, ActionHandler>}>
{children}
</ActionProvider>
```
### VisibilityProvider
```tsx
<VisibilityProvider>
{children}
</VisibilityProvider>
```
### ValidationProvider
```tsx
<ValidationProvider>
{children}
</ValidationProvider>
```
## defineRegistry
Create a type-safe component registry. Standard components are built-in -- only register custom components.
```tsx
import { defineRegistry, type Components } from '@json-render/react-native';
const { registry } = defineRegistry(catalog, {
components: {
Icon: ({ props }) => <Ionicons name={props.name} size={props.size ?? 24} />,
} as Components<typeof catalog>,
});
```
## Hooks
### useUIStream
```typescript
const {
spec, // Spec | null - current UI state
isStreaming, // boolean - true while streaming
error, // Error | null
send, // (prompt: string) => Promise<void>
clear, // () => void - reset spec and error
} = useUIStream({
api: string,
onComplete?: (spec: Spec) => void,
onError?: (error: Error) => void,
});
```
### useStateStore
```typescript
const { state, get, set, update } = useStateStore();
```
### useStateValue
```typescript
const value = useStateValue(path: string);
```
### useStateBinding
```typescript
const [value, setValue] = useStateBinding(path: string);
```
### useActions
```typescript
const { execute } = useActions();
```
### useIsVisible
```typescript
const isVisible = useIsVisible(condition?: VisibilityCondition);
```
## Catalog Exports
```typescript
import { standardComponentDefinitions, standardActionDefinitions } from "@json-render/react-native/catalog";
import { schema } from "@json-render/react-native/schema";
```
| Export | Purpose |
|--------|---------|
| `standardComponentDefinitions` | Catalog definitions for all 25+ standard components |
| `standardActionDefinitions` | Catalog definitions for standard actions (setState, navigate) |
| `schema` | React Native element tree schema |
+4 -4
View File
@@ -49,7 +49,7 @@ type ValidatorFn = (value: unknown, args?: object) => boolean | Promise<boolean>
## defineRegistry
Create a type-safe component registry from a catalog. Components receive `props`, `children`, `emit`, and `loading` with catalog-inferred types.
Create a type-safe component registry from a catalog. Components receive `props`, `children`, `onAction`, and `loading` with catalog-inferred types.
```tsx
import { defineRegistry } from '@json-render/react';
@@ -57,8 +57,8 @@ import { defineRegistry } from '@json-render/react';
const { registry } = defineRegistry(catalog, {
components: {
Card: ({ props, children }) => <div>{props.title}{children}</div>,
Button: ({ props, emit }) => (
<button onClick={() => emit?.("press")}>
Button: ({ props, onAction }) => (
<button onClick={() => onAction?.({ name: props.action })}>
{props.label}
</button>
),
@@ -90,7 +90,7 @@ type Registry = Record<string, React.ComponentType<ComponentRenderProps>>;
interface ComponentContext<P> {
props: P; // Typed props from catalog
children?: React.ReactNode; // Rendered children (for slot components)
emit?: (event: string) => void; // Emit a named event
onAction?: (action: { name: string; params?: object }) => void;
loading?: boolean;
}
```
-119
View File
@@ -4,125 +4,6 @@ export const metadata = { title: "Changelog" }
Notable changes and updates to json-render.
## v0.5.0
February 2026
### New: @json-render/react-native
Full React Native renderer with 25+ standard components, data binding, visibility, actions, and dynamic props. Build AI-generated native mobile UIs with the same catalog-driven approach as web.
```tsx
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/react-native/schema";
import {
standardComponentDefinitions,
standardActionDefinitions,
} from "@json-render/react-native/catalog";
import { defineRegistry, Renderer } from "@json-render/react-native";
const catalog = defineCatalog(schema, {
components: { ...standardComponentDefinitions },
actions: standardActionDefinitions,
});
const { registry } = defineRegistry(catalog, { components: {} });
<Renderer spec={spec} registry={registry} />
```
Includes standard components for layout (Container, Row, Column, ScrollContainer, SafeArea, Pressable, Spacer, Divider), content (Heading, Paragraph, Label, Image, Avatar, Badge, Chip), input (Button, TextInput, Switch, Checkbox, Slider, SearchBar), feedback (Spinner, ProgressBar), and composite (Card, ListItem, Modal).
### New: Event System
Components now use `emit` to fire named events instead of directly dispatching actions. The element's `on` field maps events to action bindings, decoupling component logic from action handling.
```tsx
// Component emits a named event
Button: ({ props, emit }) => (
<button onClick={() => emit?.("press")}>{props.label}</button>
),
// Element spec maps events to actions
{
"type": "Button",
"props": { "label": "Submit" },
"on": { "press": { "action": "submit", "params": { "formId": "main" } } }
}
```
### New: Repeat/List Rendering
Elements can now iterate over state arrays using the `repeat` field. Child elements use `$item` and `$index` tokens in `$path` expressions to reference the current item.
```json
{
"type": "Column",
"repeat": { "path": "/posts", "key": "id" },
"children": ["post-card"]
}
```
```json
{
"type": "Card",
"props": { "title": { "$path": "$item/title" } }
}
```
### New: User Prompt Builder
Build structured user prompts with optional spec refinement and state context:
```typescript
import { buildUserPrompt } from "@json-render/core";
// Fresh generation
buildUserPrompt({ prompt: "create a todo app" });
// Refinement (patch-only mode)
buildUserPrompt({ prompt: "add a toggle", currentSpec: spec });
// With runtime state
buildUserPrompt({ prompt: "show data", state: { todos: [] } });
```
### New: Spec Validation
Validate spec structure and auto-fix common issues:
```typescript
import { validateSpec, autoFixSpec } from "@json-render/core";
const { valid, issues } = validateSpec(spec, catalog);
const fixed = autoFixSpec(spec);
```
### Improved: State Management
`DataProvider` has been renamed to `StateProvider` with a clearer API. State is now a first-class part of specs -- elements can bind to state via `$path` expressions, and the built-in `setState` action updates state directly.
### Improved: AI Prompts
Schema prompts now include streaming best practices, repeat/list examples, and state patching guidance. Schemas can also define `defaultRules` that are always included in generated prompts.
### Improved: Documentation
- All documentation pages migrated to MDX
- AI-powered documentation chat
- Dynamic Open Graph images for all docs pages
- Improved playground
### Breaking Changes
- `DataProvider` renamed to `StateProvider`
- `useData` renamed to `useStateStore`, `useDataValue` to `useStateValue`, `useDataBinding` to `useStateBinding`
- `onAction` renamed to `emit` in component context
- `DataModel` type renamed to `StateModel`
- `Action` type renamed to `ActionBinding` (old name still available but deprecated)
---
## v0.4.0
February 2026
@@ -8,10 +8,6 @@ Install the core package plus your renderer of choice.
<PackageInstall packages="@json-render/core @json-render/react" />
## For React Native
<PackageInstall packages="@json-render/core @json-render/react-native" />
## For Remotion Video
<PackageInstall packages="@json-render/core @json-render/remotion remotion @remotion/player" />
@@ -53,7 +53,7 @@ export const catalog = defineCatalog(schema, {
## 2. Define your components
Use `defineRegistry` to map catalog types to React components. Each component receives type-safe `props`, `children`, and `emit`:
Use `defineRegistry` to map catalog types to React components. Each component receives type-safe `props`, `children`, and `onAction`:
```tsx
// lib/registry.tsx
@@ -71,10 +71,10 @@ export const { registry } = defineRegistry(catalog, {
{children}
</div>
),
Button: ({ props, emit }) => (
Button: ({ props, onAction }) => (
<button
className="px-4 py-2 bg-blue-500 text-white rounded"
onClick={() => emit?.("press")}
onClick={() => onAction?.({ name: props.action })}
>
{props.label}
</button>
-6
View File
@@ -39,11 +39,6 @@ export const docsNavigation: NavSection[] = [
href: "https://github.com/vercel-labs/json-render/tree/main/examples/dashboard",
external: true,
},
{
title: "React Native",
href: "https://github.com/vercel-labs/json-render/tree/main/examples/react-native",
external: true,
},
{
title: "Remotion",
href: "https://github.com/vercel-labs/json-render/tree/main/examples/remotion",
@@ -74,7 +69,6 @@ export const docsNavigation: NavSection[] = [
items: [
{ title: "@json-render/core", href: "/docs/api/core" },
{ title: "@json-render/react", href: "/docs/api/react" },
{ title: "@json-render/react-native", href: "/docs/api/react-native" },
{ title: "@json-render/remotion", href: "/docs/api/remotion" },
{ title: "@json-render/codegen", href: "/docs/api/codegen" },
],
-1
View File
@@ -36,7 +36,6 @@ export const PAGE_TITLES: Record<string, string> = {
// API references
"docs/api/core": "@json-render/core API",
"docs/api/react": "@json-render/react API",
"docs/api/react-native": "@json-render/react-native API",
"docs/api/codegen": "@json-render/codegen API",
"docs/api/remotion": "@json-render/remotion API",
};
-19
View File
@@ -1,24 +1,5 @@
# @json-render/codegen
## 0.5.0
### Minor Changes
- 3d2d1ad: Add @json-render/react-native package, event system (emit replaces onAction), repeat/list rendering, user prompt builder, spec validation, and rename DataProvider to StateProvider.
### Patch Changes
- Updated dependencies [3d2d1ad]
- @json-render/core@0.5.0
## 0.4.4
### Patch Changes
- dd17549: remove key/parentKey from flat specs, RFC 6902 compliance for SpecStream
- Updated dependencies [dd17549]
- @json-render/core@0.4.4
## 0.4.3
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/codegen",
"version": "0.5.0",
"version": "0.4.3",
"license": "Apache-2.0",
"description": "Utilities for generating code from json-render UI trees",
"keywords": [
-12
View File
@@ -1,17 +1,5 @@
# @json-render/core
## 0.5.0
### Minor Changes
- 3d2d1ad: Add @json-render/react-native package, event system (emit replaces onAction), repeat/list rendering, user prompt builder, spec validation, and rename DataProvider to StateProvider.
## 0.4.4
### Patch Changes
- dd17549: remove key/parentKey from flat specs, RFC 6902 compliance for SpecStream
## 0.4.3
### Patch Changes
+1 -1
View File
@@ -213,7 +213,7 @@ Any prop value can be a dynamic expression that resolves based on data state at
### Data Binding (`$path`)
Read a value directly from the state model:
Read a value directly from the data model:
```json
{
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/core",
"version": "0.5.0",
"version": "0.4.3",
"license": "Apache-2.0",
"description": "JSON becomes real things. Define your catalog, register your components, let AI generate.",
"keywords": [
-12
View File
@@ -1,12 +0,0 @@
# @json-render/react-native
## 0.5.0
### Minor Changes
- 3d2d1ad: Add @json-render/react-native package, event system (emit replaces onAction), repeat/list rendering, user prompt builder, spec validation, and rename DataProvider to StateProvider.
### Patch Changes
- Updated dependencies [3d2d1ad]
- @json-render/core@0.5.0
+1 -1
View File
@@ -158,7 +158,7 @@ The `Pressable` component wraps children and triggers an action on press. It's e
## Built-in Actions
The `setState` action is handled automatically by `ActionProvider`. It updates the state model, which triggers re-evaluation of visibility conditions and dynamic prop expressions:
The `setState` action is handled automatically by `ActionProvider`. It updates the data model, which triggers re-evaluation of visibility conditions and dynamic prop expressions:
```json
{
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/react-native",
"version": "0.5.0",
"version": "0.4.3",
"license": "Apache-2.0",
"description": "React Native renderer for @json-render/core. JSON becomes React Native components.",
"keywords": [
-19
View File
@@ -1,24 +1,5 @@
# @json-render/react
## 0.5.0
### Minor Changes
- 3d2d1ad: Add @json-render/react-native package, event system (emit replaces onAction), repeat/list rendering, user prompt builder, spec validation, and rename DataProvider to StateProvider.
### Patch Changes
- Updated dependencies [3d2d1ad]
- @json-render/core@0.5.0
## 0.4.4
### Patch Changes
- dd17549: remove key/parentKey from flat specs, RFC 6902 compliance for SpecStream
- Updated dependencies [dd17549]
- @json-render/core@0.4.4
## 0.4.3
### Patch Changes
+4 -4
View File
@@ -63,8 +63,8 @@ export const { registry } = defineRegistry(catalog, {
{children}
</div>
),
Button: ({ props, emit }) => (
<button onClick={() => emit?.("press")}>
Button: ({ props, onAction }) => (
<button onClick={() => onAction?.({ name: props.action })}>
{props.label}
</button>
),
@@ -274,7 +274,7 @@ See [@json-render/core](../core/README.md) for full expression syntax.
## Built-in Actions
The `setState` action is handled automatically by `ActionProvider`. It updates the state model, which triggers re-evaluation of visibility conditions and dynamic prop expressions:
The `setState` action is handled automatically by `ActionProvider`. It updates the data model, which triggers re-evaluation of visibility conditions and dynamic prop expressions:
```json
{
@@ -295,7 +295,7 @@ When using `defineRegistry`, components receive these props:
interface ComponentContext<P> {
props: P; // Typed props from the catalog
children?: React.ReactNode; // Rendered children
emit?: (event: string) => void; // Emit a named event
onAction?: (action: { name: string; params?: Record<string, unknown> }) => void;
loading?: boolean; // Whether the parent is loading
}
```
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/react",
"version": "0.5.0",
"version": "0.4.3",
"license": "Apache-2.0",
"description": "React renderer for @json-render/core. JSON becomes React components.",
"keywords": [
-19
View File
@@ -1,24 +1,5 @@
# @json-render/remotion
## 0.5.0
### Minor Changes
- 3d2d1ad: Add @json-render/react-native package, event system (emit replaces onAction), repeat/list rendering, user prompt builder, spec validation, and rename DataProvider to StateProvider.
### Patch Changes
- Updated dependencies [3d2d1ad]
- @json-render/core@0.5.0
## 0.4.4
### Patch Changes
- dd17549: remove key/parentKey from flat specs, RFC 6902 compliance for SpecStream
- Updated dependencies [dd17549]
- @json-render/core@0.4.4
## 0.4.3
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/remotion",
"version": "0.5.0",
"version": "0.4.3",
"license": "Apache-2.0",
"description": "Remotion renderer for @json-render/core. JSON becomes video compositions.",
"keywords": [
+1 -1
View File
@@ -81,7 +81,7 @@ const finalSpec = compiler.getResult();
Any prop value can be a dynamic expression resolved at render time:
- **`{ "$path": "/state/key" }`** -- reads a value from the state model
- **`{ "$path": "/state/key" }`** -- reads a value from the data model
- **`{ "$cond": <condition>, "$then": <value>, "$else": <value> }`** -- evaluates a visibility condition and picks a branch
`$cond` uses the same syntax as visibility conditions (`eq`, `neq`, `path`, `and`, `or`, `not`). `$then` and `$else` can themselves be expressions (recursive).
+1 -1
View File
@@ -127,7 +127,7 @@ Components receive already-resolved props -- no changes needed to component impl
## 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` action is handled automatically by `ActionProvider` and updates the data model directly, which re-evaluates visibility conditions and dynamic prop expressions:
```json
{ "action": "setState", "actionParams": { "path": "/activeTab", "value": "home" } }
+5 -24
View File
@@ -85,7 +85,7 @@ The React schema uses an element tree format:
| Provider | Purpose |
|----------|---------|
| `StateProvider` | Share state across components (JSON Pointer paths) |
| `ActionProvider` | Handle actions dispatched via the event system |
| `ActionProvider` | Handle actions dispatched from components |
| `VisibilityProvider` | Enable conditional rendering based on state |
| `ValidationProvider` | Form field validation |
@@ -108,28 +108,9 @@ Any prop value can be a data-driven expression resolved by the renderer before c
Components receive already-resolved props -- no changes needed to component implementations.
## Event System
Components use `emit` to fire named events. The element's `on` field maps events to action bindings:
```tsx
// Component emits a named event
Button: ({ props, emit }) => (
<button onClick={() => emit?.("press")}>{props.label}</button>
),
```
```json
{
"type": "Button",
"props": { "label": "Submit" },
"on": { "press": { "action": "submit" } }
}
```
## 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` action is handled automatically by `ActionProvider` and updates the data model directly, which re-evaluates visibility conditions and dynamic prop expressions:
```json
{ "action": "setState", "actionParams": { "path": "/activeTab", "value": "home" } }
@@ -142,9 +123,9 @@ The `setState` action is handled automatically by `ActionProvider` and updates t
| `defineRegistry` | Create a type-safe component registry from a catalog |
| `Renderer` | Render a spec using a registry |
| `schema` | Element tree schema |
| `useStateStore` | Access state context |
| `useStateValue` | Get single value from state |
| `useStateBinding` | Two-way state binding |
| `useStateStore` | Access data context |
| `useStateValue` | Get single value from data |
| `useStateBinding` | Two-way data binding |
| `useActions` | Access actions context |
| `useAction` | Get a single action dispatch function |
| `useUIStream` | Stream specs from an API endpoint |