mcpField
V
vue

vue

github.com/vercel-labs開発18.8k1.4k 回インストール1 日前に更新
リポジトリ

vue について

@json-render/vueは、JSON仕様をVue 3のコンポーネントツリーに変換します。Vueでデータ駆動型UIを構築する開発者向けで、状態、アクション、表示条件、検証に対応し、外部ストアにも接続できます。

主な機能

  1. 01JSON仕様をVueコンポーネントツリーに変換
  2. 02状態バインディングと動的プロパティ式
  3. 03アクション・表示条件・検証のコンテキスト
  4. 04独自コンポーネントと名前付きスロットの登録
  5. 05外部状態ストアへの接続
  6. 06UI仕様のストリーミング

活用シーン

  1. 01VueアプリでJSONの画面仕様を描画
  2. 02状態に応じた表示制御とプロパティのバインド
  3. 03フォーム検証とコンポーネントアクションの処理
  4. 04APIからUI仕様をストリーム受信

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/vercel-labs/json-render --skill vue

インストール後、Claude Code で/vueを入力して読み込まれたか確認します。

詳細

@json-render/vue

JSON 仕様をデータバインディング、表示制御、アクションに対応した Vue コンポーネントツリーに変換する Vue 3 レンダラーです。

インストール

npm install @json-render/vue @json-render/core zod

ピア依存関係:vue ^3.5.0 と zod ^4.0.0。

クイックスタート

カタログを作成する
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() }),
      slots: ["default"],
      description: "A card container",
    },
    Layout: {
      props: z.object({}),
      slots: ["default", "header", "footer"],
      description: "Layout with named content regions",
    },
    Button: {
      props: z.object({ label: z.string(), action: z.string() }),
      description: "A clickable button",
    },
  },
  actions: {},
});
h() レンダー関数でレジストリを定義する
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,
      ]),
    Layout: ({ slots }) =>
      h("div", null, [
        h("header", null, slots.header?.()),
        h("main", null, slots.default?.()),
        h("footer", null, slots.footer?.()),
      ]),
    Button: ({ props, emit }) =>
      h("button", { onClick: () => emit("press") }, props.label),
  },
});

名前付きスロット

"default" スロットには children を使用します。カタログで宣言したその他のスロット名には、要素のトップレベルにある slots オブジェクトを使用します。

{
  "type": "Layout",
  "props": {},
  "children": ["main"],
  "slots": {
    "header": ["heading"],
    "footer": ["actions"]
  }
}

レジストリのコンポーネントには、Vue ネイティブのスロット関数が渡されます。slots.header?.()、slots.footer?.() などを使ってレンダリングします。slots.default?.() は仕様の children をレンダリングします。children コンテキストフィールドは、そのレンダリング結果を参照するための便利なエイリアスです。JSON 仕様では、デフォルトのコンテンツは children に記述し、slots に default エントリーを追加しないでください。

仕様をレンダリングする
<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>

プロバイダー

プロバイダー目的
StateProviderコンポーネント間で状態を共有します(JSON Pointer パス)。制御モードでは initialState または store を受け取ります。
ActionProviderイベントシステム経由でディスパッチされたアクションを処理します
VisibilityProvider状態に基づく条件付きレンダリングを有効にします
ValidationProviderフォームフィールドの検証を行います

コンポーザブル

コンポーザブル目的
useStateStore()状態コンテキストにアクセスします(state は ShallowRef、get、set、update)
useStateValue(path)状態から単一の値を取得します
useIsVisible(condition)表示条件を満たしているか確認します
useActions()アクションコンテキストにアクセスします
useAction(binding)単一のアクションディスパッチ関数を取得します
useFieldValidation(path, config)フィールドの検証状態
useBoundProp(propValue, bindingPath)$bindState/$bindItem の双方向バインディング

注:useStateStore().state は ShallowRef<StateModel> を返します。アクセスするには state.value を使用してください。

外部ストア(StateStore)

入れ子になったリストでは、外側の repeat 内で repeat.statePath に { "$item": "field" } を設定できます。

StateStore を StateProvider に渡すと、json-render を Pinia、VueUse、または任意の状態管理機能に接続できます。

import { createStateStore, type StateStore } from "@json-render/vue";

const store = createStateStore({ count: 0 });
<StateProvider :store="store">
  <Renderer :spec="spec" :registry="registry" />
</StateProvider>

動的なプロパティ式

プロパティは $state、$bindState、$cond、$template、$computed をサポートします。双方向バインディングには、自然な値プロパティに { "$bindState": "/path" } を指定します。

表示条件

{ "$state": "/user/isAdmin" }
{ "$state": "/status", "eq": "active" }
{ "$state": "/maintenance", "not": true }
[ cond1, cond2 ]  // implicit AND

組み込みアクション

setState、pushState、removeState、validateForm は Vue スキーマに組み込まれており、ActionProvider によって処理されます。

{
  "action": "setState",
  "params": { "statePath": "/activeTab", "value": "settings" }
}

イベントシステム

コンポーネントは emit(event) を使ってイベントを発行するか、on(event) を使ってメタデータ(shouldPreventDefault、bound)を取得します。

ストリーミング

useUIStream と useChatUI は、API からストリーミングされる仕様に対応する Vue Ref を返します。

BaseComponentProps

カタログに依存しない再利用可能なコンポーネント向けです。

import type { BaseComponentProps } from "@json-render/vue";

const Card = ({ props, children }: BaseComponentProps<{ title?: string }>) =>
  h("div", null, [props.title, children]);

主なエクスポート

エクスポート目的
defineRegistryカタログから型安全なコンポーネントレジストリを作成します
Rendererレジストリを使用して仕様をレンダリングします
schema要素ツリーのスキーマ(@json-render/vue/schema から)
StateProvider、ActionProvider、VisibilityProvider、ValidationProviderコンテキストプロバイダー
useStateStore、useStateValue、useBoundProp状態コンポーザブル
useActions、useActionアクションコンポーザブル
useFieldValidation、useIsVisible検証と表示制御
useUIStream、useChatUIストリーミング用コンポーザブル
createStateStoreインメモリの StateStore を作成します
BaseComponentPropsカタログに依存しないコンポーネントのプロパティ型

コメント