Block Kit

Nesta página

O Block Kit do EmDash permite que plugins em sandbox descrevam sua interface de administração como JSON. O host renderiza os blocos — nenhum JavaScript fornecido pelo plugin é executado no navegador.

Como funciona

  1. O usuário navega para a página de administração de um plugin.
  2. O administrador envia uma interação page_load para a rota de administração do plugin.
  3. O plugin retorna uma BlockResponse contendo um array de blocos.
  4. O administrador renderiza os blocos usando o componente BlockRenderer.
  5. Quando o usuário interage (clica em um botão, envia um formulário), o administrador envia a interação de volta para o plugin.
  6. O plugin retorna novos blocos, e o ciclo se repete.
import type { SandboxedPlugin } from "emdash/plugin";

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

export default {
	routes: {
		admin: {
			handler: async (routeCtx, ctx) => {
				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: [] };
			},
		},
	},
} satisfies SandboxedPlugin;

O manipulador de rota recebe dois argumentos: routeCtx (com input, request, requestMeta) e ctx (o PluginContext). satisfies SandboxedPlugin infere ambos.

Tipos de blocos

TipoDescrição
headerCabeçalho grande em negrito
sectionTexto com elemento acessório opcional
dividerLinha horizontal
fieldsGrade de duas colunas rótulo/valor
tableTabela de dados com formatação, ordenação, paginação
actionsLinha horizontal de botões e controles
statsCartões de métricas de painel com indicadores de tendência
formCampos de entrada com visibilidade condicional e envio
imageImagem em nível de bloco com legenda
contextPequeno texto de ajuda discreto
columnsLayout de 2–3 colunas com blocos aninhados
emptyEspaço reservado de estado vazio com ícone, título, descrição, linha de comando opcional e botões de ação
accordionSeção recolhível envolvendo blocos aninhados

Tipos de elementos

TipoDescrição
buttonBotão de ação com diálogo de confirmação opcional
text_inputEntrada de texto de linha única ou multilinha
number_inputEntrada numérica com mín/máx
selectSeleção suspensa
toggleInterruptor ligado/desligado
secret_inputEntrada mascarada para chaves de API e tokens

Auxiliares de construção

O pacote @emdash-cms/blocks exporta auxiliares de construção 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. 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.