New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@matt-block/react-recaptcha-v2

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@matt-block/react-recaptcha-v2 - npm Package Compare versions

Comparing version 1.0.9 to 2.0.0-rc.0

227

lib/index.esm.js

@@ -1,2 +0,2 @@

import React, { Component } from 'react';
import React, { useState, useEffect } from 'react';

@@ -17,15 +17,13 @@ /*! *****************************************************************************

***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
function __rest(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;
}

@@ -44,98 +42,121 @@

var ReCaptcha = (function (_super) {
__extends(ReCaptcha, _super);
function ReCaptcha() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.scriptSrc = "https://www.google.com/recaptcha/api.js";
_this.testSiteKey = "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI";
_this.observer = new MutationObserver(_this.mutationCallbackGenerator());
_this.hiddenDiv = document.createElement("div");
_this.id = nanoid();
_this.successCallbackId = nanoid();
_this.expiredCallbackId = nanoid();
_this.errorCallbackId = nanoid();
return _this;
const MAIN_SCRIPT_ID = "recaptcha";
const MAIN_SCRIPT_SRC = "https://www.google.com/recaptcha/api.js";
const IMPLICIT_SCRIPT_SRC_PATTERN = /https:\/\/www.gstatic.com\/recaptcha\/releases\/.*.js$/;
const TEST_SITE_KEY = "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI";
const getMainScriptElement = () => {
if (document.getElementById(MAIN_SCRIPT_ID) !== null) {
return document.getElementById(MAIN_SCRIPT_ID);
}
ReCaptcha.prototype.componentDidMount = function () {
this.observer.observe(document.body, { childList: true });
this.appendScript();
window[this.successCallbackId] = this.props.onSuccess;
window[this.expiredCallbackId] = this.props.onExpire;
window[this.errorCallbackId] = this.props.onError;
};
ReCaptcha.prototype.componentWillUnmount = function () {
this.cleanup();
};
ReCaptcha.prototype.appendScript = function () {
if (!this.getScriptIfAvailable()) {
var reCaptchaScript = this.createScriptElement();
document.body.appendChild(reCaptchaScript);
}
};
ReCaptcha.prototype.getScriptIfAvailable = function () {
var _this = this;
if (document.getElementById("recaptcha") !== null) {
return document.getElementById("recaptcha");
}
var availableScripts = Array.from(document.scripts);
return availableScripts.find(function (script) { return script.src === _this.scriptSrc; });
};
ReCaptcha.prototype.createScriptElement = function () {
var reCaptchaScript = document.createElement("script");
reCaptchaScript.id = "recaptcha";
reCaptchaScript.src = this.scriptSrc;
reCaptchaScript.async = true;
reCaptchaScript.defer = true;
return reCaptchaScript;
};
ReCaptcha.prototype.cleanup = function () {
var script = this.getScriptIfAvailable();
if (script) {
this.removeChild(script);
}
delete window[this.successCallbackId];
delete window[this.expiredCallbackId];
delete window[this.errorCallbackId];
this.removeChild(this.hiddenDiv);
var allScripts = Array.from(document.scripts);
var reCaptchaSrcPattern = /https:\/\/www.gstatic.com\/recaptcha\/releases\/.*.js$/;
var additionalScripts = allScripts.filter(function (script) {
return reCaptchaSrcPattern.test(script.src);
const availableScripts = Array.from(document.scripts);
return availableScripts.find((script) => script.src === MAIN_SCRIPT_SRC);
};
const createMainScriptElement = () => {
const scriptElement = document.createElement("script");
scriptElement.id = MAIN_SCRIPT_ID;
scriptElement.src = MAIN_SCRIPT_SRC;
scriptElement.async = true;
scriptElement.defer = true;
return scriptElement;
};
const appendScript = () => {
if (!getMainScriptElement()) {
const reCaptchaScript = createMainScriptElement();
document.body.appendChild(reCaptchaScript);
}
};
const removeChildElement = (element) => {
const parentNode = element.parentNode;
if (parentNode !== null) {
parentNode.removeChild(element);
}
};
const removeImplicitRecaptchaScripts = () => {
const allScripts = Array.from(document.scripts);
const additionalScripts = allScripts.filter((script) => IMPLICIT_SCRIPT_SRC_PATTERN.test(script.src));
additionalScripts.map(removeChildElement);
};
const isNodeRecaptchaHiddenDiv = (node) => {
const div = node;
return (div.style &&
div.style.visibility === "hidden" &&
div.style.top === "-10000px" &&
div.style.position === "absolute");
};
const mutationCallbackGenerator = (onHiddenDivFound) => {
return (mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === "childList" &&
mutation.target === document.body &&
mutation.addedNodes.length === 1 &&
isNodeRecaptchaHiddenDiv(mutation.addedNodes[0])) {
onHiddenDivFound(mutation.addedNodes[0]);
}
});
additionalScripts.map(this.removeChild);
};
ReCaptcha.prototype.removeChild = function (element) {
var parentNode = element.parentNode;
if (parentNode !== null) {
parentNode.removeChild(element);
}
};
const useWindowCallbackBinder = (callbacks) => {
const [onSuccessCallbackId] = useState(nanoid());
const [onErrorCallbackId] = useState(nanoid());
const [onExpireCallbackId] = useState(nanoid());
const { onSuccess, onError, onExpire } = callbacks;
useEffect(() => {
window[onSuccessCallbackId] = onSuccess;
window[onExpireCallbackId] = onExpire;
window[onErrorCallbackId] = onError;
return () => {
delete window[onSuccessCallbackId];
delete window[onExpireCallbackId];
delete window[onErrorCallbackId];
};
}, [
onSuccess,
onSuccessCallbackId,
onError,
onErrorCallbackId,
onExpire,
onExpireCallbackId,
]);
return {
onSuccessCallbackId,
onErrorCallbackId,
onExpireCallbackId,
};
ReCaptcha.prototype.mutationCallbackGenerator = function () {
var _this = this;
return function (mutations) {
mutations.forEach(function (mutation) {
if (mutation.type === "childList" &&
mutation.target === document.body &&
mutation.addedNodes.length === 1 &&
_this.isNodeReCaptchaHiddenDiv(mutation.addedNodes[0])) {
_this.hiddenDiv = mutation.addedNodes[0];
_this.observer.disconnect();
}
});
};
const useRecaptchaScripts = () => {
useEffect(() => {
appendScript();
return () => {
const script = getMainScriptElement();
if (script) {
removeChildElement(script);
}
removeImplicitRecaptchaScripts();
};
};
ReCaptcha.prototype.isNodeReCaptchaHiddenDiv = function (node) {
var div = node;
return (div.style &&
div.style.visibility === "hidden" &&
div.style.top === "-10000px" &&
div.style.position === "absolute");
};
ReCaptcha.prototype.render = function () {
var _a = this.props, siteKey = _a.siteKey, theme = _a.theme, size = _a.size;
return (React.createElement("div", { id: this.id, className: "g-recaptcha", "data-sitekey": siteKey === "test" ? this.testSiteKey : siteKey, "data-theme": theme, "data-size": size, "data-callback": this.successCallbackId, "data-expired-callback": this.expiredCallbackId, "data-error-callback": this.errorCallbackId }));
};
return ReCaptcha;
}(Component));
}, []);
};
const useRecaptchaHiddenDivManager = () => {
useEffect(() => {
let hiddenDiv;
const observer = new MutationObserver(mutationCallbackGenerator((div) => {
hiddenDiv = div;
}));
observer.observe(document.body, { childList: true });
return () => {
observer.disconnect();
if (hiddenDiv) {
removeChildElement(hiddenDiv);
}
};
}, []);
};
const ReCaptcha = (props) => {
const { siteKey, theme, size } = props, callbacks = __rest(props, ["siteKey", "theme", "size"]);
const { onSuccessCallbackId, onErrorCallbackId, onExpireCallbackId } = useWindowCallbackBinder(callbacks);
useRecaptchaHiddenDivManager();
useRecaptchaScripts();
const [id] = useState(nanoid());
return (React.createElement("div", { id: id, className: "g-recaptcha", "data-sitekey": siteKey === "test" ? TEST_SITE_KEY : siteKey, "data-theme": theme, "data-size": size, "data-callback": onSuccessCallbackId, "data-error-callback": onErrorCallbackId, "data-expired-callback": onExpireCallbackId }));
};
export { ReCaptcha as default };
{
"name": "@matt-block/react-recaptcha-v2",
"version": "1.0.9",
"version": "2.0.0-rc.0",
"description": "Google reCAPTCHA v2 React component that does not pollute the DOM",

@@ -28,3 +28,3 @@ "main": "lib/index.esm.js",

"scripts": {
"build": "rollup -c rollup.config.ts",
"build": "rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
"postbuild": "tsc --emitDeclarationOnly",

@@ -37,4 +37,4 @@ "prepare": "husky install"

"devDependencies": {
"@rollup/plugin-node-resolve": "^13.3.0",
"@rollup/plugin-typescript": "^8.5.0",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-typescript": "^11.0.0",
"@types/react": "^18.0.28",

@@ -44,3 +44,3 @@ "husky": "^7.0.4",

"prettier": "^2.8.4",
"rollup": "^2.79.1",
"rollup": "^3.17.2",
"rollup-plugin-copy": "^3.4.0",

@@ -51,3 +51,3 @@ "tslib": "^1.14.1",

"peerDependencies": {
"react": "^16.0.0 || ^17.0.0 || ^18.0.0"
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},

@@ -54,0 +54,0 @@ "lint-staged": {

@@ -11,6 +11,6 @@ # React reCAPTCHA v2

- [x] Does not pollute the DOM by cleaning up on unmount (see below)
- [x] Can safely add multiple `<ReCaptcha>` components in the same page, they
will not conflict with each other.
- [x] TypeScript and Flow type declarations
- Does not pollute the DOM by cleaning up on unmount (see below)
- Can safely add multiple `<ReCaptcha>` components in the same page, they
will not conflict with each other.
- TypeScript and Flow type declarations

@@ -36,9 +36,10 @@ ### DOM Pollution and Cleanup

| React | Library |
| :------: | :-----: |
| >=16.0.0 | latest |
| React | Library | Status | End-of-Life |
| :---------------: | :---------------------------------------: | :-------------: | :---------: |
| `>=16.8.0` | [![npm (scoped)][npm_shield]][npm] | **Active** | - |
| `16.0.0 - 16.7.x` | [![npm v1 (scoped)][npm_1_shield]][npm_1] | **Maintenance** | 2023-06-01 |
## Installation
Install the package via Yarn or npm:
Install the package via npm or Yarn:

@@ -59,21 +60,19 @@ ```

```javascript
import React, { Component } from "react";
import React from "react";
import ReCaptcha from "@matt-block/react-recaptcha-v2";
class MyFormComponent extends Component {
// other methods and callbacks...
const MyFormComponent = () => {
// other logic and hooks...
render() {
return (
{/* other components to render... */}
<ReCaptcha
siteKey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
theme="light"
size="normal"
onSuccess={(captcha) => console.log(`Successful, result is ${captcha}`)}
onExpire={() => console.log("Verification has expired, re-verify.")}
onError={() => console.log("Something went wrong, check your conenction")}
/>
);
}
return (
{/* other components to render... */}
<ReCaptcha
siteKey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
theme="light"
size="normal"
onSuccess={(captcha) => console.log(`Successful, result is ${captcha}`)}
onError={() => console.log("Something went wrong, check your conenction")}
onExpire={() => console.log("Verification has expired, re-verify.")}
/>
);
}

