UNPKG

@wojtekmaj/react-recaptcha-v3

Version:

Integrate Google reCAPTCHA v3 with your React app

162 lines (161 loc) 5.48 kB
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; } }