Block Kit

En esta página

Block Kit de EmDash permite a los plugins en sandbox describir su UI de administración como JSON. El host renderiza los bloques — nunca se ejecuta JavaScript proporcionado por el plugin en el navegador.

Cómo funciona

  1. El usuario navega a la página de administración de un plugin.
  2. El administrador envía una interacción page_load a la ruta de administración del plugin.
  3. El plugin devuelve una BlockResponse que contiene un array de bloques.
  4. El administrador renderiza los bloques usando el componente BlockRenderer.
  5. Cuando el usuario interactúa (hace clic en un botón, envía un formulario), el administrador envía la interacción de vuelta al plugin.
  6. El plugin devuelve nuevos bloques, y el ciclo se repite.
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;

El manejador de ruta toma dos argumentos: routeCtx (con input, request, requestMeta) y ctx (el PluginContext). satisfies SandboxedPlugin infiere ambos.

Tipos de bloques

TipoDescripción
headerEncabezado grande en negrita
sectionTexto con elemento accesorio opcional
dividerLínea horizontal
fieldsCuadrícula de dos columnas de etiqueta/valor
tableTabla de datos con formato, ordenación, paginación
actionsFila horizontal de botones y controles
statsTarjetas de métricas de dashboard con indicadores de tendencia
formCampos de entrada con visibilidad condicional y envío
imageImagen a nivel de bloque con leyenda
contextTexto de ayuda pequeño y discreto
columnsDiseño de 2–3 columnas con bloques anidados
emptyMarcador de posición de estado vacío con icono, título, descripción, línea de comandos opcional y botones de acción
accordionSección plegable que envuelve bloques anidados

Tipos de elementos

TipoDescripción
buttonBotón de acción con diálogo de confirmación opcional
text_inputEntrada de texto de una línea o multilínea
number_inputEntrada numérica con mín/máx
selectSelección desplegable
toggleInterruptor de encendido/apagado
secret_inputEntrada enmascarada para claves API y tokens

Helpers de construcción

El paquete @emdash-cms/blocks exporta helpers de construcción 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 en el lado del cliente sin ida y vuelta.

Pruébalo

Use el Block Playground para construir y probar diseños de bloques de forma interactiva.