Block Kit

En esta página

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

  1. El usuario navega a la página de administración de un plugin.
  2. El admin 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 admin renderiza los bloques usando el componente BlockRenderer.
  5. 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.
  6. 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

TypeDescription
headerEncabezado grande en negrita
sectionTexto con elemento accesorio opcional
dividerRegla horizontal
fieldsCuadrícula de etiqueta/valor de dos columnas
tableTabla de datos con formateo, 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 atenuado
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 comando opcional y botones de acción
accordionSección colapsable que envuelve bloques anidados

Tipos de elementos

TypeDescription
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

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.