forked from Northgate-Systems/RemitX
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTurnstileWidget.tsx
More file actions
111 lines (98 loc) · 3.18 KB
/
Copy pathTurnstileWidget.tsx
File metadata and controls
111 lines (98 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
"use client";
import { useEffect, useRef, useId, useState } from "react";
declare global {
interface Window {
turnstile?: {
render: (
container: string | HTMLElement,
options: {
sitekey: string;
callback: (token: string) => void;
"expired-callback"?: () => void;
"error-callback"?: () => void;
theme?: "light" | "dark" | "auto";
}
) => string;
remove: (widgetId: string) => void;
};
onTurnstileLoad?: () => void;
}
}
const SCRIPT_ID = "cf-turnstile-script";
const SITE_KEY = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY;
interface TurnstileWidgetProps {
onVerify: (token: string) => void;
onExpire?: () => void;
}
export default function TurnstileWidget({ onVerify, onExpire }: TurnstileWidgetProps) {
const containerId = `turnstile-${useId().replace(/:/g, "")}`;
const widgetIdRef = useRef<string | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (!SITE_KEY) {
onVerify("dev-skip-no-site-key");
return;
}
function render() {
if (!window.turnstile) return;
const el = document.getElementById(containerId);
if (!el || widgetIdRef.current) return;
try {
widgetIdRef.current = window.turnstile.render(el, {
sitekey: SITE_KEY as string,
callback: onVerify,
"expired-callback": onExpire,
"error-callback": () => {
setError("Verification challenge failed. Please check your connection and try again.");
onExpire?.();
},
theme: "light",
});
setError(null);
} catch (e) {
setError("Could not load the verification widget. Please refresh the page.");
}
}
if (window.turnstile) {
render();
return;
}
let script = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;
if (!script) {
script = document.createElement("script");
script.id = SCRIPT_ID;
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onTurnstileLoad&render=explicit";
script.async = true;
script.defer = true;
script.onerror = () => {
setError("Failed to load the verification script. Check your network connection.");
};
document.head.appendChild(script);
}
window.onTurnstileLoad = render;
return () => {
if (widgetIdRef.current && window.turnstile) {
window.turnstile.remove(widgetIdRef.current);
widgetIdRef.current = null;
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [containerId]);
if (!SITE_KEY) {
return (
<div className="text-xs text-amber-700 bg-amber-50 border border-amber-200 rounded-lg px-3 py-2.5">
Cloudflare Turnstile is not configured yet - set{" "}
<code className="font-mono">NEXT_PUBLIC_TURNSTILE_SITE_KEY</code> in .env to enable
verification. Continuing without it for now.
</div>
);
}
if (error) {
return (
<div className="text-xs text-red-600 bg-red-50 border border-red-200 rounded-lg px-3 py-2.5">
{error}
</div>
);
}
return <div id={containerId} />;
}