Block Kit

Sur cette page

Le Block Kit d’EmDash permet aux plugins sandboxés de décrire leur interface d’administration en JSON. L’hôte rend les blocs — aucun JavaScript fourni par le plugin ne s’exécute jamais dans le navigateur.

Comment ça fonctionne

  1. L’utilisateur navigue vers la page d’administration d’un plugin.
  2. L’administrateur envoie une interaction page_load à la route d’administration du plugin.
  3. Le plugin retourne une BlockResponse contenant un tableau de blocs.
  4. L’administrateur rend les blocs en utilisant le composant BlockRenderer.
  5. Lorsque l’utilisateur interagit (clique sur un bouton, soumet un formulaire), l’administrateur renvoie l’interaction au plugin.
  6. Le plugin retourne de nouveaux blocs, et le cycle se répète.
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;

Le gestionnaire de route prend deux arguments : routeCtx (avec input, request, requestMeta) et ctx (le PluginContext). satisfies SandboxedPlugin infère les deux.

Types de blocs

TypeDescription
headerGrand titre en gras
sectionTexte avec élément accessoire optionnel
dividerLigne horizontale
fieldsGrille à deux colonnes étiquette/valeur
tableTableau de données avec formatage, tri, pagination
actionsRangée horizontale de boutons et contrôles
statsCartes de métriques de tableau de bord avec indicateurs de tendance
formChamps de saisie avec visibilité conditionnelle et soumission
imageImage au niveau du bloc avec légende
contextPetit texte d’aide discret
columnsDisposition en 2–3 colonnes avec blocs imbriqués
emptyEspace réservé d’état vide avec icône, titre, description, ligne de commande optionnelle et boutons d’action
accordionSection repliable enveloppant des blocs imbriqués

Types d’éléments

TypeDescription
buttonBouton d’action avec dialogue de confirmation optionnel
text_inputSaisie de texte sur une seule ligne ou multiligne
number_inputSaisie numérique avec min/max
selectSélection déroulante
toggleInterrupteur marche/arrêt
secret_inputSaisie masquée pour les clés API et les jetons

Aides à la construction

Le package @emdash-cms/blocks exporte des aides à la construction pour un code plus propre :

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" },
		}),
	],
};

Champs conditionnels

Les champs de formulaire peuvent être affichés conditionnellement en fonction des valeurs d’autres champs :

{
	"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 }
}

Le champ api_key n’apparaît que lorsque auth_enabled est activé. Les conditions sont évaluées côté client sans aller-retour.

Essayez-le

Utilisez le Block Playground pour créer et tester des mises en page de blocs de manière interactive.