@@ -93,4 +92,4 @@ ```

| `onSuccess` | `function` | `undefined` | Callback function, executed when the user submits a successful response. The response token is passed to your callback. |
| `onExpired` | `function` | `undefined` | Callback function, executed when the reCAPTCHA response expires and the user needs to re-verify. |
| `onError` | `function` | `undefined` | Callback function, executed when reCAPTCHA encounters an error (usually network connectivity) and cannot continue until connectivity is restored. If you specify a function here, you are responsible for informing the user that they should retry. |
| `onExpire` | `function` | `undefined` | Callback function, executed when the reCAPTCHA response expires and the user needs to re-verify. |

@@ -111,3 +110,5 @@ ## License

[npm]: https://www.npmjs.com/package/@matt-block/react-recaptcha-v2
[npm_shield]: https://img.shields.io/npm/v/@matt-block/react-recaptcha-v2.svg
[npm_shield]: https://img.shields.io/npm/v/@matt-block/react-recaptcha-v2/latest
[npm_1]: https://www.npmjs.com/package/@matt-block/react-recaptcha-v2/v/1.0.9
[npm_1_shield]: https://img.shields.io/badge/npm-v1.0.9-blue
[recaptcha_admin]: https://www.google.com/recaptcha/admin

@@ -114,0 +115,0 @@ [recaptcha_docs]: https://developers.google.com/recaptcha/docs/display

@@ -1,2 +0,2 @@

import { Component } from "react";
import { FC } from "react";
interface ReCaptchaProps {

@@ -10,22 +10,3 @@ siteKey: string;

}
declare class ReCaptcha extends Component<ReCaptchaProps, {}> {
private scriptSrc;
private testSiteKey;
private observer;
private hiddenDiv;
private id;
private successCallbackId;
private expiredCallbackId;
private errorCallbackId;
componentDidMount(): void;
componentWillUnmount(): void;
appendScript(): void;
getScriptIfAvailable(): HTMLScriptElement | undefined;
createScriptElement(): HTMLScriptElement;
private cleanup;
removeChild(element: HTMLElement): void;
mutationCallbackGenerator(): (mutations: MutationRecord[]) => void;
isNodeReCaptchaHiddenDiv(node: Node): boolean;
render(): JSX.Element;
}
declare const ReCaptcha: FC<ReCaptchaProps>;
export default ReCaptcha;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc