UNPKG

@wojtekmaj/react-recaptcha-v3

Version:

Integrate Google reCAPTCHA v3 with your React app

131 lines (130 loc) 7.56 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { useEffect, useId, useMemo, useRef, useState } from 'react'; import warning from 'warning'; import ReCaptchaContext from './ReCaptchaContext.js'; import { registerInstance, removeClient, unregisterInstance } from './manager.js'; let didWarnAboutHiddenBadge = false; export default function ReCaptchaProvider({ container, children, language, reCaptchaKey, scriptProps, useEnterprise, useRecaptchaNet, }) { var _a, _b, _c, _d, _e, _f, _g; const id = useId(); const [reCaptchaInstance, setReCaptchaInstance] = useState(null); const [clientId, setClientId] = useState(null); const clientIdMounted = useRef(false); useEffect(() => { function onLoadCallback() { var _a; const nextReCaptchaInstance = useEnterprise ? (_a = window.grecaptcha) === null || _a === void 0 ? void 0 : _a.enterprise : window.grecaptcha; if (!nextReCaptchaInstance) { throw new Error('reCAPTCHA not found'); } if (!nextReCaptchaInstance.ready) { throw new Error('reCAPTCHA ready callback not found'); } nextReCaptchaInstance.ready(() => { setReCaptchaInstance(nextReCaptchaInstance); }); } registerInstance(id, { language, onLoadCallback, onLoadCallbackName: scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.onLoadCallbackName, render: (container === null || container === void 0 ? void 0 : container.element) ? 'explicit' : reCaptchaKey, scriptProps: { appendTo: scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.appendTo, async: scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.async, defer: scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.defer, id: scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.id, nonce: scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.nonce, }, useEnterprise, useRecaptchaNet, }); return () => { unregisterInstance(id); setReCaptchaInstance(null); }; }, [ container === null || container === void 0 ? void 0 : container.element, id, language, reCaptchaKey, scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.appendTo, scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.async, scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.defer, scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.id, scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.nonce, scriptProps === null || scriptProps === void 0 ? void 0 : scriptProps.onLoadCallbackName, useEnterprise, useRecaptchaNet, ]); useEffect(() => { var _a, _b, _c; if (!(container === null || container === void 0 ? void 0 : container.element) || !(reCaptchaInstance === null || reCaptchaInstance === void 0 ? void 0 : reCaptchaInstance.render)) { return; } const params = { 'error-callback': container.parameters.errorCallback, 'expired-callback': container.parameters.expiredCallback, badge: ((_a = container.parameters) === null || _a === void 0 ? void 0 : _a.badge) || 'inline', callback: container.parameters.callback, sitekey: reCaptchaKey, size: 'invisible', tabindex: container.parameters.tabindex, theme: container.parameters.theme, }; const actualContainerElement = typeof (container === null || container === void 0 ? void 0 : container.element) === 'string' ? document.getElementById(container.element) : container === null || container === void 0 ? void 0 : container.element; if (!actualContainerElement) { throw new Error('reCAPTCHA container element not found'); } const nextClientId = reCaptchaInstance.render(actualContainerElement, params); if ((_b = container === null || container === void 0 ? void 0 : container.parameters) === null || _b === void 0 ? void 0 : _b.hidden) { if (!didWarnAboutHiddenBadge) { warning(false, 'reCAPTCHA badge hidden. See https://cloud.google.com/recaptcha/docs/faq#id_like_to_hide_the_badge_what_is_allowed for more information.'); didWarnAboutHiddenBadge = true; } (_c = actualContainerElement.querySelector('.grecaptcha-badge')) === null || _c === void 0 ? void 0 : _c.style.setProperty('display', 'none'); } setClientId(nextClientId); clientIdMounted.current = true; return () => { setClientId(null); clientIdMounted.current = false; removeClient(nextClientId); actualContainerElement.innerHTML = ''; }; }, [ container === null || container === void 0 ? void 0 : container.element, (_a = container === null || container === void 0 ? void 0 : container.parameters) === null || _a === void 0 ? void 0 : _a.badge, (_b = container === null || container === void 0 ? void 0 : container.parameters) === null || _b === void 0 ? void 0 : _b.hidden, (_c = container === null || container === void 0 ? void 0 : container.parameters) === null || _c === void 0 ? void 0 : _c.callback, (_d = container === null || container === void 0 ? void 0 : container.parameters) === null || _d === void 0 ? void 0 : _d.errorCallback, (_e = container === null || container === void 0 ? void 0 : container.parameters) === null || _e === void 0 ? void 0 : _e.expiredCallback, (_f = container === null || container === void 0 ? void 0 : container.parameters) === null || _f === void 0 ? void 0 : _f.tabindex, (_g = container === null || container === void 0 ? void 0 : container.parameters) === null || _g === void 0 ? void 0 : _g.theme, reCaptchaInstance, reCaptchaKey, ]); const shouldUseClientId = Boolean(container === null || container === void 0 ? void 0 : container.element); const clientIdOrReCaptchaKey = shouldUseClientId ? clientId : reCaptchaKey; const executeRecaptcha = useMemo(() => clientIdOrReCaptchaKey !== null && (reCaptchaInstance === null || reCaptchaInstance === void 0 ? void 0 : reCaptchaInstance.execute) ? (action) => { if (clientIdOrReCaptchaKey === null || !(reCaptchaInstance === null || reCaptchaInstance === void 0 ? void 0 : reCaptchaInstance.execute)) { throw new Error('reCAPTCHA has not been loaded'); } if (shouldUseClientId && !clientIdMounted.current) { console.warn('Client ID not mounted'); return null; } return reCaptchaInstance.execute(clientIdOrReCaptchaKey, { action }); } : undefined, [clientIdOrReCaptchaKey, reCaptchaInstance, shouldUseClientId]); return (_jsx(ReCaptchaContext.Provider, { value: { container: container === null || container === void 0 ? void 0 : container.element, executeRecaptcha, reCaptchaInstance, }, children: children })); }