@rikaido/react
Les composants React
Headless, composables, prêts à servir. Chaque exemple ci-dessous tourne pour vrai, dans cette page, sans clé.
Installer
npm install @rikaido/react @rikaido/sdkDu TypeScript compilé, React 18 ou plus, rien d’autre. Chaque composant est headless : il expose des attributs data-rikaido="…" et des render props, et ne porte aucun style. @rikaido/react/atelier.css est une façon de les dessiner — c’est celle des exemples ici — et la tienne en est une autre.
import { RikaidoProvider } from "@rikaido/react";
import "@rikaido/react/atelier.css";
<RikaidoProvider apiKey={import.meta.env.RIKAIDO_KEY} locale="fr">
{/* tout ce qui suit */}
</RikaidoProvider>Le verdict
Le harnais rend un verdict ; Verdict le montre comme une relecture — huit lignes dans l’ordre du validateur, chacune propre, notée, en erreur, refusée ou pas pour ce plat. Ici, une allergie à l’arachide et un satay au beurre d’arachide.
useVerdict(recipe, constraints) appelle l’API et met la réponse en cache par corps de requête. Verdict.Rows dessine les huit lignes ; Verdict.Lock dit le verrou en un mot : « Non servie. », « Servie. », « Servie, avec ses notes. » Les phrases viennent de la spec publiée, en français ou en anglais.
Verdict.Root{ verdict, locale?, attribution?, children }children peut être une fonction ({ rows, safe, ok }) => … pour tout dessiner toi-même.Verdict.Rows{ showSkipped?, children? }children(row, i) pour dessiner chaque ligne ; showSkipped={false} pour cacher celles qui n’ont pas tourné.Verdict.Row{ row }Verdict.Issue{ issue }Verdict.Lock{}useVerdict(recipe, constraints?)Async<Verdict>{ status: 'idle' | 'loading' | 'ready' | 'error', data?, error? }.verdictRows(verdict, locale)VerdictRow[]Avec un render prop, tu dessines tout toi-même et la structure reste la sienne :
Attributs exposés : data-rikaido="verdict" (data-safe, data-ok), verdict-rows, verdict-row (data-check, data-state), verdict-mark, verdict-check, verdict-findings, verdict-issue (data-code, data-severity : error, warn, safety), verdict-text, verdict-subject, verdict-code, verdict-lock.
Le cast
Deux portraits par ingrédient : le dessin kawaii, un SVG de 64 × 64 rendu en ligne, et le jouet 3D, un WebP servi par adresse et chargé par le composant parce qu’il voyage avec ta clé.
IngredientPortrait{ name, form?, size?, alt?, fallback?, attribution?, children? }form : kawaii (défaut) ou toy. children({ portrait, toyUrl, status }) pour tout dessiner toi-même. Un nom que le cast n’a pas montre fallback, ou l’initiale.useIngredientPortrait(name)Async<Portrait>{ slug, kawaiiSvg, kawaiiUrl, toyUrl }.useToyUrl(name)Async<string>blob: URL, révoquée quand le composant part.Attributs exposés : data-rikaido="portrait" (data-form, data-status), portrait-kawaii, portrait-toy, portrait-fallback.
Le graphe
Ce que le graphe sait d’un ingrédient : de quoi il est fait, ce qui le remplace. AllergenBadges fait l’union sur toute une liste et dit quand un ingrédient lui est inconnu — une rangée vide parce que le graphe n’a jamais vu l’aliment ne doit jamais se lire comme « sans allergène ».
AllergenBadges{ names, locale?, attribution?, children? }children({ allergens, unknown, status }) pour dessiner toi-même.Substitutions{ name, locale?, attribution?, children? }useIngredient(name, { neighbours? })Async<GraphIngredient>{ canonical, known, facts, substitutions, art, neighbourhood? }.allergenLabel(code, locale)stringAttributs exposés : data-rikaido="allergens" (data-status, data-unknown), allergen (data-allergen), allergen-none, allergen-unknown, substitutions, substitution (data-role), substitution-swap, substitution-ratio, substitution-why, substitution-caveat.
Lire une source
Une adresse, un markdown ou un texte collé ; la recette qu’il contient, dans la forme que le harnais lit.
RecipeReader{ onRead?, locale?, placeholder?, submitLabel?, children? }children(state) pour dessiner l’état sous le champ.useRecipeRead(){ state, read(source, locale?), reset }Les petites choses
Pures, sans réseau, sans clé — ce que chaque app de cuisine réécrit.
Mettre à l’échelle
« 1 ½ », « 2-3 », « 3/4 » lus en nombres, multipliés, réécrits en jolies fractions. Ce qui ne se lit pas — « une pincée » — reste écrit tel quel.
useScaledRecipe(recipe, servings, baseServings, locale?)RecipescaleRecipe(recipe, factor, locale?)Recipescaled (nombre ou null) et display.parseQuantity(text) · formatQuantity(n, locale?)number | null · stringLes unités
Métrique et impérial, dans les deux sens : g ↔ oz et lb, ml ↔ c. à thé, c. à soupe et tasses, °C ↔ °F. Une unité inconnue revient telle quelle.
La minuterie
Un réducteur, un intervalle, et les deux choses qu’un cuisinier veut savoir : combien il reste, et si ça a sonné. Elle ne dérive pas : le temps restant se calcule sur l’horloge, pas sur les ticks.
useTimer(totalMs, { onDone?, tickMs? }){ clock, remainingMs, progress, running, done, start, pause, reset, add }clock est « 1:30 » ou « 1:00:00 ».timerReducer · remainingOf · formatClockpurLes étapes, une à la fois
Le pager du mode cuisson : il tient l’index, tu dessines l’étape. Les touches du clavier sont déjà branchées sur props.
useCookSteps(steps, initial?){ step, index, count, isFirst, isLast, next, prev, go, props, tempC }props sur le conteneur : role="group", l’étiquette « 2 / 4 », tabIndex, et onKeyDown pour ←, →, Espace, Entrée, Début, Fin.La marque
Chaque composant qui montre une donnée de Rikaido — le verdict, un portrait, les faits du graphe — porte « Propulsé par Rikaido », un lien discret avec le sceau. C’est la contrepartie du palier gratuit : le code est Apache-2.0, la marque reste. attribution="mark" garde seulement le sceau ; attribution="none" est pour un compte avec carte au dossier.
import { PoweredByRikaido, RikaidoSeal } from "@rikaido/react";
<PoweredByRikaido /> // le sceau et les mots, dans la langue du provider
<PoweredByRikaido variant="mark" /> // le sceau seul, les mots pour les lecteurs d’écran
<RikaidoSeal size={24} /> // le sceau, pour ton propre lienSans styles, ou avec les tiens
Rien ici n’impose une apparence. Chaque pièce porte un attribut data-rikaido et, quand il y a un état, un data-* qui le nomme. Une feuille de style qui cible ces attributs habille tout d’un coup :
[data-rikaido="verdict-row"][data-state="refused"] { color: crimson; }
[data-rikaido="allergen"] { border-radius: 999px; padding: 2px 10px; background: #fee; }
[data-rikaido="attribution"] { font-size: 12px; opacity: 0.7; }@rikaido/react/atelier.css fait exactement ça, dans la finition de l’atelier. Lis-la comme un point de départ.