Block Kit

このページ

EmDash の Block Kit を使用すると、サンドボックス化されたプラグインが管理 UI を JSON として記述できます。ホストがブロックをレンダリングし、プラグインが提供する JavaScript はブラウザで実行されることはありません。

仕組み

  1. ユーザーがプラグインの管理ページに移動します。
  2. 管理画面がプラグインの管理ルートに page_load インタラクションを送信します。
  3. プラグインがブロックの配列を含む BlockResponse を返します。
  4. 管理画面が BlockRenderer コンポーネントを使用してブロックをレンダリングします。
  5. ユーザーが操作(ボタンのクリック、フォームの送信)すると、管理画面がインタラクションをプラグインに送り返します。
  6. プラグインが新しいブロックを返し、サイクルが繰り返されます。
import { definePlugin } from "emdash";
import type { PluginContext } from "emdash";

interface BlockInteraction {
	type: "page_load" | "block_action" | "form_submit";
	page?: string;
	action_id?: string;
	values?: Record<string, unknown>;
}

export default definePlugin({
	routes: {
		admin: {
			handler: async (routeCtx, ctx: PluginContext) => {
				const interaction = routeCtx.input as BlockInteraction;

				if (interaction.type === "page_load") {
					return {
						blocks: [
							{ type: "header", text: "My Plugin Settings" },
							{
								type: "form",
								block_id: "settings",
								fields: [
									{ type: "text_input", action_id: "api_url", label: "API URL" },
									{ type: "toggle", action_id: "enabled", label: "Enabled", initial_value: true },
								],
								submit: { label: "Save", action_id: "save" },
							},
						],
					};
				}

				if (interaction.type === "form_submit" && interaction.action_id === "save") {
					await ctx.kv.set("settings", interaction.values);
					return {
						blocks: [/* ... updated blocks ... */],
						toast: { message: "Settings saved", type: "success" },
					};
				}

				return { blocks: [] };
			},
		},
	},
});

標準形式のルートハンドラーは 2 つの引数を取ります:routeCtxinputrequestrequestMeta を含む)と ctxPluginContext)。

ブロックタイプ

TypeDescription
header大きな太字の見出し
sectionオプションのアクセサリ要素を持つテキスト
divider水平線
fields2 列のラベル/値グリッド
tableフォーマット、ソート、ページネーション付きのデータテーブル
actionsボタンとコントロールの水平行
statsトレンドインジケーター付きのダッシュボードメトリックカード
form条件付き表示と送信を持つ入力フィールド
imageキャプション付きのブロックレベル画像
context小さなミュートされたヘルプテキスト
columnsネストされたブロックを持つ 2〜3 列レイアウト
emptyアイコン、タイトル、説明、オプションのコマンドライン、アクションボタンを持つ空状態プレースホルダー
accordionネストされたブロックをラップする折りたたみ可能なセクション

要素タイプ

TypeDescription
buttonオプションの確認ダイアログ付きアクションボタン
text_input単一行または複数行のテキスト入力
number_input最小値/最大値付きの数値入力
selectドロップダウン選択
toggleオン/オフスイッチ
secret_inputAPI キーとトークン用のマスクされた入力

ビルダーヘルパー

@emdash-cms/blocks パッケージは、よりクリーンなコードのためのビルダーヘルパーをエクスポートします:

import { blocks, elements } from "@emdash-cms/blocks";

const { header, form, section, stats } = blocks;
const { textInput, toggle, select, button } = elements;

return {
	blocks: [
		header("SEO Settings"),
		form({
			blockId: "settings",
			fields: [
				textInput("site_title", "Site Title", { initialValue: "My Site" }),
				toggle("generate_sitemap", "Generate Sitemap", { initialValue: true }),
				select("robots", "Default Robots", [
					{ label: "Index, Follow", value: "index,follow" },
					{ label: "No Index", value: "noindex,follow" },
				]),
			],
			submit: { label: "Save", actionId: "save" },
		}),
	],
};

条件付きフィールド

フォームフィールドは、他のフィールドの値に基づいて条件付きで表示できます:

{
	"type": "toggle",
	"action_id": "auth_enabled",
	"label": "Enable Authentication"
}
{
	"type": "secret_input",
	"action_id": "api_key",
	"label": "API Key",
	"condition": { "field": "auth_enabled", "eq": true }
}

api_key フィールドは auth_enabled がオンになっている場合にのみ表示されます。条件はラウンドトリップなしでクライアント側で評価されます。

試してみる

Block Playground を使用して、ブロックレイアウトをインタラクティブに構築およびテストします。