react
JSON仕様をReactコンポーネントに変換するjson-render向けReactレンダラーです。`@json-render/react`を使用する場合、JSONからReact UIを構築する場合、コンポーネントカタログの作成、またはAIが生成した仕様のレンダリングに活用できます。
description の原文を見る
React renderer for json-render that turns JSON specs into React components. Use when working with @json-render/react, building React UIs from JSON, creating component catalogs, or rendering AI-generated specs.
SKILL.md 本文
@json-render/react
JSONスペックをReactコンポーネントツリーに変換するReactレンダラー。
クイックスタート
import { defineRegistry, Renderer } from "@json-render/react";
import { catalog } from "./catalog";
const { registry } = defineRegistry(catalog, {
components: {
Card: ({ props, children }) => <div>{props.title}{children}</div>,
},
});
function App({ spec }) {
return <Renderer spec={spec} registry={registry} />;
}
カタログの作成
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/react/schema";
import { defineRegistry } from "@json-render/react";
import { z } from "zod";
// propsスキーマを持つカタログを作成
export const catalog = defineCatalog(schema, {
components: {
Button: {
props: z.object({
label: z.string(),
variant: z.enum(["primary", "secondary"]).nullable(),
}),
description: "Clickable button",
},
Card: {
props: z.object({ title: z.string() }),
description: "Card container with title",
},
},
});
// 型安全なpropsを持つコンポーネント実装を定義
const { registry } = defineRegistry(catalog, {
components: {
Button: ({ props }) => (
<button className={props.variant}>{props.label}</button>
),
Card: ({ props, children }) => (
<div className="card">
<h2>{props.title}</h2>
{children}
</div>
),
},
});
スペック構造(エレメントツリー)
Reactスキーマはエレメントツリーフォーマットを使用します:
{
"root": {
"type": "Card",
"props": { "title": "Hello" },
"children": [
{ "type": "Button", "props": { "label": "Click me" } }
]
}
}
表示条件
エレメントに visible を使用して状態に基づいて表示/非表示を制御します。新しい構文:{ "$state": "/path" }、{ "$state": "/path", "eq": value }、{ "$state": "/path", "not": true }、AND の場合 { "$and": [cond1, cond2] }、OR の場合 { "$or": [cond1, cond2] }。ヘルパー:visibility.when("/path")、visibility.unless("/path")、visibility.eq("/path", val)、visibility.and(cond1, cond2)、visibility.or(cond1, cond2)。
プロバイダー
| プロバイダー | 目的 |
|---|---|
StateProvider | コンポーネント間で状態を共有(JSON Pointerパス)。制御モード用のオプショナルな store プロップを受け入れます。 |
ActionProvider | イベントシステム経由でディスパッチされたアクションを処理 |
VisibilityProvider | 状態に基づく条件付きレンダリングを有効化 |
ValidationProvider | フォームフィールド検証 |
外部ストア(制御モード)
外部の状態管理(Redux、Zustand、XState など)を使用するために、StateStore を StateProvider(または JSONUIProvider / createRenderer)に渡します:
import { createStateStore, type StateStore } from "@json-render/react";
const store = createStateStore({ count: 0 });
<StateProvider store={store}>{children}</StateProvider>
// どこからでも更新可能 — Reactが自動的に再レンダリング:
store.set("/count", 1);
store が指定された場合、initialState と onStateChange は無視されます。
動的プロップ式
任意のプロップ値はレンダラーが解決するデータドリブン式で、コンポーネントがpropsを受け取る前に解決されます:
{ "$state": "/state/key" }- 状態モデルから読み込み(一方向読み込み){ "$bindState": "/path" }- 双方向バインディング:状態から読み込み、書き込みを有効化。フォームコンポーネントの自然な値プロップ(value、checked、pressed など)で使用します。{ "$bindItem": "field" }- リピートアイテムフィールドへの双方向バインディング。リピートスコープ内で使用します。{ "$cond": <condition>, "$then": <value>, "$else": <value> }- 条件付き値{ "$template": "Hello, ${/name}!" }- 状態値を文字列に補間{ "$computed": "fn", "args": { ... } }- 解決済みargで登録関数を呼び出し
{
"type": "Input",
"props": {
"value": { "$bindState": "/form/email" },
"placeholder": "Email"
}
}
コンポーネントは双方向バインディングに statePath プロップを使用しません。代わりに自然な値プロップで { "$bindState": "/path" } を使用します。
コンポーネントは既に解決済みのpropsを受け取ります。双方向バインド時は、レンダラーが提供する bindings マップで useBoundProp フックを使用します。
$computed 関数は JSONUIProvider または createRenderer の functions プロップ経由で登録します:
<JSONUIProvider
functions={{ fullName: (args) => `${args.first} ${args.last}` }}
>
イベントシステム
コンポーネントは emit を使用して名前付きイベントを発火するか、on() を使用してメタデータ付きのイベントハンドルを取得します。エレメントの on フィールドはイベントをアクションバインディングにマッピングします:
// シンプルなイベント発火
Button: ({ props, emit }) => (
<button onClick={() => emit("press")}>{props.label}</button>
),
// メタデータ付きイベントハンドル(例: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>
);
},
{
"type": "Button",
"props": { "label": "Submit" },
"on": { "press": { "action": "submit" } }
}
on() が返す EventHandle は以下を持ちます:emit()、shouldPreventDefault(ブール値)、bound(ブール値)。
状態ウォッチャー
エレメントは watch フィールド(type/props/children と同レベルのトップレベル)を宣言して、状態値が変更されたときにアクションをトリガーできます:
{
"type": "Select",
"props": { "value": { "$bindState": "/form/country" }, "options": ["US", "Canada"] },
"watch": { "/form/country": { "action": "loadCities" } },
"children": []
}
組み込みアクション
setState、pushState、removeState、validateForm アクションはReactスキーマに組み込まれており、ActionProvider によって自動的に処理されます。カタログ actions で宣言する必要なく、AI プロンプトに注入されます:
{ "action": "setState", "params": { "statePath": "/activeTab", "value": "home" } }
{ "action": "pushState", "params": { "statePath": "/items", "value": { "text": "New" } } }
{ "action": "removeState", "params": { "statePath": "/items", "index": 0 } }
{ "action": "validateForm", "params": { "statePath": "/formResult" } }
validateForm はすべての登録フィールドを検証し、{ valid, errors } を状態に書き込みます。
注:アクションパラメータの statePath(例:setState.statePath)は変更対象パスです。コンポーネントpropsでの双方向バインディングは statePath ではなく、値プロップで { "$bindState": "/path" } を使用します。
useBoundProp
双方向バインディングが必要なフォームコンポーネント用に、プロップが { "$bindState": "/path" } または { "$bindItem": "field" } を使用する場合、レンダラーが提供する bindings マップで useBoundProp を使用します:
import { useBoundProp } from "@json-render/react";
Input: ({ element, bindings }) => {
const [value, setValue] = useBoundProp<string>(
element.props.value,
bindings?.value
);
return (
<input
value={value ?? ""}
onChange={(e) => setValue(e.target.value)}
/>
);
},
useBoundProp(propValue, bindingPath) は [value, setValue] を返します。value は解決済みのプロップ;setValue はバインド済みの状態パスに書き込みます(バインドされていない場合はno-op)。
BaseComponentProps
特定のカタログに紐付かない再利用可能なコンポーネントライブラリを構築するため(例:@json-render/shadcn):
import type { BaseComponentProps } from "@json-render/react";
const Card = ({ props, children }: BaseComponentProps<{ title?: string }>) => (
<div>{props.title}{children}</div>
);
defineRegistry
defineRegistry は、カタログが actions を宣言している場合のみ actions フィールドを条件付きで必須とします。actions: {} を持つカタログはそれを省略できます。
主要なエクスポート
| エクスポート | 目的 |
|---|---|
defineRegistry | カタログから型安全なコンポーネントレジストリを作成 |
Renderer | レジストリを使用してスペックをレンダリング |
schema | エレメントツリースキーマ(組み込み状態アクション:setState、pushState、removeState、validateForm を含む) |
useStateStore | 状態コンテキストにアクセス |
useStateValue | 状態から単一の値を取得 |
useBoundProp | $bindState/$bindItem 式の双方向バインディング |
useActions | アクションコンテキストにアクセス |
useAction | 単一のアクションディスパッチ関数を取得 |
useOptionalValidation | useValidation の例外非スローバリアント(プロバイダーがない場合はnullを返す) |
useUIStream | APIエンドポイントからスペックをストリーム |
createStateStore | フレームワークに依存しないインメモリ StateStore を作成 |
StateStore | 外部状態管理をプラグインするためのインターフェース |
BaseComponentProps | 再利用可能なコンポーネントライブラリ用のカタログに依存しない基本型 |
EventHandle | イベントハンドル型(emit、shouldPreventDefault、bound) |
ComponentContext | 型付きコンポーネントコンテキスト(カタログ対応) |
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- vercel-labs
- ライセンス
- Apache-2.0
- 最終更新
- 不明
Source: https://github.com/vercel-labs/json-render / ライセンス: Apache-2.0
関連スキル
agent-browser
AI エージェント向けのブラウザ自動化 CLI です。ウェブサイトとの対話が必要な場合に使用します。ページ遷移、フォーム入力、ボタンクリック、スクリーンショット取得、データ抽出、ウェブアプリのテスト、ブラウザ操作の自動化など、あらゆるブラウザタスクに対応できます。「ウェブサイトを開く」「フォームに記入する」「ボタンをクリックする」「スクリーンショットを取得する」「ページからデータを抽出する」「このウェブアプリをテストする」「サイトにログインする」「ブラウザ操作を自動化する」といった要求や、プログラマティックなウェブ操作が必要なタスクで起動します。
anyskill
AnySkill — あなたのプライベート・スキルクラウド。GitHubを基盤としたリポジトリからエージェントスキルを管理、同期、動的にロードできます。自然言語でクラウドスキルを検索し、オンデマンドでプロンプトを自動ロード、カスタムスキルのアップロードと共有、スキルバンドルの一括インストールが可能です。OpenClaw、Antigravity、Claude Code、Cursorに対応しています。
engram
AIエージェント向けの永続的なメモリシステムです。バグ修正、意思決定、発見、設定変更の後はmem_saveを使用してください。ユーザーが「覚えている」「記憶している」と言及した場合、または以前のセッションと重複する作業を開始する際はmem_searchを使用します。セッション終了前にmem_session_summaryを使用して、コンテキストを保持してください。
skyvern
AI駆動のブラウザ自動化により、任意のウェブサイトを自動化できます。フォーム入力、データ抽出、ファイルダウンロード、ログイン、複数ステップのワークフロー実行など、ユーザーがウェブサイトと連携する必要があるときに使用します。Skyvernは、LLMとコンピュータビジョンを活用して、未知のサイトも自動操作可能です。Python SDK、TypeScript SDK、REST API、MCPサーバー、またはCLIを通じて統合できます。
pinchbench
PinchBenchベンチマークを実行して、OpenClawエージェントの実世界タスクにおけるパフォーマンスを評価できます。モデルの機能テスト、モデル間の比較、ベンチマーク結果のリーダーボード提出、またはOpenClawのセットアップがカレンダー、メール、リサーチ、コーディング、複数ステップのワークフローにどの程度対応しているかを確認する際に使用します。
openui
OpenUIとOpenUI Langを使用してジェネレーティブUIアプリを構築できます。これらはLLM生成インターフェースのためのトークン効率的なオープン標準です。OpenUI、@openuidev、ジェネレーティブUI、LLMからのストリーミングUI、AI向けコンポーネントライブラリ、またはjson-render/A2UIの置き換えについて述べる際に使用します。スキャフォルディング、defineComponent、システムプロンプト、Renderer、およびOpenUI Lang出力のデバッグに対応しています。