'use client' import { useEffect, useRef } from 'react' interface TurnstileApi { render: ( el: HTMLElement, opts: { sitekey: string theme?: 'auto' | 'light' | 'dark' callback?: (token: string) => void 'error-callback'?: () => void 'expired-callback'?: () => void }, ) => string } declare global { interface Window { turnstile?: TurnstileApi } } const SCRIPT_ID = 'cf-turnstile-script' /** Widget de Cloudflare Turnstile. Llama onVerify(token) cuando se resuelve. */ export function Turnstile({ onVerify }: { onVerify: (token: string) => void }) { const ref = useRef(null) const rendered = useRef(false) const cb = useRef(onVerify) cb.current = onVerify const siteKey = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY useEffect(() => { if (!siteKey) return let cancelled = false function render() { if (cancelled || rendered.current || !ref.current || !window.turnstile) return rendered.current = true window.turnstile.render(ref.current, { sitekey: siteKey!, theme: 'dark', callback: (t) => cb.current(t), 'error-callback': () => cb.current(''), 'expired-callback': () => cb.current(''), }) } if (window.turnstile) { render() return () => { cancelled = true } } if (!document.getElementById(SCRIPT_ID)) { const s = document.createElement('script') s.id = SCRIPT_ID s.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js' s.async = true s.defer = true document.head.appendChild(s) } const iv = window.setInterval(() => { if (window.turnstile) { window.clearInterval(iv) render() } }, 200) return () => { cancelled = true window.clearInterval(iv) } }, [siteKey]) if (!siteKey) return null return
}