Exemples d'intégration frontend
Le widget est un élément personnalisé standard, donc il fonctionne dans chaque framework sans wrapper à installer. La forme est toujours la même : charge le paquet une fois (intégration côté client), affiche <caputchin-widget sitekey="cpt_pub_..."> dans ton formulaire, et lis le champ caché caputchin-token qu'il injecte quand le visiteur réussit l'épreuve. Pour un jeu, remplace par <caputchin-game ... game="caputchin/games/leaf-memory">.
Les exemples ci-dessous ne diffèrent que par la syntaxe de chaque framework et son unique particularité d'élément personnalisé.
HTML pur
Le champ injecté voyage avec un POST de formulaire normal, donc il n'y a rien à câbler :
<script src="https://cdn.jsdelivr.net/npm/@caputchin/widget@3/dist/widget.js"></script>
<form action="/contact" method="POST">
<input name="email" type="email" required />
<caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
<button type="submit">Send</button>
</form>React
Importe une fois au démarrage, puis lis le champ depuis FormData à l'envoi :
import "@caputchin/widget";
export function ContactForm() {
async function handleSubmit(e) {
e.preventDefault();
const data = new FormData(e.currentTarget);
await fetch("/api/contact", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ email: data.get("email"), token: data.get("caputchin-token") }),
});
}
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" required />
<caputchin-widget sitekey="cpt_pub_..." />
<button type="submit">Send</button>
</form>
);
}Si tu utilises TypeScript avec React, déclare les deux éléments une fois pour que JSX les accepte :
// caputchin.d.ts
import type { DetailedHTMLProps, HTMLAttributes } from "react";
declare module "react" {
namespace JSX {
interface IntrinsicElements {
"caputchin-widget": DetailedHTMLProps<HTMLAttributes<HTMLElement> & { sitekey: string }, HTMLElement>;
"caputchin-game": DetailedHTMLProps<HTMLAttributes<HTMLElement> & { sitekey: string; game?: string; games?: string }, HTMLElement>;
}
}
}Cette forme declare module "react" est propre au JSX de React. En TypeScript pur, les éléments sont simplement des HTMLElement et n'ont besoin d'aucune déclaration, et les autres frameworks ci-dessous typent les éléments personnalisés à leur façon, donc tu n'as besoin de ce bloc que dans un projet React.
Vue
Indique au compilateur de Vue que les balises caputchin- sont des éléments personnalisés, pour qu'il n'essaie pas de les résoudre comme des composants :
// vite.config.js
export default {
plugins: [vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith("caputchin-") } } })],
};<script setup>
import "@caputchin/widget";
function onSubmit(e) {
const data = new FormData(e.target);
// send data.get("caputchin-token") to your backend
}
</script>
<template>
<form @submit.prevent="onSubmit">
<input name="email" type="email" required />
<caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
<button type="submit">Send</button>
</form>
</template>Svelte
Svelte affiche les éléments personnalisés tels quels, sans config :
<script>
import "@caputchin/widget";
function onSubmit(e) {
const data = new FormData(e.currentTarget);
// send data.get("caputchin-token") to your backend
}
</script>
<form on:submit|preventDefault={onSubmit}>
<input name="email" type="email" required />
<caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
<button type="submit">Send</button>
</form>Angular
Ajoute CUSTOM_ELEMENTS_SCHEMA au module ou au composant standalone pour qu'Angular autorise la balise inconnue, et importe le paquet une fois (dans main.ts) :
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import "@caputchin/widget";
@Component({
selector: "contact-form",
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<form (submit)="onSubmit($event)">
<input name="email" type="email" required />
<caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
<button type="submit">Send</button>
</form>
`,
})
export class ContactFormComponent {
onSubmit(e: Event) {
const data = new FormData(e.target as HTMLFormElement);
// send data.get("caputchin-token") to your backend
}
}Next.js
Le même code React fonctionne. L'élément personnalisé s'affiche comme une balise vide pendant le rendu serveur et se met à niveau côté client une fois le paquet chargé, donc aucun traitement particulier n'est nécessaire au-delà d'importer @caputchin/widget dans un composant client (ou de charger le script CDN avec next/script).
Voir aussi
- Intégration côté client pour les options de chargement.
- Intégration côté serveur pour la moitié backend.