Compare commits

..
Author SHA1 Message Date
Chris Tate b0f85bc3e0 fix lint 2026-03-06 19:36:35 -06:00
Chris Tate cd1df67539 Merge remote-tracking branch 'origin/main' into ctate/mcp
# Conflicts:
#	pnpm-lock.yaml
2026-03-06 19:17:21 -06:00
Chris Tate 42436376dd mcp 2026-03-06 19:15:28 -06:00
83 changed files with 36 additions and 1591 deletions
+1 -2
View File
@@ -18,8 +18,7 @@
"@json-render/vue",
"@json-render/xstate",
"@json-render/image",
"@json-render/mcp",
"@json-render/svelte"
"@json-render/mcp"
]
],
"linked": [],
+1 -22
View File
@@ -19,8 +19,6 @@ npm install @json-render/core @json-render/react-pdf
npm install @json-render/core @json-render/react-email @react-email/components @react-email/render
# or for Vue
npm install @json-render/core @json-render/vue
# or for Svelte
npm install @json-render/core @json-render/svelte
```
## Why json-render?
@@ -30,7 +28,7 @@ json-render is a **Generative UI** framework: AI generates interfaces from natur
- **Guardrailed** - AI can only use components in your catalog
- **Predictable** - JSON output matches your schema, every time
- **Fast** - Stream and render progressively as the model responds
- **Cross-Platform** - React, Vue, Svelte (web), React Native (mobile) from the same catalog
- **Cross-Platform** - React, Vue (web), React Native (mobile) from the same catalog
- **Batteries Included** - 36 pre-built shadcn/ui components ready to use
## Quick Start
@@ -118,14 +116,12 @@ function Dashboard({ spec }) {
| `@json-render/core` | Schemas, catalogs, AI prompts, dynamic props, SpecStream utilities |
| `@json-render/react` | React renderer, contexts, hooks |
| `@json-render/vue` | Vue 3 renderer, composables, providers |
| `@json-render/svelte` | Svelte 5 renderer with runes-based reactivity |
| `@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 |
| `@json-render/react-pdf` | React PDF renderer for generating PDF documents from specs |
| `@json-render/react-email` | React Email renderer for HTML/plain-text emails from specs |
| `@json-render/image` | Image renderer for SVG/PNG output (OG images, social cards) via Satori |
| `@json-render/codegen` | Utilities for generating code from json-render UI trees |
| `@json-render/redux` | Redux / Redux Toolkit adapter for `StateStore` |
| `@json-render/zustand` | Zustand adapter for `StateStore` |
| `@json-render/jotai` | Jotai adapter for `StateStore` |
@@ -182,23 +178,6 @@ const { registry } = defineRegistry(catalog, {
// <Renderer :spec="spec" :registry="registry" />
```
### Svelte (UI)
```typescript
import { defineRegistry, Renderer } from "@json-render/svelte";
import { schema } from "@json-render/svelte/schema";
const { registry } = defineRegistry(catalog, {
components: {
Card: ({ props, children }) => /* Svelte 5 snippet */,
Button: ({ props, emit }) => /* Svelte 5 snippet */,
},
});
// In your Svelte component:
// <Renderer spec={spec} registry={registry} />
```
### shadcn/ui (Web)
```tsx
-9
View File
@@ -1,14 +1,5 @@
# web
## 0.1.5
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/codegen@0.12.0
- @json-render/react@0.12.0
## 0.1.4
### Patch Changes
-104
View File
@@ -1,104 +0,0 @@
import { pageMetadata } from "@/lib/page-metadata"
export const metadata = pageMetadata("docs/api/jotai")
# @json-render/jotai
Jotai adapter for json-render's `StateStore` interface.
## Installation
```bash
npm install @json-render/jotai @json-render/core @json-render/react jotai
```
## jotaiStateStore
Create a `StateStore` backed by a Jotai atom.
```typescript
import { jotaiStateStore } from "@json-render/jotai";
```
### Options
<table>
<thead>
<tr>
<th>Option</th>
<th>Type</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>atom</code></td>
<td><code>{'WritableAtom<StateModel, [StateModel], void>'}</code></td>
<td>Yes</td>
<td>A writable atom holding the state model.</td>
</tr>
<tr>
<td><code>store</code></td>
<td>Jotai <code>Store</code></td>
<td>No</td>
<td>The Jotai store instance. Defaults to a new store created internally. Pass your own to share state with <code>{'<Provider>'}</code>.</td>
</tr>
</tbody>
</table>
### Example
```typescript
import { atom } from "jotai";
import { jotaiStateStore } from "@json-render/jotai";
import { StateProvider } from "@json-render/react";
const uiAtom = atom<Record<string, unknown>>({ count: 0 });
const store = jotaiStateStore({ atom: uiAtom });
```
```tsx
<StateProvider store={store}>
{/* json-render reads/writes go through Jotai */}
</StateProvider>
```
### Shared Jotai Store
If your app already uses a Jotai `<Provider>` with a custom store, pass it so both json-render and your components share the same state:
```typescript
import { atom, createStore } from "jotai";
import { Provider as JotaiProvider } from "jotai/react";
import { jotaiStateStore } from "@json-render/jotai";
import { StateProvider } from "@json-render/react";
const jStore = createStore();
const uiAtom = atom<Record<string, unknown>>({ count: 0 });
const store = jotaiStateStore({ atom: uiAtom, store: jStore });
```
```tsx
<JotaiProvider store={jStore}>
<StateProvider store={store}>
{/* Both json-render and useAtom() see the same state */}
</StateProvider>
</JotaiProvider>
```
## Re-exports
<table>
<thead>
<tr>
<th>Export</th>
<th>Source</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>StateStore</code></td>
<td><code>@json-render/core</code></td>
</tr>
</tbody>
</table>
-104
View File
@@ -1,104 +0,0 @@
import { pageMetadata } from "@/lib/page-metadata"
export const metadata = pageMetadata("docs/api/redux")
# @json-render/redux
Redux / Redux Toolkit adapter for json-render's `StateStore` interface.
## Installation
```bash
npm install @json-render/redux @json-render/core @json-render/react redux
# or with Redux Toolkit (recommended):
npm install @json-render/redux @json-render/core @json-render/react @reduxjs/toolkit
```
## reduxStateStore
Create a `StateStore` backed by a Redux store.
```typescript
import { reduxStateStore } from "@json-render/redux";
```
### Options
<table>
<thead>
<tr>
<th>Option</th>
<th>Type</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>store</code></td>
<td><code>Store</code></td>
<td>Yes</td>
<td>The Redux store instance.</td>
</tr>
<tr>
<td><code>selector</code></td>
<td><code>{'(state: S) => StateModel'}</code></td>
<td>No</td>
<td>Select the json-render slice from the Redux state tree. Defaults to <code>{'(state) => state'}</code>.</td>
</tr>
<tr>
<td><code>dispatch</code></td>
<td><code>{'(nextState: StateModel, store: Store) => void'}</code></td>
<td>Yes</td>
<td>Dispatch an action that replaces the selected slice with the next state.</td>
</tr>
</tbody>
</table>
### Example
```typescript
import { configureStore, createSlice } from "@reduxjs/toolkit";
import { reduxStateStore } from "@json-render/redux";
import { StateProvider } from "@json-render/react";
const uiSlice = createSlice({
name: "ui",
initialState: { count: 0 } as Record<string, unknown>,
reducers: {
replaceUiState: (_state, action) => action.payload,
},
});
const reduxStore = configureStore({
reducer: { ui: uiSlice.reducer },
});
const store = reduxStateStore({
store: reduxStore,
selector: (state) => state.ui,
dispatch: (next, s) => s.dispatch(uiSlice.actions.replaceUiState(next)),
});
```
```tsx
<StateProvider store={store}>
{/* json-render reads/writes go through Redux */}
</StateProvider>
```
## Re-exports
<table>
<thead>
<tr>
<th>Export</th>
<th>Source</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>StateStore</code></td>
<td><code>@json-render/core</code></td>
</tr>
</tbody>
</table>
@@ -1,77 +0,0 @@
import { pageMetadata } from "@/lib/page-metadata"
export const metadata = pageMetadata("docs/api/xstate")
# @json-render/xstate
[XState Store](https://stately.ai/docs/xstate-store) adapter for json-render's `StateStore` interface.
Requires `@xstate/store` v3+.
## Installation
```bash
npm install @json-render/xstate @json-render/core @json-render/react @xstate/store
```
## xstateStoreStateStore
Create a `StateStore` backed by an `@xstate/store` atom.
```typescript
import { xstateStoreStateStore } from "@json-render/xstate";
```
### Options
<table>
<thead>
<tr>
<th>Option</th>
<th>Type</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>atom</code></td>
<td><code>{'Atom<StateModel>'}</code></td>
<td>Yes</td>
<td>An <code>@xstate/store</code> atom (from <code>createAtom</code>) holding the json-render state model.</td>
</tr>
</tbody>
</table>
### Example
```typescript
import { createAtom } from "@xstate/store";
import { xstateStoreStateStore } from "@json-render/xstate";
import { StateProvider } from "@json-render/react";
const uiAtom = createAtom({ count: 0 });
const store = xstateStoreStateStore({ atom: uiAtom });
```
```tsx
<StateProvider store={store}>
{/* json-render reads/writes go through @xstate/store */}
</StateProvider>
```
## Re-exports
<table>
<thead>
<tr>
<th>Export</th>
<th>Source</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>StateStore</code></td>
<td><code>@json-render/core</code></td>
</tr>
</tbody>
</table>
@@ -1,108 +0,0 @@
import { pageMetadata } from "@/lib/page-metadata"
export const metadata = pageMetadata("docs/api/zustand")
# @json-render/zustand
Zustand adapter for json-render's `StateStore` interface.
Requires Zustand v5+. Zustand v4 is not supported due to breaking API changes in the vanilla store interface.
## Installation
```bash
npm install @json-render/zustand @json-render/core @json-render/react zustand
```
## zustandStateStore
Create a `StateStore` backed by a Zustand vanilla store.
```typescript
import { zustandStateStore } from "@json-render/zustand";
```
### Options
<table>
<thead>
<tr>
<th>Option</th>
<th>Type</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>store</code></td>
<td><code>{'StoreApi<S>'}</code></td>
<td>Yes</td>
<td>A Zustand vanilla store (from <code>createStore</code> in <code>zustand/vanilla</code>).</td>
</tr>
<tr>
<td><code>selector</code></td>
<td><code>{'(state: S) => StateModel'}</code></td>
<td>No</td>
<td>Select the json-render slice from the store state. Defaults to the entire state.</td>
</tr>
<tr>
<td><code>updater</code></td>
<td><code>{'(nextState: StateModel, store: StoreApi<S>) => void'}</code></td>
<td>No</td>
<td>Apply a state change back to the store. Defaults to a shallow merge.</td>
</tr>
</tbody>
</table>
### Example
```typescript
import { createStore } from "zustand/vanilla";
import { zustandStateStore } from "@json-render/zustand";
import { StateProvider } from "@json-render/react";
const bearStore = createStore(() => ({
count: 0,
name: "Bear",
}));
const store = zustandStateStore({ store: bearStore });
```
```tsx
<StateProvider store={store}>
{/* json-render reads/writes go through Zustand */}
</StateProvider>
```
### Nested Slice
```typescript
const appStore = createStore(() => ({
ui: { count: 0 },
auth: { token: null },
}));
const store = zustandStateStore({
store: appStore,
selector: (s) => s.ui,
updater: (next, s) => s.setState({ ui: next }),
});
```
## Re-exports
<table>
<thead>
<tr>
<th>Export</th>
<th>Source</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>StateStore</code></td>
<td><code>@json-render/core</code></td>
</tr>
</tbody>
</table>
+1 -1
View File
@@ -16,7 +16,7 @@ const SYSTEM_PROMPT = `You are a helpful documentation assistant for json-render
GitHub repository: https://github.com/vercel-labs/json-render
Documentation: https://json-render.dev/docs
npm packages: @json-render/core, @json-render/react, @json-render/vue, @json-render/svelte, @json-render/shadcn, @json-render/react-native, @json-render/react-email, @json-render/react-pdf, @json-render/image, @json-render/remotion, @json-render/codegen, @json-render/mcp, @json-render/redux, @json-render/zustand, @json-render/jotai, @json-render/xstate
npm packages: @json-render/core, @json-render/react, @json-render/react-email, @json-render/react-pdf, @json-render/image, @json-render/remotion, @json-render/codegen, @json-render/mcp
You have access to the full json-render documentation via the bash and readFile tools. The docs are available as markdown files in the /workspace/docs/ directory.
-4
View File
@@ -134,10 +134,6 @@ export const docsNavigation: NavSection[] = [
{ title: "@json-render/svelte", href: "/docs/api/svelte" },
{ title: "@json-render/codegen", href: "/docs/api/codegen" },
{ title: "@json-render/mcp", href: "/docs/api/mcp" },
{ title: "@json-render/redux", href: "/docs/api/redux" },
{ title: "@json-render/zustand", href: "/docs/api/zustand" },
{ title: "@json-render/jotai", href: "/docs/api/jotai" },
{ title: "@json-render/xstate", href: "/docs/api/xstate" },
],
},
];
-4
View File
@@ -51,10 +51,6 @@ export const PAGE_TITLES: Record<string, string> = {
"docs/api/remotion": "@json-render/remotion API",
"docs/api/shadcn": "@json-render/shadcn API",
"docs/api/mcp": "@json-render/mcp API",
"docs/api/redux": "@json-render/redux API",
"docs/api/zustand": "@json-render/zustand API",
"docs/api/jotai": "@json-render/jotai API",
"docs/api/xstate": "@json-render/xstate API",
};
/**
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "web",
"version": "0.1.5",
"version": "0.1.4",
"type": "module",
"private": true,
"license": "Apache-2.0",
-9
View File
@@ -1,14 +1,5 @@
# example-chat
## 0.1.5
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/react@0.12.0
- @json-render/shadcn@0.12.0
## 0.1.4
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-chat",
"version": "0.1.5",
"version": "0.1.4",
"type": "module",
"private": true,
"scripts": {
-9
View File
@@ -1,14 +1,5 @@
# example-dashboard
## 0.1.5
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/codegen@0.12.0
- @json-render/react@0.12.0
## 0.1.4
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-dashboard",
"version": "0.1.5",
"version": "0.1.4",
"type": "module",
"private": true,
"scripts": {
-8
View File
@@ -1,13 +1,5 @@
# example-image
## 0.1.2
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/image@0.12.0
## 0.1.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-image",
"version": "0.1.2",
"version": "0.1.1",
"type": "module",
"private": true,
"scripts": {
-11
View File
@@ -1,11 +0,0 @@
# example-mcp
## 0.1.1
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/mcp@0.12.0
- @json-render/react@0.12.0
- @json-render/shadcn@0.12.0
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-mcp",
"version": "0.1.1",
"version": "0.1.0",
"type": "module",
"private": true,
"scripts": {
-9
View File
@@ -1,14 +1,5 @@
# example-no-ai
## 0.1.5
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/react@0.12.0
- @json-render/shadcn@0.12.0
## 0.1.4
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-no-ai",
"version": "0.1.5",
"version": "0.1.4",
"type": "module",
"private": true,
"scripts": {
-9
View File
@@ -1,9 +0,0 @@
# example-react-email
## 0.1.1
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/react-email@0.12.0
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-react-email",
"version": "0.1.1",
"version": "0.1.0",
"type": "module",
"private": true,
"scripts": {
-8
View File
@@ -1,13 +1,5 @@
# example-react-native
## 0.1.5
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/react-native@0.12.0
## 0.1.4
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-react-native",
"version": "0.1.5",
"version": "0.1.4",
"private": true,
"main": "expo-router/entry",
"scripts": {
-8
View File
@@ -1,13 +1,5 @@
# example-react-pdf
## 0.1.5
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/react-pdf@0.12.0
## 0.1.4
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-react-pdf",
"version": "0.1.5",
"version": "0.1.4",
"type": "module",
"private": true,
"scripts": {
-8
View File
@@ -1,13 +1,5 @@
# example-remotion
## 0.1.5
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/remotion@0.12.0
## 0.1.4
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-remotion",
"version": "0.1.5",
"version": "0.1.4",
"type": "module",
"private": true,
"scripts": {
@@ -1,13 +1,5 @@
# com.example.json-render-demo
## 0.0.6
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/react@0.12.0
## 0.0.5
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "com.example.json-render-demo",
"version": "0.0.6",
"version": "0.0.5",
"description": "Test",
"private": true,
"license": "~~proprietary~~",
@@ -1,13 +1,5 @@
# com.example.json-render-fullpage-demo
## 0.0.6
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/react@0.12.0
## 0.0.5
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "com.example.json-render-fullpage-demo",
"version": "0.0.6",
"version": "0.0.5",
"description": "Full-page Stripe App example (alpha)",
"private": true,
"license": "~~proprietary~~",
-9
View File
@@ -1,9 +0,0 @@
# svelte-chat
## 0.0.2
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/svelte@0.12.0
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "svelte-chat",
"private": true,
"version": "0.0.2",
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite dev",
-9
View File
@@ -1,9 +0,0 @@
# example-svelte
## 0.1.2
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/svelte@0.12.0
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-svelte",
"version": "0.1.2",
"version": "0.1.1",
"private": true,
"type": "module",
"scripts": {
-10
View File
@@ -1,15 +1,5 @@
# vite-renderers
## 0.1.3
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/svelte@0.12.0
- @json-render/react@0.12.0
- @json-render/vue@0.12.0
## 0.1.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "vite-renderers",
"version": "0.1.3",
"version": "0.1.2",
"private": true,
"type": "module",
"scripts": {
-8
View File
@@ -1,13 +1,5 @@
# example-vue
## 0.1.3
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/vue@0.12.0
## 0.1.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-vue",
"version": "0.1.3",
"version": "0.1.2",
"private": true,
"scripts": {
"predev": "command -v portless >/dev/null 2>&1 || (echo '\\nportless is required but not installed. Run: npm i -g portless\\nSee: https://github.com/vercel-labs/portless\\n' && exit 1)",
-7
View File
@@ -1,12 +1,5 @@
# @json-render/codegen
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/codegen",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "Utilities for generating code from json-render UI trees",
"keywords": [
-14
View File
@@ -1,19 +1,5 @@
# @json-render/core
## 0.12.0
### Minor Changes
- 63c339b: Add Svelte renderer, React Email renderer, and MCP Apps integration.
### New:
- **`@json-render/svelte`** — Svelte 5 renderer with runes-based reactivity. Full support for data binding, visibility, actions, validation, watchers, streaming, and repeat scopes. Includes `defineRegistry`, `Renderer`, `schema`, composables, and context providers.
- **`@json-render/react-email`** — React Email renderer for generating HTML and plain-text emails from JSON specs. 17 standard components (Html, Head, Body, Container, Section, Row, Column, Heading, Text, Link, Button, Image, Hr, Preview, Markdown). Server-side `renderToHtml` / `renderToPlainText` APIs. Custom catalog and registry support.
- **`@json-render/mcp`** — MCP Apps integration that serves json-render UIs as interactive apps inside Claude, ChatGPT, Cursor, VS Code, and other MCP-capable clients. `createMcpApp` server factory, `useJsonRenderApp` React hook for iframes, and `buildAppHtml` utility.
### Fixed:
- **`@json-render/svelte`** — Corrected JSDoc comment and added missing `zod` peer dependency.
## 0.11.0
### Minor Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/core",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "JSON becomes real things. Define your catalog, register your components, let AI generate.",
"keywords": [
-7
View File
@@ -1,12 +1,5 @@
# @json-render/image
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Minor Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/image",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "Image renderer for @json-render/core. JSON becomes SVG and PNG images via Satori.",
"keywords": [
-7
View File
@@ -1,12 +1,5 @@
# @json-render/jotai
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/jotai",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "Jotai adapter for json-render StateStore",
"keywords": [
-20
View File
@@ -1,20 +0,0 @@
# @json-render/mcp
## 0.12.0
### Minor Changes
- 63c339b: Add Svelte renderer, React Email renderer, and MCP Apps integration.
### New:
- **`@json-render/svelte`** — Svelte 5 renderer with runes-based reactivity. Full support for data binding, visibility, actions, validation, watchers, streaming, and repeat scopes. Includes `defineRegistry`, `Renderer`, `schema`, composables, and context providers.
- **`@json-render/react-email`** — React Email renderer for generating HTML and plain-text emails from JSON specs. 17 standard components (Html, Head, Body, Container, Section, Row, Column, Heading, Text, Link, Button, Image, Hr, Preview, Markdown). Server-side `renderToHtml` / `renderToPlainText` APIs. Custom catalog and registry support.
- **`@json-render/mcp`** — MCP Apps integration that serves json-render UIs as interactive apps inside Claude, ChatGPT, Cursor, VS Code, and other MCP-capable clients. `createMcpApp` server factory, `useJsonRenderApp` React hook for iframes, and `buildAppHtml` utility.
### Fixed:
- **`@json-render/svelte`** — Corrected JSDoc comment and added missing `zod` peer dependency.
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/mcp",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "MCP Apps integration for @json-render/core. Serve json-render UIs as interactive MCP Apps in Claude, ChatGPT, Cursor, and VS Code.",
"keywords": [
-20
View File
@@ -1,20 +0,0 @@
# @json-render/react-email
## 0.12.0
### Minor Changes
- 63c339b: Add Svelte renderer, React Email renderer, and MCP Apps integration.
### New:
- **`@json-render/svelte`** — Svelte 5 renderer with runes-based reactivity. Full support for data binding, visibility, actions, validation, watchers, streaming, and repeat scopes. Includes `defineRegistry`, `Renderer`, `schema`, composables, and context providers.
- **`@json-render/react-email`** — React Email renderer for generating HTML and plain-text emails from JSON specs. 17 standard components (Html, Head, Body, Container, Section, Row, Column, Heading, Text, Link, Button, Image, Hr, Preview, Markdown). Server-side `renderToHtml` / `renderToPlainText` APIs. Custom catalog and registry support.
- **`@json-render/mcp`** — MCP Apps integration that serves json-render UIs as interactive apps inside Claude, ChatGPT, Cursor, VS Code, and other MCP-capable clients. `createMcpApp` server factory, `useJsonRenderApp` React hook for iframes, and `buildAppHtml` utility.
### Fixed:
- **`@json-render/svelte`** — Corrected JSDoc comment and added missing `zod` peer dependency.
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/react-email",
"version": "0.12.0",
"version": "0.8.0",
"license": "Apache-2.0",
"description": "React Email renderer for @json-render/core. JSON becomes HTML emails.",
"keywords": [
-7
View File
@@ -1,12 +1,5 @@
# @json-render/react-native
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/react-native",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "React Native renderer for @json-render/core. JSON becomes React Native components.",
"keywords": [
-7
View File
@@ -1,12 +1,5 @@
# @json-render/react-pdf
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/react-pdf",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "React PDF renderer for @json-render/core. JSON becomes PDF documents.",
"keywords": [
-7
View File
@@ -1,12 +1,5 @@
# @internal/react-state
## 0.8.5
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.8.4
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@internal/react-state",
"version": "0.8.5",
"version": "0.8.4",
"private": true,
"license": "Apache-2.0",
"description": "Shared React state context for json-render renderer packages",
-7
View File
@@ -1,12 +1,5 @@
# @json-render/react
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/react",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "React renderer for @json-render/core. JSON becomes React components.",
"keywords": [
-7
View File
@@ -1,12 +1,5 @@
# @json-render/redux
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/redux",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "Redux adapter for json-render StateStore",
"keywords": [
-7
View File
@@ -1,12 +1,5 @@
# @json-render/remotion
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/remotion",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "Remotion renderer for @json-render/core. JSON becomes video compositions.",
"keywords": [
-8
View File
@@ -1,13 +1,5 @@
# @json-render/shadcn
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
- @json-render/react@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/shadcn",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "shadcn/ui component library for @json-render/core. JSON becomes beautiful Tailwind-styled React components.",
"keywords": [
-20
View File
@@ -1,20 +0,0 @@
# @json-render/svelte
## 0.12.0
### Minor Changes
- 63c339b: Add Svelte renderer, React Email renderer, and MCP Apps integration.
### New:
- **`@json-render/svelte`** — Svelte 5 renderer with runes-based reactivity. Full support for data binding, visibility, actions, validation, watchers, streaming, and repeat scopes. Includes `defineRegistry`, `Renderer`, `schema`, composables, and context providers.
- **`@json-render/react-email`** — React Email renderer for generating HTML and plain-text emails from JSON specs. 17 standard components (Html, Head, Body, Container, Section, Row, Column, Heading, Text, Link, Button, Image, Hr, Preview, Markdown). Server-side `renderToHtml` / `renderToPlainText` APIs. Custom catalog and registry support.
- **`@json-render/mcp`** — MCP Apps integration that serves json-render UIs as interactive apps inside Claude, ChatGPT, Cursor, VS Code, and other MCP-capable clients. `createMcpApp` server factory, `useJsonRenderApp` React hook for iframes, and `buildAppHtml` utility.
### Fixed:
- **`@json-render/svelte`** — Corrected JSDoc comment and added missing `zod` peer dependency.
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
-155
View File
@@ -1,155 +0,0 @@
# @json-render/svelte
Svelte 5 renderer for `@json-render/core`. Turn JSON specs into Svelte components with runes-based reactivity.
## Installation
```bash
npm install @json-render/core @json-render/svelte
```
Peer dependencies: `svelte ^5.0.0` and `zod ^4.0.0`.
## Quick Start
### 1. Create a Catalog
```typescript
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/svelte/schema";
import { z } from "zod";
export const catalog = defineCatalog(schema, {
components: {
Card: {
props: z.object({
title: z.string(),
description: z.string().nullable(),
}),
description: "A card container",
},
Button: {
props: z.object({
label: z.string(),
action: z.string(),
}),
description: "A clickable button",
},
},
actions: {
submit: { description: "Submit the form" },
},
});
```
### 2. Define Component Implementations
```typescript
import { defineRegistry } from "@json-render/svelte";
import { catalog } from "./catalog";
export const { registry } = defineRegistry(catalog, {
components: {
Card: ({ props, children }) => /* Svelte 5 snippet */,
Button: ({ props, emit }) => /* Svelte 5 snippet */,
},
actions: {
submit: async (params) => { /* handle submit */ },
},
});
```
### 3. Render Specs
```svelte
<script>
import { Renderer, StateProvider, ActionProvider } from "@json-render/svelte";
import { registry } from "./registry";
const spec = { /* ... */ };
</script>
<StateProvider initialState={{ form: { name: "" } }}>
<ActionProvider handlers={{ submit: handleSubmit }}>
<Renderer {spec} {registry} />
</ActionProvider>
</StateProvider>
```
## Providers
| Provider | Purpose |
|----------|---------|
| `StateProvider` | Share state across components (JSON Pointer paths). Accepts optional `store` prop for controlled mode. |
| `ActionProvider` | Handle actions dispatched via the event system |
| `VisibilityProvider` | Enable conditional rendering based on state |
| `ValidationProvider` | Form field validation |
| `RepeatScopeProvider` | Repeat scope for list rendering |
| `FunctionsContextProvider` | Register `$computed` functions |
| `JsonUIProvider` | All-in-one provider combining state, actions, visibility, validation, and functions |
## Context Accessors
Svelte 5 uses `getContext`-based accessors instead of hooks:
| Accessor | Purpose |
|----------|---------|
| `getStateContext()` | Access state context (`state`, `get`, `set`) |
| `getStateValue(path)` | Get single value from state |
| `getBoundProp(value, binding)` | Two-way binding for `$bindState`/`$bindItem` |
| `getVisibilityContext()` | Access visibility context |
| `isVisible(condition)` | Check if a visibility condition is met |
| `getActionContext()` | Access action context |
| `getAction(binding)` | Get a single action dispatch function |
| `getValidationContext()` | Access validation context |
| `getFieldValidation(path, config)` | Field validation state |
| `getRepeatScope()` | Access current repeat scope |
| `getFunctions()` | Access registered computed functions |
## Streaming
```typescript
import { createUIStream, createChatUI } from "@json-render/svelte";
const stream = createUIStream({ endpoint: "/api/generate" });
// Or for chat-style UI:
const chat = createChatUI({ endpoint: "/api/chat" });
```
## Key Exports
| Export | Purpose |
|--------|---------|
| `defineRegistry` | Create a type-safe component registry from a catalog |
| `createRenderer` | Create a renderer function from a registry |
| `Renderer` | Render a spec using a registry |
| `CatalogRenderer` | Render with automatic provider wiring |
| `JsonUIProvider` | All-in-one provider |
| `schema` | Element tree schema (includes built-in state actions) |
| `createUIStream` | Stream specs from an API endpoint |
| `createChatUI` | Chat-style streaming interface |
| `flatToTree` | Convert flat spec to tree format |
| `ConfirmDialog` | Confirmation dialog component |
| `ConfirmDialogManager` | Manage multiple confirmation dialogs |
### 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 |
| `SvelteSchema` | Schema type for the Svelte renderer |
| `SvelteSpec` | Spec type for the Svelte renderer |
## Documentation
Full API reference: [json-render.dev/docs/api/svelte](https://json-render.dev/docs/api/svelte).
## License
Apache-2.0
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/svelte",
"version": "0.12.0",
"version": "0.6.1",
"license": "Apache-2.0",
"description": "Svelte 5 renderer for @json-render/core. JSON becomes Svelte components.",
"keywords": [
-7
View File
@@ -1,12 +1,5 @@
# @json-render/vue
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/vue",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "Vue renderer for @json-render/core. JSON becomes Vue components.",
"keywords": [
-7
View File
@@ -1,12 +1,5 @@
# @json-render/xstate
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/xstate",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "XState Store adapter for json-render StateStore",
"keywords": [
-7
View File
@@ -1,12 +1,5 @@
# @json-render/zustand
## 0.12.0
### Patch Changes
- Updated dependencies [63c339b]
- @json-render/core@0.12.0
## 0.11.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@json-render/zustand",
"version": "0.12.0",
"version": "0.11.0",
"license": "Apache-2.0",
"description": "Zustand adapter for json-render StateStore",
"keywords": [
-112
View File
@@ -1,112 +0,0 @@
---
name: json-render-codegen
description: Code generation utilities for json-render. Use when generating code from UI specs, building custom code exporters, traversing specs, or serializing props for @json-render/codegen.
---
# @json-render/codegen
Framework-agnostic utilities for generating code from json-render UI trees. Use these to build custom code exporters for Next.js, Remix, or other frameworks.
## Installation
```bash
npm install @json-render/codegen
```
## Tree Traversal
```typescript
import {
traverseSpec,
collectUsedComponents,
collectStatePaths,
collectActions,
} from "@json-render/codegen";
// Walk the spec depth-first
traverseSpec(spec, (element, key, depth, parent) => {
console.log(`${" ".repeat(depth * 2)}${key}: ${element.type}`);
});
// Get all component types used
const components = collectUsedComponents(spec);
// Set { "Card", "Metric", "Button" }
// Get all state paths referenced
const statePaths = collectStatePaths(spec);
// Set { "analytics/revenue", "user/name" }
// Get all action names
const actions = collectActions(spec);
// Set { "submit_form", "refresh_data" }
```
## Serialization
```typescript
import {
serializePropValue,
serializeProps,
escapeString,
type SerializeOptions,
} from "@json-render/codegen";
// Serialize a single value
serializePropValue("hello");
// { value: '"hello"', needsBraces: false }
serializePropValue({ $state: "/user/name" });
// { value: '{ $state: "/user/name" }', needsBraces: true }
// Serialize props for JSX
serializeProps({ title: "Dashboard", columns: 3, disabled: true });
// 'title="Dashboard" columns={3} disabled'
// Escape strings for code
escapeString('hello "world"');
// 'hello \"world\"'
```
### SerializeOptions
```typescript
interface SerializeOptions {
quotes?: "single" | "double";
indent?: number;
}
```
## Types
```typescript
import type { GeneratedFile, CodeGenerator } from "@json-render/codegen";
const myGenerator: CodeGenerator = {
generate(spec) {
return [
{ path: "package.json", content: "..." },
{ path: "app/page.tsx", content: "..." },
];
},
};
```
## Building a Custom Generator
```typescript
import {
collectUsedComponents,
collectStatePaths,
traverseSpec,
serializeProps,
type GeneratedFile,
} from "@json-render/codegen";
import type { Spec } from "@json-render/core";
export function generateNextJSProject(spec: Spec): GeneratedFile[] {
const files: GeneratedFile[] = [];
const components = collectUsedComponents(spec);
// Generate package.json, component files, main page...
return files;
}
```
-66
View File
@@ -1,66 +0,0 @@
---
name: json-render-jotai
description: Jotai adapter for json-render's StateStore interface. Use when integrating json-render with Jotai for state management via @json-render/jotai.
---
# @json-render/jotai
Jotai adapter for json-render's `StateStore` interface. Wire a Jotai atom as the state backend for json-render.
## Installation
```bash
npm install @json-render/jotai @json-render/core @json-render/react jotai
```
## Usage
```tsx
import { atom } from "jotai";
import { jotaiStateStore } from "@json-render/jotai";
import { StateProvider } from "@json-render/react";
// 1. Create an atom that holds the json-render state
const uiAtom = atom<Record<string, unknown>>({ count: 0 });
// 2. Create the json-render StateStore adapter
const store = jotaiStateStore({ atom: uiAtom });
// 3. Use it
<StateProvider store={store}>
{/* json-render reads/writes go through Jotai */}
</StateProvider>
```
### With a Shared Jotai Store
When your app already uses a Jotai `<Provider>` with a custom store, pass it so both json-render and your components share the same state:
```tsx
import { atom, createStore } from "jotai";
import { Provider as JotaiProvider } from "jotai/react";
import { jotaiStateStore } from "@json-render/jotai";
import { StateProvider } from "@json-render/react";
const jStore = createStore();
const uiAtom = atom<Record<string, unknown>>({ count: 0 });
const store = jotaiStateStore({ atom: uiAtom, store: jStore });
<JotaiProvider store={jStore}>
<StateProvider store={store}>
{/* Both json-render and useAtom() see the same state */}
</StateProvider>
</JotaiProvider>
```
## API
### `jotaiStateStore(options)`
Creates a `StateStore` backed by a Jotai atom.
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `atom` | `WritableAtom<StateModel, [StateModel], void>` | Yes | A writable atom holding the state model |
| `store` | Jotai `Store` | No | The Jotai store instance. Defaults to a new store. Pass your own to share state with `<Provider>`. |
-142
View File
@@ -1,142 +0,0 @@
---
name: json-render-react-pdf
description: React PDF renderer for json-render. Use when generating PDF documents from JSON specs, working with @json-render/react-pdf, or rendering specs to PDF buffers/streams/files.
---
# @json-render/react-pdf
React PDF renderer that generates PDF documents from JSON specs using `@react-pdf/renderer`.
## Installation
```bash
npm install @json-render/core @json-render/react-pdf
```
## Quick Start
```typescript
import { renderToBuffer } from "@json-render/react-pdf";
import type { Spec } from "@json-render/core";
const spec: Spec = {
root: "doc",
elements: {
doc: { type: "Document", props: { title: "Invoice" }, children: ["page"] },
page: {
type: "Page",
props: { size: "A4" },
children: ["heading", "table"],
},
heading: {
type: "Heading",
props: { text: "Invoice #1234", level: "h1" },
children: [],
},
table: {
type: "Table",
props: {
columns: [
{ header: "Item", width: "60%" },
{ header: "Price", width: "40%", align: "right" },
],
rows: [
["Widget A", "$10.00"],
["Widget B", "$25.00"],
],
},
children: [],
},
},
};
const buffer = await renderToBuffer(spec);
```
## Render APIs
```typescript
import { renderToBuffer, renderToStream, renderToFile } from "@json-render/react-pdf";
// In-memory buffer
const buffer = await renderToBuffer(spec);
// Readable stream (pipe to HTTP response)
const stream = await renderToStream(spec);
stream.pipe(res);
// Direct to file
await renderToFile(spec, "./output.pdf");
```
All render functions accept an optional second argument: `{ registry?, state?, handlers? }`.
## Standard Components
| Component | Description |
|-----------|-------------|
| `Document` | Top-level PDF wrapper (must be root) |
| `Page` | Page with size (A4, LETTER), orientation, margins |
| `View` | Generic container (padding, margin, background, border) |
| `Row`, `Column` | Flex layout with gap, align, justify |
| `Heading` | h1-h4 heading text |
| `Text` | Body text (fontSize, color, weight, alignment) |
| `Image` | Image from URL or base64 |
| `Link` | Hyperlink with text and href |
| `Table` | Data table with typed columns and rows |
| `List` | Ordered or unordered list |
| `Divider` | Horizontal line separator |
| `Spacer` | Empty vertical space |
| `PageNumber` | Current page number and total pages |
## Custom Catalog
```typescript
import { defineCatalog } from "@json-render/core";
import { schema, defineRegistry, renderToBuffer } from "@json-render/react-pdf";
import { standardComponentDefinitions } from "@json-render/react-pdf/catalog";
import { z } from "zod";
const catalog = defineCatalog(schema, {
components: {
...standardComponentDefinitions,
Badge: {
props: z.object({ label: z.string(), color: z.string().nullable() }),
slots: [],
description: "A colored badge label",
},
},
actions: {},
});
const { registry } = defineRegistry(catalog, {
components: {
Badge: ({ props }) => (
<View style={{ backgroundColor: props.color ?? "#e5e7eb", padding: 4 }}>
<Text>{props.label}</Text>
</View>
),
},
});
const buffer = await renderToBuffer(spec, { registry });
```
## External Store (Controlled Mode)
Pass a `StateStore` for full control over state:
```typescript
import { createStateStore } from "@json-render/react-pdf";
const store = createStateStore({ invoice: { total: 100 } });
store.set("/invoice/total", 200);
```
## Server-Safe Import
Import schema and catalog without pulling in React:
```typescript
import { schema, standardComponentDefinitions } from "@json-render/react-pdf/server";
```
-64
View File
@@ -1,64 +0,0 @@
---
name: json-render-redux
description: Redux adapter for json-render's StateStore interface. Use when integrating json-render with Redux or Redux Toolkit for state management via @json-render/redux.
---
# @json-render/redux
Redux adapter for json-render's `StateStore` interface. Wire a Redux store (or Redux Toolkit slice) as the state backend for json-render.
## Installation
```bash
npm install @json-render/redux @json-render/core @json-render/react redux
# or with Redux Toolkit (recommended):
npm install @json-render/redux @json-render/core @json-render/react @reduxjs/toolkit
```
## Usage
```tsx
import { configureStore, createSlice } from "@reduxjs/toolkit";
import { reduxStateStore } from "@json-render/redux";
import { StateProvider } from "@json-render/react";
// 1. Define a slice for json-render state
const uiSlice = createSlice({
name: "ui",
initialState: { count: 0 } as Record<string, unknown>,
reducers: {
replaceUiState: (_state, action) => action.payload,
},
});
// 2. Create the Redux store
const reduxStore = configureStore({
reducer: { ui: uiSlice.reducer },
});
// 3. Create the json-render StateStore adapter
const store = reduxStateStore({
store: reduxStore,
selector: (state) => state.ui,
dispatch: (next, s) => s.dispatch(uiSlice.actions.replaceUiState(next)),
});
// 4. Use it
<StateProvider store={store}>
{/* json-render reads/writes go through Redux */}
</StateProvider>
```
## API
### `reduxStateStore(options)`
Creates a `StateStore` backed by a Redux store.
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `store` | `Store` | Yes | The Redux store instance |
| `selector` | `(state) => StateModel` | Yes | Select the json-render slice from the Redux state tree. Use `(s) => s` if the entire state is the model. |
| `dispatch` | `(nextState, store) => void` | Yes | Dispatch an action that replaces the selected slice with the next state |
The `dispatch` callback receives the full next state model and the Redux store.
-177
View File
@@ -1,177 +0,0 @@
---
name: json-render-vue
description: Vue 3 renderer for json-render. Use when building Vue UIs from JSON specs, working with @json-render/vue, defining Vue component registries, or rendering AI-generated specs in Vue.
---
# @json-render/vue
Vue 3 renderer that converts JSON specs into Vue component trees with data binding, visibility, and actions.
## Installation
```bash
npm install @json-render/vue @json-render/core zod
```
Peer dependencies: `vue ^3.5.0` and `zod ^4.0.0`.
## Quick Start
### Create a Catalog
```typescript
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/vue/schema";
import { z } from "zod";
export const catalog = defineCatalog(schema, {
components: {
Card: {
props: z.object({ title: z.string(), description: z.string().nullable() }),
description: "A card container",
},
Button: {
props: z.object({ label: z.string(), action: z.string() }),
description: "A clickable button",
},
},
actions: {},
});
```
### Define Registry with h() Render Functions
```typescript
import { h } from "vue";
import { defineRegistry } from "@json-render/vue";
import { catalog } from "./catalog";
export const { registry } = defineRegistry(catalog, {
components: {
Card: ({ props, children }) =>
h("div", { class: "card" }, [
h("h3", null, props.title),
props.description ? h("p", null, props.description) : null,
children,
]),
Button: ({ props, emit }) =>
h("button", { onClick: () => emit("press") }, props.label),
},
});
```
### Render Specs
```vue
<script setup lang="ts">
import { StateProvider, ActionProvider, Renderer } from "@json-render/vue";
import { registry } from "./registry";
const spec = { root: "card-1", elements: { /* ... */ } };
</script>
<template>
<StateProvider :initial-state="{ form: { name: '' } }">
<ActionProvider :handlers="{ submit: handleSubmit }">
<Renderer :spec="spec" :registry="registry" />
</ActionProvider>
</StateProvider>
</template>
```
## Providers
| Provider | Purpose |
|----------|---------|
| `StateProvider` | Share state across components (JSON Pointer paths). Accepts `initialState` or `store` for controlled mode. |
| `ActionProvider` | Handle actions dispatched via the event system |
| `VisibilityProvider` | Enable conditional rendering based on state |
| `ValidationProvider` | Form field validation |
## Composables
| Composable | Purpose |
|------------|---------|
| `useStateStore()` | Access state context (`state` as `ShallowRef`, `get`, `set`, `update`) |
| `useStateValue(path)` | Get single value from state |
| `useIsVisible(condition)` | Check if a visibility condition is met |
| `useActions()` | Access action context |
| `useAction(binding)` | Get a single action dispatch function |
| `useFieldValidation(path, config)` | Field validation state |
| `useBoundProp(propValue, bindingPath)` | Two-way binding for `$bindState`/`$bindItem` |
Note: `useStateStore().state` returns a `ShallowRef<StateModel>` — use `state.value` to access.
## External Store (StateStore)
Pass a `StateStore` to `StateProvider` to wire json-render to Pinia, VueUse, or any state management:
```typescript
import { createStateStore, type StateStore } from "@json-render/vue";
const store = createStateStore({ count: 0 });
```
```vue
<StateProvider :store="store">
<Renderer :spec="spec" :registry="registry" />
</StateProvider>
```
## Dynamic Prop Expressions
Props support `$state`, `$bindState`, `$cond`, `$template`, `$computed`. Use `{ "$bindState": "/path" }` on the natural value prop for two-way binding.
## Visibility Conditions
```typescript
{ "$state": "/user/isAdmin" }
{ "$state": "/status", "eq": "active" }
{ "$state": "/maintenance", "not": true }
[ cond1, cond2 ] // implicit AND
```
## Built-in Actions
`setState`, `pushState`, `removeState`, and `validateForm` are built into the Vue schema and handled by `ActionProvider`:
```json
{
"action": "setState",
"params": { "statePath": "/activeTab", "value": "settings" }
}
```
## Event System
Components use `emit(event)` to fire events, or `on(event)` for metadata (`shouldPreventDefault`, `bound`).
## Streaming
`useUIStream` and `useChatUI` return Vue Refs for streaming specs from an API.
## BaseComponentProps
For catalog-agnostic reusable components:
```typescript
import type { BaseComponentProps } from "@json-render/vue";
const Card = ({ props, children }: BaseComponentProps<{ title?: string }>) =>
h("div", null, [props.title, children]);
```
## 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 (from `@json-render/vue/schema`) |
| `StateProvider`, `ActionProvider`, `VisibilityProvider`, `ValidationProvider` | Context providers |
| `useStateStore`, `useStateValue`, `useBoundProp` | State composables |
| `useActions`, `useAction` | Action composables |
| `useFieldValidation`, `useIsVisible` | Validation and visibility |
| `useUIStream`, `useChatUI` | Streaming composables |
| `createStateStore` | Create in-memory `StateStore` |
| `BaseComponentProps` | Catalog-agnostic component props type |
-45
View File
@@ -1,45 +0,0 @@
---
name: json-render-xstate
description: XState Store adapter for json-render's StateStore interface. Use when integrating json-render with @xstate/store for state management via @json-render/xstate.
---
# @json-render/xstate
[XState Store](https://stately.ai/docs/xstate-store) adapter for json-render's `StateStore` interface. Wire an `@xstate/store` atom as the state backend for json-render.
## Installation
```bash
npm install @json-render/xstate @json-render/core @json-render/react @xstate/store
```
Requires `@xstate/store` v3+.
## Usage
```tsx
import { createAtom } from "@xstate/store";
import { xstateStoreStateStore } from "@json-render/xstate";
import { StateProvider } from "@json-render/react";
// 1. Create an atom
const uiAtom = createAtom({ count: 0 });
// 2. Create the json-render StateStore adapter
const store = xstateStoreStateStore({ atom: uiAtom });
// 3. Use it
<StateProvider store={store}>
{/* json-render reads/writes go through @xstate/store */}
</StateProvider>
```
## API
### `xstateStoreStateStore(options)`
Creates a `StateStore` backed by an `@xstate/store` atom.
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `atom` | `Atom<StateModel>` | Yes | An `@xstate/store` atom (from `createAtom`) holding the json-render state model |
-65
View File
@@ -1,65 +0,0 @@
---
name: json-render-zustand
description: Zustand adapter for json-render's StateStore interface. Use when integrating json-render with Zustand for state management via @json-render/zustand.
---
# @json-render/zustand
Zustand adapter for json-render's `StateStore` interface. Wire a Zustand vanilla store as the state backend for json-render.
## Installation
```bash
npm install @json-render/zustand @json-render/core @json-render/react zustand
```
Requires Zustand v5+. Zustand v4 is not supported due to breaking API changes in the vanilla store interface.
## Usage
```tsx
import { createStore } from "zustand/vanilla";
import { zustandStateStore } from "@json-render/zustand";
import { StateProvider } from "@json-render/react";
// 1. Create a Zustand vanilla store
const bearStore = createStore(() => ({
count: 0,
name: "Bear",
}));
// 2. Create the json-render StateStore adapter
const store = zustandStateStore({ store: bearStore });
// 3. Use it
<StateProvider store={store}>
{/* json-render reads/writes go through Zustand */}
</StateProvider>
```
### With a Nested Slice
```tsx
const appStore = createStore(() => ({
ui: { count: 0 },
auth: { token: null },
}));
const store = zustandStateStore({
store: appStore,
selector: (s) => s.ui,
updater: (next, s) => s.setState({ ui: next }),
});
```
## API
### `zustandStateStore(options)`
Creates a `StateStore` backed by a Zustand store.
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `store` | `StoreApi<S>` | Yes | Zustand vanilla store (from `createStore` in `zustand/vanilla`) |
| `selector` | `(state) => StateModel` | No | Select the json-render slice. Defaults to entire state. |
| `updater` | `(nextState, store) => void` | No | Apply next state to the store. Defaults to shallow merge. Override for nested slices, or use `(next, s) => s.setState(next, true)` for full replacement. |