@clauzier/admin-kit (0.10.0)
Installation
@clauzier:registry=npm install @clauzier/admin-kit@0.10.0"@clauzier/admin-kit": "0.10.0"About this package
@clauzier/admin-kit
Back-office React Admin généré depuis les schémas servis par cms-core.
Une coquille cliente ne décrit que son identité : titre, palette, URL d'API.
Les ressources, les formulaires, les libellés, l'écran de réglages et le menu
viennent du contrat /api/content-schemas — un type de contenu déclaré côté
socle apparaît dans l'admin sans qu'une ligne y soit écrite.
Installation
bun add @clauzier/admin-kit
Les paquets react-admin, @mui/material, @mui/icons-material,
@api-platform/admin, @tanstack/react-query, react, react-dom et
react-router-dom sont des peerDependencies : deux instances de
react-admin dans un même bundle donnent deux contextes et plus rien ne
fonctionne. La coquille les déclare donc explicitement.
Utilisation
import { createRoot } from 'react-dom/client';
import { AdminKitApp } from '@clauzier/admin-kit/app';
import '@clauzier/admin-kit/styles/admin.css';
import './palette.css';
createRoot(document.getElementById('root')!).render(
<AdminKitApp
apiUrl="https://api.exemple.tld/api"
title="Mon Club"
subtitle="Espace d'administration"
tokenKey="monclub_admin_token"
palette={{
primary: '#4f7cff',
secondary: '#e63946',
light: {
background: '#f4f4f8',
paper: '#ffffff',
text: '#12121a',
textMuted: '#5c5c70',
border: '#dcdce6',
},
dark: {
background: '#0b0b10',
paper: '#14141c',
text: '#f2f2f5',
textMuted: '#8a8a99',
border: '#24242e',
},
fontBody: "'Inter', system-ui, sans-serif",
}}
/>,
);
Props de AdminKitApp
| Prop | Type | Défaut | Rôle |
|---|---|---|---|
apiUrl |
string |
— | point d'entrée de l'API (…/api) |
title |
string |
— | titre de l'admin et de l'écran de connexion |
subtitle |
string |
— | sous-titre de l'écran de connexion |
tokenKey |
string |
— | clé localStorage du jeton Sanctum |
palette |
AdminPalette |
— | couleurs de marque et surfaces des deux modes (voir Thème) |
defaultTheme |
'light' | 'dark' |
'dark' |
mode au premier chargement |
messages |
object |
{} |
surcharges de traduction, fusionnées avec celles du kit et de react-admin |
children |
ReactNode |
— | <Resource> et <CustomRoutes> supplémentaires, transmis tels quels |
dashboard |
DashboardComponent |
Dashboard |
composant de la page d'accueil |
menuExtras |
readonly MenuExtra[] |
[] |
entrées de menu ajoutées à une section (Administration par défaut) |
mediaPage |
boolean |
true |
page Médias (grille, téléversement, suppression, copie d'URL) |
Ce que le kit construit
- Tableau de bord (
/) : carte « Publication du site » (état de la reconstruction, bouton « Reconstruire le site », désactivé et expliqué quand le socle n'est pas configuré) et raccourcis vers chaque écran. La carte se masque face à un socle qui n'expose pasGET /site/rebuild. - Menu par sections : Pages / Contenu / Site / Administration. Un singleton
et un type
category: sitevont dans Site,category: contentdans Contenu ; sans catégorie,menurejoint Site et le reste Contenu. - Réglages (
/<type>pour chaque singleton, « Réglages du site » poursite) : un onglet par groupe du contrat, « Général » pour les champs sans groupe, création de la fiche à la première sauvegarde. - Textes d'interface (
ui: labels) : une ligne par clé avec sa description, le défaut en placeholder et les variables disponibles ; seules les surcharges non vides sont enregistrées. - Saisie libre à suggestions (
ui: suggest) : un champtextdont lesoptionsse proposent en liste déroulante sans fermer la saisie — toute autre valeur reste acceptée, et la valeur enregistrée revient à l'identique à la ré-ouverture. - Catalogue de rôles (
ui: roles) : liste{ slug, label, discord_role_id }éditée en lignes ; l'identifiant se dérive du libellé tant qu'il n'a pas été saisi à la main, un doublon bloque l'enregistrement. - Accès d'une page : section « Accès » de l'éditeur de pages, visibilité
publicoumembers, et pour cette dernière les rôles autorisés choisis dans le catalogue de la fiche Site (vide : tout membre connecté). - Écran Utilisateurs : mode de connexion (Discord ou mot de passe), présence
sur le serveur Discord, rôles attribués à la main (envoyés en
PUT /users/{id}sousroles) et rôles synchronisés depuis Discord en lecture seule. - Le toast « Contenu publié — le site sera reconstruit » ne promet une
reconstruction que si
GET /site/rebuildrépondconfigured: true.
Points d'extension
import { AdminKitApp, registerInput } from '@clauzier/admin-kit';
import { CustomRoutes, Resource } from 'react-admin';
import { Route } from 'react-router-dom';
import BarChartIcon from '@mui/icons-material/BarChart';
registerInput('color', (field, source) => <ColorInput source={source} label={field.label} />);
<AdminKitApp
{...identite}
dashboard={MonAccueil}
menuExtras={[{ label: 'Statistiques', to: '/stats', icon: <BarChartIcon /> }]}
>
<Resource name="commandes" list={CommandesList} />
<CustomRoutes>
<Route path="/stats" element={<Stats />} />
</CustomRoutes>
</AdminKitApp>;
registerInput(type, factory): un éditeur dédié pour untypeou unuide champ, sans patcher le socle.useAdminKit():apiUrl,token(),siteClient,menuExtras,mediaPagedepuis n'importe quel écran rendu sous<AdminKitApp>.useMemberRoles()(@clauzier/admin-kit/members) : le catalogue de rôles de la fiche Site, mis en cache par react-query.menuSections(schemas, options)est pur : une coquille qui remplace le menu ou l'accueil part des mêmes sections.
Thème
Le socle ne fournit aucune palette par défaut : une valeur de repli ferait
hériter l'identité d'un client à tous les autres. createAdminTheme construit
le thème MUI et émet les mêmes valeurs en custom properties --admin-*, pour
que la feuille de style et les composants partent d'une source unique.
tests/socle.test.ts échoue si une couleur littérale, un var(--x, repli) ou
le nom d'un client apparaît dans src/.
Traductions
L'interface est en français (ra-language-french + les chaînes du kit). Une
coquille surcharge n'importe quelle chaîne, y compris celles de react-admin,
en passant un arbre partiel :
<AdminKitApp messages={{ ra: { action: { create: 'Ajouter' } } }} … />
Contrat de schémas
Toutes les clés au-delà du socle publié sont optionnelles et lues défensivement : un type de champ inconnu se replie sur une saisie texte plutôt que de casser l'écran. Le kit reste donc utilisable face à une API plus ancienne que lui.
| Clé | Effet |
|---|---|
label_plural |
libellé du menu — un pluriel français ne se dérive pas en ajoutant un s |
singleton |
une seule fiche, slug forcé au type : écran de réglages au lieu d'une liste |
category |
content ou site : section du menu ; inconnu → null, repli sur le type |
groups |
[{ key, label }] ordonnés : un onglet par groupe dans l'écran de réglages |
help |
texte d'aide sous le champ |
ui |
force un éditeur dédié (menu, labels, suggest, roles…) |
group |
groupe du champ ; absent ou inconnu → « Général » |
in_list |
affiche le champ en colonne de liste |
reference_type |
type cible d'un champ reference, alimente la liste déroulante |
options |
pour ui: labels, les clés de libellé dans l'ordre d'affichage |
option_labels |
pour ui: labels, description d'une clé ; sans point, titre d'un espace de noms |
defaults |
pour ui: labels, défaut de chaque clé, montré en placeholder |
capabilities.search |
affiche la boîte de recherche ; sans le paramètre q côté API elle ne ferait rien |
capabilities.statuses |
statuts acceptés par le socle |
Endpoints consommés
| Route | Usage |
|---|---|
GET /content-schemas |
contrat des types de contenu |
GET /block-schemas |
contrat des blocs de page (absent → éditeur sans blocs) |
POST /login, POST /logout |
session Sanctum |
/content_entities, /pages, /blocks, /media |
ressources API Platform (Hydra) |
POST /media, DELETE /media/{id} |
téléversement avec progression, suppression |
GET /site |
catalogue de rôles (data.member_roles) |
GET /site/rebuild |
état de la reconstruction (404 → carte masquée) |
POST /site/rebuild |
demande de reconstruction (409 si non configurée) |
GET/POST /users, PUT/DELETE /users/{id} |
écran Utilisateurs |
Développement
bun install
bun run lint && bun run format:check && bun run typecheck && bun run test
Dependencies
Dependencies
| ID | Version |
|---|---|
| ra-i18n-polyglot | ^5.15.0 |
| ra-input-rich-text | ^5.15.1 |
| ra-language-french | ^5.15.0 |
Development dependencies
| ID | Version |
|---|---|
| @eslint/js | ^10.0.0 |
| @testing-library/react | ^16.3.0 |
| @types/node | ^26.0.0 |
| @types/react | ^19.0.0 |
| @types/react-dom | ^19.0.0 |
| eslint | ^10.0.0 |
| eslint-plugin-react-hooks | ^7.0.0 |
| jsdom | ^28.0.0 |
| prettier | ^3.9.0 |
| typescript | ~5.9.0 |
| typescript-eslint | ^8.40.0 |
| vitest | ^4.0.0 |
Peer dependencies
| ID | Version |
|---|---|
| @api-platform/admin | ^4.0.0 |
| @mui/icons-material | ^9.0.0 |
| @mui/material | ^9.0.0 |
| @tanstack/react-query | ^5.83.0 |
| react | ^19.0.0 |
| react-admin | ^5.15.0 |
| react-dom | ^19.0.0 |
| react-router-dom | ^7.0.0 |