Le type de champ json d’EmDash stocke des données structurées arbitraires, éditées par défaut via une entrée de texte sur une seule ligne qui accepte du JSON brut. Field Kit est un plugin officiel qui fournit quatre widgets composables pour les champs json, configurés entièrement via les options de seed afin que les constructeurs de sites puissent les utiliser avec le schéma de seed seul.
Installation
Installez le package depuis npm :
npm i @emdash-cms/plugin-field-kit
La configuration suivante enregistre le plugin :
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { fieldKitPlugin } from "@emdash-cms/plugin-field-kit";
export default defineConfig({
integrations: [
emdash({
plugins: [fieldKitPlugin()],
}),
],
});
Attachez un widget à n’importe quel champ json en définissant widget sur field-kit:<name>. La définition de champ suivante utilise le widget list :
{
"slug": "ingredients",
"type": "json",
"widget": "field-kit:list",
"options": { "fields": [...] }
}
Widgets
| Widget | Utilisation | Valeur stockée |
|---|---|---|
object-form | Formulaire en ligne pour les objets JSON plats | { key: value, ... } |
list | Éditeur de tableau ordonné avec ajout / suppression / réorganisation | [{ ... }, ...] |
grid | Matrice lignes × colonnes | { rowKey: { colKey: value } } |
tags | Entrée de puce/tag en forme libre | ["tag1", "tag2"] |
Si un widget manque ses options requises (par exemple fields pour object-form/list, ou rows/columns pour grid), l’éditeur affiche un avertissement en ligne “Widget mal configuré” au lieu d’une entrée cassée — utile lors de l’itération sur les schémas de seed.
object-form
Rend un groupe de sous-champs typés qui se stockent comme un seul objet JSON. Bon pour les données structurées de forme fixe comme les informations nutritionnelles ou de contact. La définition de champ suivante configure un objet nutritionnel :
{
"slug": "nutrition",
"type": "json",
"widget": "field-kit:object-form",
"options": {
"collapsed": false,
"fields": [
{ "key": "calories", "label": "Calories", "type": "number", "suffix": "kcal" },
{ "key": "protein", "label": "Protein", "type": "number", "suffix": "g" },
{ "key": "fat", "label": "Fat", "type": "number", "suffix": "g" },
{ "key": "carbs", "label": "Carbs", "type": "number", "suffix": "g" }
]
}
}
Valeur stockée : { "calories": 250, "protein": 12.5, "fat": 8, "carbs": 30 }.
| Option | Type | Par défaut | Description |
|---|---|---|---|
fields | SubFieldDef[] | (requis) | Définitions de sous-champs — voir Sous-champs. |
collapsed | boolean | false | Rendre le groupe replié par défaut. |
helpText | string | — | Texte d’aide affiché sous le widget. |
list
Un éditeur de tableau ordonné avec des contrôles d’ajout, de suppression et de réorganisation. Chaque ligne est un objet JSON dont la forme est définie par fields. L’en-tête de ligne affiche un résumé rendu à partir d’un modèle de style Mustache. La définition de champ suivante configure une liste d’ingrédients :
{
"slug": "ingredients",
"type": "json",
"widget": "field-kit:list",
"options": {
"itemLabel": "Ingredient",
"min": 1,
"max": 50,
"sortable": true,
"summary": "{{name}} — {{amount}}",
"fields": [
{ "key": "name", "label": "Name", "type": "text", "required": true },
{ "key": "amount", "label": "Amount", "type": "text" },
{ "key": "optional", "label": "Optional", "type": "boolean" }
]
}
}
La valeur stockée est un tableau d’objets de ligne :
[
{ "name": "Flour", "amount": "500g", "optional": false },
{ "name": "Butter", "amount": "200g", "optional": false }
]
| Option | Type | Par défaut | Description |
|---|---|---|---|
fields | SubFieldDef[] | (requis) | Définitions de sous-champs pour chaque ligne. |
itemLabel | string | "Item" | Étiquette au singulier pour une ligne (utilisée dans le bouton “Ajouter” et les titres de ligne de secours). |
min | number | — | Nombre minimum d’éléments. En dessous, le bouton de suppression se cache. |
max | number | — | Nombre maximum d’éléments. À ce nombre, le bouton d’ajout se cache. |
sortable | boolean | true | Afficher les boutons de réorganisation haut/bas. |
summary | string | — | Modèle Mustache rendu comme titre de ligne repliée. Voir Modèles de résumé. |
helpText | string | — | Texte d’aide affiché sous le widget. |
grid
Une matrice bidimensionnelle de lignes × colonnes. Chaque cellule peut être un interrupteur, une entrée de texte, une entrée numérique ou une sélection. Utile pour les matrices comme la disponibilité saisonnière, les tableaux de prix ou les comparaisons de fonctionnalités. La définition de champ suivante configure une grille de disponibilité saisonnière :
{
"slug": "availability",
"type": "json",
"widget": "field-kit:grid",
"options": {
"cell": "toggle",
"rows": [
{ "key": "berries", "label": "Berries" },
{ "key": "stoneFruit", "label": "Stone fruit" },
{ "key": "citrus", "label": "Citrus" }
],
"columns": [
{ "key": "spring", "label": "Spring" },
{ "key": "summer", "label": "Summer" },
{ "key": "autumn", "label": "Autumn" },
{ "key": "winter", "label": "Winter" }
]
}
}
La valeur stockée est un objet indexé par ligne, puis par colonne :
{
"berries": { "spring": false, "summer": true, "autumn": false, "winter": false },
"stoneFruit": { "spring": false, "summer": true, "autumn": true, "winter": false },
"citrus": { "spring": false, "summer": false, "autumn": true, "winter": true }
}
| Option | Type | Par défaut | Description |
|---|---|---|---|
rows | GridAxisDef[] | (requis) | Définitions de lignes : { key, label, image? }. |
columns | GridAxisDef[] | (requis) | Définitions de colonnes : { key, label, image? }. |
cell | "toggle" | "text" | "number" | "select" | "toggle" | Type d’entrée de cellule, appliqué uniformément à chaque cellule. |
cellOptions | string[] | Array<{ label, value }> | [] | Requis quand cell est "select". |
helpText | string | — | Texte d’aide affiché sous le widget. |
tags
Une entrée de style puce pour les tableaux de chaînes. Prend en charge une liste fixe de suggestions, des valeurs personnalisées en forme libre (commutables), des transformations de casse et un max optionnel. La définition de champ suivante configure une entrée de tags de mots-clés :
{
"slug": "keywords",
"type": "json",
"widget": "field-kit:tags",
"options": {
"placeholder": "Add a keyword…",
"max": 10,
"transform": "lowercase",
"allowCustom": true,
"suggestions": ["vegan", "vegetarian", "gluten-free", "dairy-free", "nut-free"]
}
}
Valeur stockée : ["vegan", "gluten-free"].
Appuyez sur Enter ou , pour valider un tag. Backspace sur une entrée vide supprime le dernier tag. Les tags en double sont ignorés silencieusement.
| Option | Type | Par défaut | Description |
|---|---|---|---|
placeholder | string | "Add..." | Placeholder d’entrée affiché lorsqu’aucun tag n’est présent. |
max | number | — | Nombre maximum de tags. L’entrée se cache à la limite. |
suggestions | string[] | [] | Suggestions d’autocomplétion affichées via une <datalist>. |
allowCustom | boolean | true | Quand false, seules les valeurs de suggestions peuvent être ajoutées. |
transform | "none" | "lowercase" | "uppercase" | "trim" | "none" | Normaliser les tags au fur et à mesure qu’ils sont ajoutés. |
helpText | string | — | Texte d’aide affiché sous le widget. |
Sous-champs
object-form et list acceptent un tableau options.fields de définitions de sous-champs typés. Chaque entrée a une key (la clé d’objet JSON dans laquelle elle écrit), un label, un type et des extras spécifiques au type.
| Type de sous-champ | Rendu comme | Extras notables |
|---|---|---|
text | Entrée sur une ligne | placeholder |
textarea | Entrée multiligne | rows (par défaut 3), placeholder |
number | Entrée numérique | min, max, step, prefix, suffix, placeholder |
boolean | Interrupteur à bascule | — |
select | Menu déroulant | options: string[] | Array<{ label, value }>, placeholder |
date | Entrée de date | — |
color | Sélecteur de couleur natif associé à une entrée de texte hexadécimal | — |
url | Entrée URL (HTML5 type="url") | placeholder |
Propriétés communes à chaque sous-champ : required, helpText, defaultValue.
Modèles de résumé
Le widget list rend chaque ligne repliée en utilisant un modèle de style Mustache dans options.summary. {{key}} est remplacé par la valeur de la ligne pour cette clé (convertie en chaîne). Les valeurs fausses se replient sur "{itemLabel} {n}". Le modèle suivant combine deux clés :
"summary": "{{name}} — {{amount}}"
Rend des lignes comme Flour — 500g. Le modèle est une substitution de chaîne simple — pas de HTML, pas d’expressions imbriquées.
Durabilité des données
Les widgets Field Kit stockent du JSON simple dans la colonne existante du champ, en utilisant uniquement cette colonne. Si vous supprimez @emdash-cms/plugin-field-kit de votre configuration, les données restent valides — le champ revient à l’entrée de texte json par défaut.
Cela s’applique même lorsque vous modifiez la forme du widget : les clés inconnues sur les objets stockés sont préservées lors de la prochaine écriture, vous pouvez donc faire évoluer un schéma sans perdre les données capturées sous un ancien ensemble de champs.
Voir également
- Aperçu des plugins — comment fonctionnent les plugins EmDash.
- Choisir un format de plugin — écrivez vos propres widgets de champ si Field Kit ne convient pas.
- Discussion #571 — la proposition qui a conduit à ce plugin.