Field Kit

Sur cette page

Le type de champ json d’EmDash stocke des données structurées arbitraires, mais l’éditeur par défaut est une saisie de texte sur une seule ligne où vous devez taper du JSON brut à la main. Field Kit est un plugin de première partie qui fournit quatre widgets composables pour les champs json, entièrement configurés via les options de seed — aucun React requis pour les créateurs de sites.

Installation

npm i @emdash-cms/plugin-field-kit

Enregistrez le plugin dans astro.config.mjs :

import { defineConfig } from "astro/config";
import emdash from "emdash";
import { fieldKitPlugin } from "@emdash-cms/plugin-field-kit";

export default defineConfig({
	integrations: [
		emdash({
			plugins: [fieldKitPlugin()],
		}),
	],
});

Ensuite, attachez un widget à n’importe quel champ json en définissant widget sur field-kit:<name> :

{
	"slug": "ingredients",
	"type": "json",
	"widget": "field-kit:list",
	"options": { "fields": [...] }
}

Widgets

WidgetUtiliser pourValeur stockée
object-formFormulaire en ligne pour objets JSON plats{ key: value, ... }
listÉditeur de tableau ordonné avec ajouter / supprimer / réorganiser[{ ... }, ...]
gridMatrice lignes × colonnes{ rowKey: { colKey: value } }
tagsSaisie de chip/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 saisie cassée — utile lors de l’itération sur les schémas de seed.

object-form

Affiche un groupe de sous-champs typés qui sont stockés comme un seul objet JSON. Bon pour les données structurées de forme fixe comme les valeurs nutritionnelles ou les informations de contact.

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

OptionTypePar défautDescription
fieldsSubFieldDef[](requis)Définitions de sous-champs — voir Sous-champs.
collapsedbooleanfalseAfficher le groupe réduit par défaut.
helpTextstringTexte 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 type Mustache.

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

Valeur stockée :

[
	{ "name": "Flour", "amount": "500g", "optional": false },
	{ "name": "Butter", "amount": "200g", "optional": false }
]
OptionTypePar défautDescription
fieldsSubFieldDef[](requis)Définitions de sous-champs pour chaque ligne.
itemLabelstring"Item"Étiquette au singulier pour une ligne (utilisée dans le bouton “Ajouter” et les titres de ligne de secours).
minnumberNombre minimum d’éléments. En dessous, le bouton de suppression est masqué.
maxnumberNombre maximum d’éléments. À ce nombre, le bouton d’ajout est masqué.
sortablebooleantrueAfficher les boutons de réorganisation haut/bas.
summarystringModèle Mustache rendu comme titre de ligne réduite. Voir Modèles de résumé.
helpTextstringTexte d’aide affiché sous le widget.

grid

Une matrice bidimensionnelle de lignes × colonnes. Chaque cellule peut être un interrupteur, une saisie de texte, une saisie 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.

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

Valeur stockée :

{
	"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 }
}
OptionTypePar défautDescription
rowsGridAxisDef[](requis)Définitions de lignes : { key, label, image? }.
columnsGridAxisDef[](requis)Définitions de colonnes : { key, label, image? }.
cell"toggle" | "text" | "number" | "select""toggle"Type de saisie de cellule, appliqué uniformément à chaque cellule.
cellOptionsstring[] | Array<{ label, value }>[]Requis lorsque cell est "select".
helpTextstringTexte d’aide affiché sous le widget.

tags

Une saisie de type chip pour les tableaux de chaînes. Prend en charge une liste fixe de suggestions, des valeurs personnalisées en forme libre (basculables), des transformations de casse et un max optionnel.

{
	"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 une étiquette. Backspace sur une saisie vide supprime la dernière étiquette. Les étiquettes en double sont silencieusement ignorées.

OptionTypePar défautDescription
placeholderstring"Add..."Espace réservé de saisie affiché lorsqu’il n’y a pas d’étiquettes présentes.
maxnumberNombre maximum d’étiquettes. La saisie est masquée à la limite.
suggestionsstring[][]Suggestions d’autocomplétion affichées via une <datalist>.
allowCustombooleantrueLorsque false, seules les valeurs de suggestions peuvent être ajoutées.
transform"none" | "lowercase" | "uppercase" | "trim""none"Normaliser les étiquettes au fur et à mesure qu’elles sont ajoutées.
helpTextstringTexte 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-champRendu en tant queExtras notables
textSaisie sur une seule ligneplaceholder
textareaSaisie sur plusieurs lignesrows (par défaut 3), placeholder
numberSaisie numériquemin, max, step, prefix, suffix, placeholder
booleanInterrupteur
selectListe déroulanteoptions: string[] | Array<{ label, value }>, placeholder
dateSaisie de date
colorSélecteur de couleur natif associé à une saisie de texte hexadécimal
urlSaisie d’URL (HTML5 type="url")placeholder

Props communes sur chaque sous-champ : required, helpText, defaultValue.

Modèles de résumé

Le widget list affiche chaque ligne réduite à l’aide d’un modèle de type Mustache dans options.summary. {{key}} est remplacé par la valeur de la ligne pour cette clé (convertie en chaîne). Les valeurs falsy reviennent à "{itemLabel} {n}".

"summary": "{{name}} — {{amount}}"

Affiche les lignes comme Flour — 500g. Le modèle est une simple substitution de chaîne — 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. Il n’y a pas de tables spécifiques au plugin, pas de clés étrangères, pas de mutation de schéma. Si vous supprimez @emdash-cms/plugin-field-kit de votre configuration, les données restent valides — seule l’interface utilisateur d’édition revient à la saisie 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 ensemble de champs plus ancien.

Voir aussi