Schéma de bloc & types de champs
Tous les types de champs, le builder defineBlock + fields, les options de champs, les repeaters et les options de select.
Tous les types de champs
Définissez les props éditables d'un bloc avec le builder fields.*() à l'intérieur de defineBlock. Chaque builder renvoie une définition de champ ; la clé que vous lui donnez dans props devient la clé de contenu.
| Builder | Description | Type de valeur |
|---|---|---|
fields.text() | Champ de texte sur une ligne | string |
fields.textarea() | Zone de texte multiligne | string |
fields.richText() | Éditeur WYSIWYG (Tiptap) | string (HTML) |
fields.markdown() | Éditeur Markdown | string (Markdown) |
fields.number() | Champ numérique | number |
fields.date() | Sélecteur de date | string (ISO date) |
fields.datetime() | Sélecteur de date et heure | string (ISO) |
fields.boolean() | Interrupteur | boolean |
fields.color() | Sélecteur de couleur | string (hex) |
fields.media() | Téléversement d'image/vidéo | ResolvedMedia ou ResolvedMedia[] |
fields.link() | Lien interne/externe | string |
fields.url() | Champ URL | string |
fields.email() | Champ e-mail | string |
fields.select() | Liste déroulante (choix unique) | string |
fields.radio() | Groupe radio (choix unique) | string |
fields.multiselect() | Choix multiple | string[] |
fields.relation() | Référencer des enregistrements d'un modèle | record or record[] |
fields.repeater() | Tableau de groupes de champs imbriqués | object[] |
fields.table() | Grille de tableau éditable | { columns, rows } |
fields.json() | Éditeur JSON brut | JSON value |
fields.form() | Choisir un formulaire Cmssy | string (form id) |
fields.pageSelector() | Choisir une ou des pages | PageRef[] |
La plupart des builders n'acceptent que les options de base ci-dessous. fields.select(), fields.radio() et fields.multiselect() exigent un tableau options ; fields.media() accepte multiple ; fields.relation() a besoin d'un model (le slug du modèle référencé) et, en option, de mode: "all", multiple, sort et limit. Une relation stocke le ou les id d'enregistrement ; l'API de delivery les résout en enregistrements complets avant le rendu de votre composant.
Définir un bloc
Un bloc se déclare avec defineBlock. Ses champs éditables se trouvent sous props :
import { defineBlock, fields } from "@cmssy/react";
import Hero from "./Hero";
export const heroProps = {
heading: fields.text({ label: "Heading", required: true, defaultValue: "Welcome" }),
description: fields.textarea({ label: "Description" }),
};
export const heroBlock = defineBlock({
type: "hero",
label: "Hero",
component: Hero,
props: heroProps,
});
Exportez l'objet props séparément et typez le composant à partir de lui - BlockProps<typeof heroProps> - ainsi le schéma reste le seul endroit où un champ est nommé, et les types de valeur du tableau ci-dessus deviennent ceux que voit votre composant. Voir Développement de blocs.
Options de champs
Chaque builder fields.*() accepte les mêmes options de base :
fields.text({
label: "Heading",
required: true,
defaultValue: "Welcome",
placeholder: "Enter text",
helperText: "Main heading",
})
Clés disponibles : label, required, defaultValue, placeholder, helperText, localized. Les champs select et repeater en ajoutent quelques-unes (ci-dessous).
Champs identiques dans toutes les langues
Par défaut, chaque champ est traduit : chaque langue conserve sa propre valeur. Un champ qui doit contenir une seule valeur pour tout le site - un logo, une photo produit, une couleur de marque - déclare localized: false :
props: {
logo: fields.media({ label: "Logo", localized: false }),
heading: fields.text({ label: "Heading" }),
}
L'éditeur affiche un tel champ une seule fois, avec un cadenas, quelle que soit la langue en cours d'édition ; le modifier le modifie pour toutes les langues. L'API de delivery le renvoie toujours dans le contenu de chaque langue, votre composant lit donc content.logo exactement comme avant - rien ne change côté consommateur.
localized est indépendant de tab : un champ sur l'onglet style ou advanced est déjà une valeur par bloc, le drapeau n'y apporte rien. Basculer le drapeau sur un champ existant déplace la valeur stockée lors du prochain envoi du manifeste. Nécessite @cmssy/core 16.4.0 ou plus récent.
Select & Multiselect
Les options sont un simple tableau de chaînes :
props: {
layout: fields.select({
label: "Layout",
options: ["grid", "list", "carousel"],
defaultValue: "grid",
}),
tags: fields.multiselect({
label: "Tags",
options: ["featured", "new"],
}),
}
Repeater (tableaux)
Utilisez itemSchema — une map de fields.*() imbriqués — pour décrire chaque ligne :
props: {
features: fields.repeater({
label: "Features",
maxItems: 6,
itemSchema: {
icon: fields.text({ label: "Icon Name", defaultValue: "Star" }),
title: fields.text({ label: "Title", required: true }),
description: fields.textarea({ label: "Description" }),
},
}),
}
Dans votre composant :
export default function Features({ content }) {
return (
<div className="grid grid-cols-3 gap-6">
{(content.features ?? []).map((f, i) => (
<div key={i}><h3>{f.title}</h3><p>{f.description}</p></div>
))}
</div>
);
}
Le repeater prend aussi en charge itemLabel, addButtonLabel, minItems, maxItems et collapsible.