O Block Kit do EmDash permite que plugins sandboxed descrevam sua interface de administração como JSON. O host renderiza os blocos — nenhum JavaScript fornecido pelo plugin é executado no navegador.
Como funciona
- O usuário navega para a página de administração de um plugin.
- O admin envia uma interação
page_loadpara a rota de administração do plugin. - O plugin retorna uma
BlockResponsecontendo um array de blocos. - O admin renderiza os blocos usando o componente
BlockRenderer. - Quando o usuário interage (clica em um botão, envia um formulário), o admin envia a interação de volta para o plugin.
- O plugin retorna novos blocos e o ciclo se repete.
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: [] };
},
},
},
});
O manipulador de rota em formato padrão aceita dois argumentos: routeCtx (com input, request, requestMeta) e ctx (o PluginContext).
Tipos de blocos
| Type | Description |
|---|---|
header | Título grande em negrito |
section | Texto com elemento acessório opcional |
divider | Linha horizontal |
fields | Grade de rótulo/valor de duas colunas |
table | Tabela de dados com formatação, ordenação, paginação |
actions | Linha horizontal de botões e controles |
stats | Cartões de métricas do painel com indicadores de tendência |
form | Campos de entrada com visibilidade condicional e envio |
image | Imagem em nível de bloco com legenda |
context | Texto de ajuda pequeno e esmaecido |
columns | Layout de 2–3 colunas com blocos aninhados |
empty | Espaço reservado de estado vazio com ícone, título, descrição, linha de comando opcional e botões de ação |
accordion | Seção recolhível que envolve blocos aninhados |
Tipos de elementos
| Type | Description |
|---|---|
button | Botão de ação com diálogo de confirmação opcional |
text_input | Entrada de texto de linha única ou multilinha |
number_input | Entrada numérica com mín/máx |
select | Seleção suspensa |
toggle | Interruptor ligar/desligar |
secret_input | Entrada mascarada para chaves de API e tokens |
Auxiliares de construtor
O pacote @emdash-cms/blocks exporta auxiliares de construtor para código mais limpo:
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" },
}),
],
};
Campos condicionais
Campos de formulário podem ser exibidos condicionalmente com base em valores de outros campos:
{
"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 }
}
O campo api_key só aparece quando auth_enabled está ativado. As condições são avaliadas no lado do cliente sem ida e volta.
Experimente
Use o Block Playground para construir e testar layouts de blocos de forma interativa.