@wojtekmaj/react-recaptcha-v3
Version:
Integrate Google reCAPTCHA v3 with your React app
162 lines (161 loc) • 5.48 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { loadScript } from './utils.js';
/**
* Holds the loaded script type. This is used to prevent multiple versions of the script from
* being loaded.
*/
let loadedUrl = null;
let isLoaded = false;
const instances = new Set();
const onLoadCallbacks = new Set();
const isBrowser = typeof window !== 'undefined';
const cfgKey = '___grecaptcha_cfg';
// Random name to prevent conflicts with other scripts
const onLoadCallbackName = `onLoadCallback_${Math.random().toString(36).slice(2)}`;
function initialize() {
if (!isBrowser) {
return;
}
/**
* Makes it possible for multiple reCAPTCHA instances to be loaded by wrapping the onReady
* callback in a function that pushes the callbacks to a global array (fns). This array is then
* executed when reCAPTCHA loads.
*
* A modified version of the script provided by Google:
* https://developers.google.com/recaptcha/docs/loading#loading_recaptcha_asynchronously
*/
function ready(cb) {
if (isLoaded) {
cb();
}
else {
if (!window[cfgKey]) {
window[cfgKey] = {};
}
const cfg = window[cfgKey];
if (!cfg.fns) {
cfg.fns = [];
}
const fns = cfg.fns;
fns.push(cb);
}
}
if (!window.grecaptcha) {
window.grecaptcha = {};
}
if (!window.grecaptcha.enterprise) {
window.grecaptcha.enterprise = {};
}
window.grecaptcha.ready = ready;
window.grecaptcha.enterprise.ready = ready;
function onLoadCallback() {
isLoaded = true;
for (const callback of onLoadCallbacks) {
callback();
}
onLoadCallbacks.clear();
}
// @ts-ignore
window[onLoadCallbackName] = onLoadCallback;
}
function generateGoogleRecaptchaSrc({ language, onLoadCallbackName, render, useEnterprise = false, useRecaptchaNet = false, }) {
const host = useRecaptchaNet ? 'recaptcha.net' : 'google.com';
const script = useEnterprise ? 'enterprise.js' : 'api.js';
const params = new URLSearchParams({
render,
});
if (onLoadCallbackName) {
params.set('onload', onLoadCallbackName);
}
if (language) {
params.set('hl', language);
}
return `https://www.${host}/recaptcha/${script}?${params.toString()}`;
}
function loadGoogleRecaptchaScript({ language, render, scriptProps, useEnterprise, useRecaptchaNet, }) {
const defaultScriptProps = {
id: 'google-recaptcha-v3',
};
const src = generateGoogleRecaptchaSrc({
language,
onLoadCallbackName,
render,
useEnterprise,
useRecaptchaNet,
});
if (loadedUrl) {
if (loadedUrl !== src) {
throw new Error('reCAPTCHA has already been loaded with different parameters. Remove the existing script and load it again.');
}
return;
}
loadedUrl = src;
loadScript(Object.assign(Object.assign(Object.assign({}, defaultScriptProps), scriptProps), { src }));
}
export function removeClient(clientId) {
if (!window[cfgKey]) {
return;
}
const cfg = window[cfgKey];
if (!cfg.clients) {
return;
}
delete cfg.clients[clientId];
}
export function registerInstance(instanceId, _a) {
var { onLoadCallback, onLoadCallbackName } = _a, loadGoogleRecaptchaScriptOptions = __rest(_a, ["onLoadCallback", "onLoadCallbackName"]);
if (instances.size === 0) {
initialize();
}
loadGoogleRecaptchaScript(loadGoogleRecaptchaScriptOptions);
instances.add(instanceId);
if (onLoadCallback) {
if (isLoaded) {
onLoadCallback();
}
else {
onLoadCallbacks.add(onLoadCallback);
}
}
if (onLoadCallbackName) {
function callOnLoadCallbackIfExists() {
if (!onLoadCallbackName) {
return;
}
// @ts-ignore
const maybeOnLoadCallback = window[onLoadCallbackName];
if (typeof maybeOnLoadCallback === 'function') {
maybeOnLoadCallback();
}
}
if (isLoaded) {
callOnLoadCallbackIfExists();
}
else {
onLoadCallbacks.add(callOnLoadCallbackIfExists);
}
}
}
export function unregisterInstance(instanceId) {
var _a, _b, _c;
instances.delete(instanceId);
if (instances.size === 0) {
window.grecaptcha = undefined;
window[cfgKey] = undefined;
(_a = document.querySelector('.grecaptcha-badge')) === null || _a === void 0 ? void 0 : _a.remove();
(_b = document.querySelector(`script[src="${loadedUrl}"]`)) === null || _b === void 0 ? void 0 : _b.remove();
(_c = document.querySelector(`script[src^="https://www.gstatic.com/recaptcha/releases"]`)) === null || _c === void 0 ? void 0 : _c.remove();
loadedUrl = null;
isLoaded = false;
}
}