64 lines
2.2 KiB
JavaScript
64 lines
2.2 KiB
JavaScript
'use client';
|
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
import { useEffect, useRef } from 'react';
|
|
const SCRIPT_SRC = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
|
|
/** Loads the Turnstile script once, shared across all widget instances. */ function ensureScript() {
|
|
if (typeof document === 'undefined') {
|
|
return;
|
|
}
|
|
if (document.querySelector(`script[src="${SCRIPT_SRC}"]`)) {
|
|
return;
|
|
}
|
|
const script = document.createElement('script');
|
|
script.src = SCRIPT_SRC;
|
|
script.async = true;
|
|
script.defer = true;
|
|
document.head.appendChild(script);
|
|
}
|
|
/**
|
|
* Cloudflare Turnstile widget — reusable across any form. Renders the challenge
|
|
* and reports the token via onToken. The token must then be verified
|
|
* server-side (see verifyTurnstile) before a submission is trusted.
|
|
*
|
|
* siteKey is a prop rather than an env var so all Turnstile config lives in one
|
|
* place (SiteIntegrations), consistent with the plugin's panel-managed model.
|
|
* The script is injected directly (no next/script dependency) so the widget
|
|
* stays framework-agnostic.
|
|
*/ export function Turnstile({ onToken, siteKey, theme = 'auto' }) {
|
|
const ref = useRef(null);
|
|
const widgetId = useRef(null);
|
|
useEffect(()=>{
|
|
if (!siteKey) {
|
|
return;
|
|
}
|
|
ensureScript();
|
|
function render() {
|
|
if (!ref.current || !window.turnstile || widgetId.current) {
|
|
return;
|
|
}
|
|
widgetId.current = window.turnstile.render(ref.current, {
|
|
callback: (token)=>onToken(token),
|
|
'error-callback': ()=>onToken(null),
|
|
'expired-callback': ()=>onToken(null),
|
|
sitekey: siteKey,
|
|
theme
|
|
});
|
|
}
|
|
render();
|
|
// Script may load after mount — retry briefly until ready.
|
|
const interval = setInterval(render, 300);
|
|
return ()=>clearInterval(interval);
|
|
}, [
|
|
siteKey,
|
|
theme,
|
|
onToken
|
|
]);
|
|
if (!siteKey) {
|
|
return null;
|
|
}
|
|
return /*#__PURE__*/ _jsx("div", {
|
|
ref: ref
|
|
});
|
|
} //# sourceMappingURL=Turnstile.js.map
|
|
|
|
//# sourceMappingURL=Turnstile.js.map
|