Il Block Kit di EmDash consente ai plugin in sandbox di descrivere la loro interfaccia di amministrazione come JSON. L’host renderizza i blocchi — nessun JavaScript fornito dal plugin viene mai eseguito nel browser.
Come funziona
- L’utente naviga alla pagina di amministrazione di un plugin.
- L’amministratore invia un’interazione
page_loadalla route di amministrazione del plugin. - Il plugin restituisce una
BlockResponsecontenente un array di blocchi. - L’amministratore renderizza i blocchi utilizzando il componente
BlockRenderer. - Quando l’utente interagisce (clicca un pulsante, invia un modulo), l’amministratore invia l’interazione al plugin.
- Il plugin restituisce nuovi blocchi, e il ciclo si ripete.
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;
Il gestore della route accetta due argomenti: routeCtx (con input, request, requestMeta) e ctx (il PluginContext). satisfies SandboxedPlugin deduce entrambi.
Tipi di blocchi
| Tipo | Descrizione |
|---|---|
header | Intestazione grande in grassetto |
section | Testo con elemento accessorio opzionale |
divider | Linea orizzontale |
fields | Griglia a due colonne etichetta/valore |
table | Tabella dati con formattazione, ordinamento, paginazione |
actions | Riga orizzontale di pulsanti e controlli |
stats | Carte metriche dashboard con indicatori di tendenza |
form | Campi di input con visibilità condizionale e invio |
image | Immagine a livello di blocco con didascalia |
context | Piccolo testo di aiuto discreto |
columns | Layout a 2–3 colonne con blocchi nidificati |
empty | Segnaposto stato vuoto con icona, titolo, descrizione, riga di comando opzionale e pulsanti di azione |
accordion | Sezione comprimibile che avvolge blocchi nidificati |
Tipi di elementi
| Tipo | Descrizione |
|---|---|
button | Pulsante di azione con dialogo di conferma opzionale |
text_input | Input di testo a riga singola o multilinea |
number_input | Input numerico con min/max |
select | Selezione a discesa |
toggle | Interruttore on/off |
secret_input | Input mascherato per chiavi API e token |
Helper di costruzione
Il pacchetto @emdash-cms/blocks esporta helper di costruzione per codice più pulito:
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" },
}),
],
};
Campi condizionali
I campi del modulo possono essere visualizzati condizionalmente in base ai valori di altri campi:
{
"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 }
}
Il campo api_key appare solo quando auth_enabled è attivato. Le condizioni vengono valutate lato client senza round-trip.
Provalo
Usa il Block Playground per costruire e testare layout di blocchi in modo interattivo.