El Block Kit de EmDash permite que los plugins sandboxed describan su interfaz de administración como JSON. El host renderiza los bloques — ningún JavaScript proporcionado por el plugin se ejecuta en el navegador.
Cómo funciona
- El usuario navega a la página de administración de un plugin.
- El admin envía una interacción
page_loada la ruta de administración del plugin. - El plugin devuelve una
BlockResponseque contiene un array de bloques. - El admin renderiza los bloques usando el componente
BlockRenderer. - Cuando el usuario interactúa (hace clic en un botón, envía un formulario), el admin envía la interacción de vuelta al plugin.
- El plugin devuelve nuevos bloques y el ciclo se repite.
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: [] };
},
},
},
});
El manejador de ruta en formato estándar toma dos argumentos: routeCtx (con input, request, requestMeta) y ctx (el PluginContext).
Tipos de bloques
| Type | Description |
|---|---|
header | Encabezado grande en negrita |
section | Texto con elemento accesorio opcional |
divider | Regla horizontal |
fields | Cuadrícula de etiqueta/valor de dos columnas |
table | Tabla de datos con formateo, ordenación, paginación |
actions | Fila horizontal de botones y controles |
stats | Tarjetas de métricas de dashboard con indicadores de tendencia |
form | Campos de entrada con visibilidad condicional y envío |
image | Imagen a nivel de bloque con leyenda |
context | Texto de ayuda pequeño y atenuado |
columns | Diseño de 2–3 columnas con bloques anidados |
empty | Marcador de posición de estado vacío con icono, título, descripción, línea de comando opcional y botones de acción |
accordion | Sección colapsable que envuelve bloques anidados |
Tipos de elementos
| Type | Description |
|---|---|
button | Botón de acción con diálogo de confirmación opcional |
text_input | Entrada de texto de una línea o multilínea |
number_input | Entrada numérica con mín/máx |
select | Selección desplegable |
toggle | Interruptor de encendido/apagado |
secret_input | Entrada enmascarada para claves API y tokens |
Ayudantes de constructor
El paquete @emdash-cms/blocks exporta ayudantes de constructor para código más limpio:
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 condicionales
Los campos de formulario pueden mostrarse condicionalmente según los valores de otros 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 }
}
El campo api_key solo aparece cuando auth_enabled está activado. Las condiciones se evalúan del lado del cliente sin ida y vuelta.
Pruébalo
Usa el Block Playground para construir y probar diseños de bloques de forma interactiva.