EmDash의 Block Kit을 사용하면 샌드박스 플러그인이 관리 UI를 JSON으로 설명할 수 있습니다. 호스트가 블록을 렌더링하며 플러그인이 제공하는 JavaScript는 브라우저에서 실행되지 않습니다.
작동 방식
- 사용자가 플러그인의 관리 페이지로 이동합니다.
- 관리자가 플러그인의 관리 경로로
page_load상호작용을 보냅니다. - 플러그인이 블록 배열을 포함하는
BlockResponse를 반환합니다. - 관리자가
BlockRenderer컴포넌트를 사용하여 블록을 렌더링합니다. - 사용자가 상호작용(버튼 클릭, 폼 제출)하면 관리자가 상호작용을 플러그인으로 다시 보냅니다.
- 플러그인이 새 블록을 반환하고 사이클이 반복됩니다.
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: [] };
},
},
},
});
표준 형식 경로 핸들러는 두 개의 인수를 받습니다: routeCtx(input, request, requestMeta 포함)와 ctx(PluginContext).
블록 타입
| Type | Description |
|---|---|
header | 크고 굵은 제목 |
section | 선택적 액세서리 요소가 있는 텍스트 |
divider | 수평선 |
fields | 2열 레이블/값 그리드 |
table | 포맷팅, 정렬, 페이지네이션이 있는 데이터 테이블 |
actions | 버튼과 컨트롤의 수평 행 |
stats | 추세 지표가 있는 대시보드 메트릭 카드 |
form | 조건부 표시 및 제출이 있는 입력 필드 |
image | 캡션이 있는 블록 레벨 이미지 |
context | 작고 음소거된 도움말 텍스트 |
columns | 중첩된 블록이 있는 2~3열 레이아웃 |
empty | 아이콘, 제목, 설명, 선택적 명령줄 및 액션 버튼이 있는 빈 상태 플레이스홀더 |
accordion | 중첩된 블록을 감싸는 접을 수 있는 섹션 |
요소 타입
| Type | Description |
|---|---|
button | 선택적 확인 대화상자가 있는 액션 버튼 |
text_input | 단일 줄 또는 여러 줄 텍스트 입력 |
number_input | 최소/최대값이 있는 숫자 입력 |
select | 드롭다운 선택 |
toggle | 켜기/끄기 스위치 |
secret_input | API 키와 토큰용 마스크된 입력 |
빌더 헬퍼
@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를 사용하여 블록 레이아웃을 대화형으로 빌드하고 테스트하세요.