@hcaptcha/react-hcaptcha
Advanced tools
Comparing version 1.8.1 to 1.9.0
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized"; | ||
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose"; | ||
import * as React from 'react'; | ||
import { generateQuery, getFrame, getMountElement } from './utils.js'; | ||
var SCRIPT_ID = 'hcaptcha-api-script-id'; | ||
var HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad'; // Prevent loading API script multiple times | ||
var scripts = []; // Generate hCaptcha API script | ||
var mountCaptchaScript = function mountCaptchaScript(params) { | ||
if (params === void 0) { | ||
params = {}; | ||
} | ||
var element = getMountElement(params.scriptLocation); | ||
delete params.scriptLocation; | ||
var frame = getFrame(element); | ||
var script = scripts.find(function (_ref) { | ||
var scope = _ref.scope; | ||
return scope === frame.window; | ||
}); | ||
if (frame.document.getElementById(SCRIPT_ID) && script) { | ||
// API was already requested | ||
return script.promise; | ||
} | ||
var promise = new Promise(function (resolve, reject) { | ||
// Create global onload callback | ||
frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve; | ||
var domain = params.apihost || "https://js.hcaptcha.com"; | ||
delete params.apihost; | ||
var script = frame.document.createElement("script"); | ||
script.id = SCRIPT_ID; | ||
script.src = domain + "/1/api.js?render=explicit&onload=" + HCAPTCHA_LOAD_FN_NAME; | ||
script.async = params.loadAsync !== undefined ? params.loadAsync : true; | ||
delete params.loadAsync; | ||
script.onerror = function (event) { | ||
return reject('script-error'); | ||
}; | ||
var query = generateQuery(params); | ||
script.src += query !== "" ? "&" + query : ""; | ||
element.appendChild(script); | ||
}); | ||
scripts.push({ | ||
promise: promise, | ||
scope: frame.window | ||
}); | ||
return promise; | ||
}; | ||
import { hCaptchaLoader, initSentry } from '@hcaptcha/loader'; | ||
import { getFrame, getMountElement } from './utils.js'; | ||
import { breadcrumbMessages, scopeTag } from "./constants"; | ||
var HCaptcha = /*#__PURE__*/function (_React$Component) { | ||
_inheritsLoose(HCaptcha, _React$Component); | ||
function HCaptcha(props) { | ||
var _this; | ||
_this = _React$Component.call(this, props) || this; | ||
_this = _React$Component.call(this, props) || this; | ||
/** | ||
@@ -67,10 +19,11 @@ * Internal reference to track hCaptcha API | ||
*/ | ||
_this._hcaptcha = undefined; | ||
_this._hcaptcha = undefined; // API Methods | ||
// API Methods | ||
_this.renderCaptcha = _this.renderCaptcha.bind(_assertThisInitialized(_this)); | ||
_this.resetCaptcha = _this.resetCaptcha.bind(_assertThisInitialized(_this)); | ||
_this.removeCaptcha = _this.removeCaptcha.bind(_assertThisInitialized(_this)); | ||
_this.isReady = _this.isReady.bind(_assertThisInitialized(_this)); // Event Handlers | ||
_this.isReady = _this.isReady.bind(_assertThisInitialized(_this)); | ||
// Event Handlers | ||
_this.loadCaptcha = _this.loadCaptcha.bind(_assertThisInitialized(_this)); | ||
@@ -86,2 +39,3 @@ _this.handleOnLoad = _this.handleOnLoad.bind(_assertThisInitialized(_this)); | ||
_this.apiScriptRequested = false; | ||
_this.sentryHub = null; | ||
_this.state = { | ||
@@ -95,8 +49,5 @@ isApiReady: false, | ||
} | ||
var _proto = HCaptcha.prototype; | ||
_proto.componentDidMount = function componentDidMount() { | ||
var _this2 = this; | ||
// Once captcha is mounted intialize hCaptcha - hCaptcha | ||
@@ -107,2 +58,8 @@ var element = getMountElement(this.props.scriptLocation); | ||
var isApiReady = typeof this._hcaptcha !== 'undefined'; | ||
this.sentryHub = initSentry(this.props.sentry, scopeTag); | ||
this.sentryHub.addBreadcrumb({ | ||
category: scopeTag.value, | ||
message: breadcrumbMessages.mounted | ||
}); | ||
/* | ||
@@ -113,3 +70,2 @@ * Check if hCaptcha has already been loaded, | ||
*/ | ||
if (isApiReady) { | ||
@@ -123,19 +79,19 @@ this.setState({ | ||
} | ||
this.loadCaptcha(); | ||
}; | ||
_proto.componentWillUnmount = function componentWillUnmount() { | ||
var captchaId = this.state.captchaId; | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} // Reset any stored variables / timers when unmounting | ||
} | ||
// Reset any stored variables / timers when unmounting | ||
hcaptcha.reset(captchaId); | ||
hcaptcha.remove(captchaId); | ||
this.sentryHub.addBreadcrumb({ | ||
category: scopeTag.value, | ||
message: breadcrumbMessages.unmounted | ||
}); | ||
}; | ||
_proto.shouldComponentUpdate = function shouldComponentUpdate(nextProps, nextState) { | ||
@@ -146,16 +102,14 @@ // Prevent component re-rendering when these internal state variables are updated | ||
} | ||
return true; | ||
}; | ||
_proto.componentDidUpdate = function componentDidUpdate(prevProps) { | ||
var _this3 = this; | ||
// Prop Keys that could change | ||
var keys = ['sitekey', 'size', 'theme', 'tabindex', 'languageOverride', 'endpoint']; // See if any props changed during component update | ||
var keys = ['sitekey', 'size', 'theme', 'tabindex', 'languageOverride', 'endpoint']; | ||
// See if any props changed during component update | ||
var match = keys.every(function (key) { | ||
return prevProps[key] === _this3.props[key]; | ||
}); // If they have changed, remove current captcha and render a new one | ||
}); | ||
// If they have changed, remove current captcha and render a new one | ||
if (!match) { | ||
@@ -167,3 +121,2 @@ this.removeCaptcha(function () { | ||
}; | ||
_proto.loadCaptcha = function loadCaptcha() { | ||
@@ -173,17 +126,19 @@ if (this.apiScriptRequested) { | ||
} | ||
var _this$props = this.props, | ||
apihost = _this$props.apihost, | ||
assethost = _this$props.assethost, | ||
endpoint = _this$props.endpoint, | ||
host = _this$props.host, | ||
imghost = _this$props.imghost, | ||
hl = _this$props.languageOverride, | ||
reCaptchaCompat = _this$props.reCaptchaCompat, | ||
reportapi = _this$props.reportapi, | ||
sentry = _this$props.sentry, | ||
custom = _this$props.custom, | ||
loadAsync = _this$props.loadAsync, | ||
scriptLocation = _this$props.scriptLocation; | ||
apihost = _this$props.apihost, | ||
assethost = _this$props.assethost, | ||
endpoint = _this$props.endpoint, | ||
host = _this$props.host, | ||
imghost = _this$props.imghost, | ||
hl = _this$props.languageOverride, | ||
reCaptchaCompat = _this$props.reCaptchaCompat, | ||
reportapi = _this$props.reportapi, | ||
sentry = _this$props.sentry, | ||
custom = _this$props.custom, | ||
loadAsync = _this$props.loadAsync, | ||
scriptLocation = _this$props.scriptLocation, | ||
_this$props$cleanup = _this$props.cleanup, | ||
cleanup = _this$props$cleanup === void 0 ? true : _this$props$cleanup; | ||
var mountParams = { | ||
render: 'explicit', | ||
apihost: apihost, | ||
@@ -195,3 +150,3 @@ assethost: assethost, | ||
imghost: imghost, | ||
recaptchacompat: reCaptchaCompat === false ? "off" : null, | ||
recaptchacompat: reCaptchaCompat === false ? 'off' : null, | ||
reportapi: reportapi, | ||
@@ -201,8 +156,8 @@ sentry: sentry, | ||
loadAsync: loadAsync, | ||
scriptLocation: scriptLocation | ||
scriptLocation: scriptLocation, | ||
cleanup: cleanup | ||
}; | ||
mountCaptchaScript(mountParams).then(this.handleOnLoad)["catch"](this.handleError); | ||
hCaptchaLoader(mountParams).then(this.handleOnLoad, this.handleError)["catch"](this.handleError); | ||
this.apiScriptRequested = true; | ||
}; | ||
_proto.renderCaptcha = function renderCaptcha(onReady) { | ||
@@ -222,4 +177,4 @@ var isApiReady = this.state.isApiReady; | ||
}); | ||
var hcaptcha = this._hcaptcha; //Render hCaptcha widget and provide necessary callbacks - hCaptcha | ||
var hcaptcha = this._hcaptcha; | ||
//Render hCaptcha widget and provide necessary callbacks - hCaptcha | ||
var captchaId = hcaptcha.render(this.ref.current, renderParams); | ||
@@ -233,23 +188,21 @@ this.setState({ | ||
}; | ||
_proto.resetCaptcha = function resetCaptcha() { | ||
var captchaId = this.state.captchaId; | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} // Reset captcha state, removes stored token and unticks checkbox | ||
} | ||
// Reset captcha state, removes stored token and unticks checkbox | ||
hcaptcha.reset(captchaId); | ||
this.sentryHub.addBreadcrumb({ | ||
category: scopeTag.value, | ||
message: breadcrumbMessages.reset | ||
}); | ||
}; | ||
_proto.removeCaptcha = function removeCaptcha(callback) { | ||
var captchaId = this.state.captchaId; | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} | ||
this.setState({ | ||
@@ -261,36 +214,39 @@ isRemoved: true | ||
}); | ||
this.sentryHub.addBreadcrumb({ | ||
category: scopeTag.value, | ||
message: breadcrumbMessages.removed | ||
}); | ||
}; | ||
_proto.handleOnLoad = function handleOnLoad() { | ||
var _this4 = this; | ||
this.setState({ | ||
isApiReady: true | ||
}, function () { | ||
var element = getMountElement(_this4.props.scriptLocation); | ||
var frame = getFrame(element); | ||
_this4._hcaptcha = frame.window.hcaptcha; // render captcha and wait for captcha id | ||
try { | ||
var element = getMountElement(_this4.props.scriptLocation); | ||
var frame = getFrame(element); | ||
_this4._hcaptcha = frame.window.hcaptcha; | ||
_this4.renderCaptcha(function () { | ||
// trigger onLoad if it exists | ||
var onLoad = _this4.props.onLoad; | ||
if (onLoad) onLoad(); | ||
}); | ||
// render captcha and wait for captcha id | ||
_this4.renderCaptcha(function () { | ||
// trigger onLoad if it exists | ||
var onLoad = _this4.props.onLoad; | ||
if (onLoad) onLoad(); | ||
}); | ||
} catch (error) { | ||
_this4.sentryHub.captureException(error); | ||
} | ||
}); | ||
}; | ||
_proto.handleSubmit = function handleSubmit(event) { | ||
var onVerify = this.props.onVerify; | ||
var _this$state = this.state, | ||
isRemoved = _this$state.isRemoved, | ||
captchaId = _this$state.captchaId; | ||
isRemoved = _this$state.isRemoved, | ||
captchaId = _this$state.captchaId; | ||
var hcaptcha = this._hcaptcha; | ||
if (typeof hcaptcha === 'undefined' || isRemoved) return; | ||
var token = hcaptcha.getResponse(captchaId); //Get response token from hCaptcha widget | ||
var ekey = hcaptcha.getRespKey(captchaId); //Get current challenge session id from hCaptcha widget | ||
if (onVerify) onVerify(token, ekey); //Dispatch event to verify user response | ||
}; | ||
_proto.handleExpire = function handleExpire() { | ||
@@ -300,12 +256,13 @@ var onExpire = this.props.onExpire; | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} | ||
hcaptcha.reset(captchaId); // If hCaptcha runs into error, reset captcha - hCaptcha | ||
if (onExpire) onExpire(); | ||
this.sentryHub.addBreadcrumb({ | ||
category: scopeTag.value, | ||
message: breadcrumbMessages.expired | ||
}); | ||
}; | ||
_proto.handleError = function handleError(event) { | ||
@@ -315,3 +272,2 @@ var onError = this.props.onError; | ||
var hcaptcha = this._hcaptcha; | ||
if (this.isReady()) { | ||
@@ -321,13 +277,10 @@ // If hCaptcha runs into error, reset captcha - hCaptcha | ||
} | ||
if (onError) onError(event); | ||
}; | ||
_proto.isReady = function isReady() { | ||
var _this$state2 = this.state, | ||
isApiReady = _this$state2.isApiReady, | ||
isRemoved = _this$state2.isRemoved; | ||
isApiReady = _this$state2.isApiReady, | ||
isRemoved = _this$state2.isRemoved; | ||
return isApiReady && !isRemoved; | ||
}; | ||
_proto.handleOpen = function handleOpen() { | ||
@@ -337,6 +290,4 @@ if (!this.isReady() || !this.props.onOpen) { | ||
} | ||
this.props.onOpen(); | ||
}; | ||
_proto.handleClose = function handleClose() { | ||
@@ -346,6 +297,4 @@ if (!this.isReady() || !this.props.onClose) { | ||
} | ||
this.props.onClose(); | ||
}; | ||
_proto.handleChallengeExpired = function handleChallengeExpired() { | ||
@@ -355,6 +304,4 @@ if (!this.isReady() || !this.props.onChalExpired) { | ||
} | ||
this.props.onChalExpired(); | ||
}; | ||
_proto.execute = function execute(opts) { | ||
@@ -364,32 +311,27 @@ if (opts === void 0) { | ||
} | ||
var captchaId = this.state.captchaId; | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
try { | ||
var captchaId = this.state.captchaId; | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} | ||
if (opts && typeof opts !== "object") { | ||
opts = null; | ||
} | ||
return hcaptcha.execute(captchaId, opts); | ||
} catch (error) { | ||
this.sentryHub.captureException(error); | ||
} | ||
if (opts && typeof opts !== "object") { | ||
opts = null; | ||
} | ||
return hcaptcha.execute(captchaId, opts); | ||
}; | ||
_proto.setData = function setData(data) { | ||
var captchaId = this.state.captchaId; | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} | ||
if (data && typeof data !== "object") { | ||
data = null; | ||
} | ||
hcaptcha.setData(captchaId, data); | ||
}; | ||
_proto.getResponse = function getResponse() { | ||
@@ -399,3 +341,2 @@ var hcaptcha = this._hcaptcha; | ||
}; | ||
_proto.getRespKey = function getRespKey() { | ||
@@ -405,3 +346,2 @@ var hcaptcha = this._hcaptcha; | ||
}; | ||
_proto.render = function render() { | ||
@@ -414,6 +354,4 @@ var elementId = this.state.elementId; | ||
}; | ||
return HCaptcha; | ||
}(React.Component); | ||
export default HCaptcha; |
@@ -1,15 +0,1 @@ | ||
function generateQuery(params) { | ||
return Object.entries(params).filter(function (_ref) { | ||
var key = _ref[0], | ||
value = _ref[1]; | ||
return value || value === false; | ||
}).map(function (_ref2) { | ||
var key = _ref2[0], | ||
value = _ref2[1]; | ||
return encodeURIComponent(key) + "=" + encodeURIComponent(value); | ||
}).join("&"); | ||
} | ||
; | ||
function getFrame(element) { | ||
@@ -23,7 +9,5 @@ var doc = element && element.ownerDocument || document; | ||
} | ||
function getMountElement(element) { | ||
return element || document.head; | ||
} | ||
export { generateQuery, getFrame, getMountElement }; | ||
export { getFrame, getMountElement }; |
"use strict"; | ||
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); | ||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -11,81 +9,23 @@ value: true | ||
exports["default"] = void 0; | ||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); | ||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); | ||
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); | ||
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); | ||
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); | ||
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); | ||
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); | ||
var React = _interopRequireWildcard(require("react")); | ||
var _loader = require("@hcaptcha/loader"); | ||
var _utils = require("./utils.js"); | ||
var _constants = require("./constants"); | ||
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; } | ||
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } | ||
var SCRIPT_ID = 'hcaptcha-api-script-id'; | ||
var HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad'; // Prevent loading API script multiple times | ||
var scripts = []; // Generate hCaptcha API script | ||
var mountCaptchaScript = function mountCaptchaScript() { | ||
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var element = (0, _utils.getMountElement)(params.scriptLocation); | ||
delete params.scriptLocation; | ||
var frame = (0, _utils.getFrame)(element); | ||
var script = scripts.find(function (_ref) { | ||
var scope = _ref.scope; | ||
return scope === frame.window; | ||
}); | ||
if (frame.document.getElementById(SCRIPT_ID) && script) { | ||
// API was already requested | ||
return script.promise; | ||
} | ||
var promise = new Promise(function (resolve, reject) { | ||
// Create global onload callback | ||
frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve; | ||
var domain = params.apihost || "https://js.hcaptcha.com"; | ||
delete params.apihost; | ||
var script = frame.document.createElement("script"); | ||
script.id = SCRIPT_ID; | ||
script.src = "".concat(domain, "/1/api.js?render=explicit&onload=").concat(HCAPTCHA_LOAD_FN_NAME); | ||
script.async = params.loadAsync !== undefined ? params.loadAsync : true; | ||
delete params.loadAsync; | ||
script.onerror = function (event) { | ||
return reject('script-error'); | ||
}; | ||
var query = (0, _utils.generateQuery)(params); | ||
script.src += query !== "" ? "&".concat(query) : ""; | ||
element.appendChild(script); | ||
}); | ||
scripts.push({ | ||
promise: promise, | ||
scope: frame.window | ||
}); | ||
return promise; | ||
}; | ||
var HCaptcha = /*#__PURE__*/function (_React$Component) { | ||
(0, _inherits2["default"])(HCaptcha, _React$Component); | ||
var _super = _createSuper(HCaptcha); | ||
function HCaptcha(props) { | ||
var _this; | ||
(0, _classCallCheck2["default"])(this, HCaptcha); | ||
_this = _super.call(this, props); | ||
/** | ||
@@ -97,10 +37,11 @@ * Internal reference to track hCaptcha API | ||
*/ | ||
_this._hcaptcha = undefined; | ||
_this._hcaptcha = undefined; // API Methods | ||
// API Methods | ||
_this.renderCaptcha = _this.renderCaptcha.bind((0, _assertThisInitialized2["default"])(_this)); | ||
_this.resetCaptcha = _this.resetCaptcha.bind((0, _assertThisInitialized2["default"])(_this)); | ||
_this.removeCaptcha = _this.removeCaptcha.bind((0, _assertThisInitialized2["default"])(_this)); | ||
_this.isReady = _this.isReady.bind((0, _assertThisInitialized2["default"])(_this)); // Event Handlers | ||
_this.isReady = _this.isReady.bind((0, _assertThisInitialized2["default"])(_this)); | ||
// Event Handlers | ||
_this.loadCaptcha = _this.loadCaptcha.bind((0, _assertThisInitialized2["default"])(_this)); | ||
@@ -116,2 +57,3 @@ _this.handleOnLoad = _this.handleOnLoad.bind((0, _assertThisInitialized2["default"])(_this)); | ||
_this.apiScriptRequested = false; | ||
_this.sentryHub = null; | ||
_this.state = { | ||
@@ -125,3 +67,2 @@ isApiReady: false, | ||
} | ||
(0, _createClass2["default"])(HCaptcha, [{ | ||
@@ -131,3 +72,2 @@ key: "componentDidMount", | ||
var _this2 = this; | ||
// Once captcha is mounted intialize hCaptcha - hCaptcha | ||
@@ -138,2 +78,8 @@ var element = (0, _utils.getMountElement)(this.props.scriptLocation); | ||
var isApiReady = typeof this._hcaptcha !== 'undefined'; | ||
this.sentryHub = (0, _loader.initSentry)(this.props.sentry, _constants.scopeTag); | ||
this.sentryHub.addBreadcrumb({ | ||
category: _constants.scopeTag.value, | ||
message: _constants.breadcrumbMessages.mounted | ||
}); | ||
/* | ||
@@ -144,3 +90,2 @@ * Check if hCaptcha has already been loaded, | ||
*/ | ||
if (isApiReady) { | ||
@@ -154,3 +99,2 @@ this.setState({ | ||
} | ||
this.loadCaptcha(); | ||
@@ -163,10 +107,13 @@ } | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} // Reset any stored variables / timers when unmounting | ||
} | ||
// Reset any stored variables / timers when unmounting | ||
hcaptcha.reset(captchaId); | ||
hcaptcha.remove(captchaId); | ||
this.sentryHub.addBreadcrumb({ | ||
category: _constants.scopeTag.value, | ||
message: _constants.breadcrumbMessages.unmounted | ||
}); | ||
} | ||
@@ -180,3 +127,2 @@ }, { | ||
} | ||
return true; | ||
@@ -188,10 +134,10 @@ } | ||
var _this3 = this; | ||
// Prop Keys that could change | ||
var keys = ['sitekey', 'size', 'theme', 'tabindex', 'languageOverride', 'endpoint']; // See if any props changed during component update | ||
var keys = ['sitekey', 'size', 'theme', 'tabindex', 'languageOverride', 'endpoint']; | ||
// See if any props changed during component update | ||
var match = keys.every(function (key) { | ||
return prevProps[key] === _this3.props[key]; | ||
}); // If they have changed, remove current captcha and render a new one | ||
}); | ||
// If they have changed, remove current captcha and render a new one | ||
if (!match) { | ||
@@ -209,17 +155,19 @@ this.removeCaptcha(function () { | ||
} | ||
var _this$props = this.props, | ||
apihost = _this$props.apihost, | ||
assethost = _this$props.assethost, | ||
endpoint = _this$props.endpoint, | ||
host = _this$props.host, | ||
imghost = _this$props.imghost, | ||
hl = _this$props.languageOverride, | ||
reCaptchaCompat = _this$props.reCaptchaCompat, | ||
reportapi = _this$props.reportapi, | ||
sentry = _this$props.sentry, | ||
custom = _this$props.custom, | ||
loadAsync = _this$props.loadAsync, | ||
scriptLocation = _this$props.scriptLocation; | ||
apihost = _this$props.apihost, | ||
assethost = _this$props.assethost, | ||
endpoint = _this$props.endpoint, | ||
host = _this$props.host, | ||
imghost = _this$props.imghost, | ||
hl = _this$props.languageOverride, | ||
reCaptchaCompat = _this$props.reCaptchaCompat, | ||
reportapi = _this$props.reportapi, | ||
sentry = _this$props.sentry, | ||
custom = _this$props.custom, | ||
loadAsync = _this$props.loadAsync, | ||
scriptLocation = _this$props.scriptLocation, | ||
_this$props$cleanup = _this$props.cleanup, | ||
cleanup = _this$props$cleanup === void 0 ? true : _this$props$cleanup; | ||
var mountParams = { | ||
render: 'explicit', | ||
apihost: apihost, | ||
@@ -231,3 +179,3 @@ assethost: assethost, | ||
imghost: imghost, | ||
recaptchacompat: reCaptchaCompat === false ? "off" : null, | ||
recaptchacompat: reCaptchaCompat === false ? 'off' : null, | ||
reportapi: reportapi, | ||
@@ -237,5 +185,6 @@ sentry: sentry, | ||
loadAsync: loadAsync, | ||
scriptLocation: scriptLocation | ||
scriptLocation: scriptLocation, | ||
cleanup: cleanup | ||
}; | ||
mountCaptchaScript(mountParams).then(this.handleOnLoad)["catch"](this.handleError); | ||
(0, _loader.hCaptchaLoader)(mountParams).then(this.handleOnLoad, this.handleError)["catch"](this.handleError); | ||
this.apiScriptRequested = true; | ||
@@ -259,4 +208,4 @@ } | ||
}); | ||
var hcaptcha = this._hcaptcha; //Render hCaptcha widget and provide necessary callbacks - hCaptcha | ||
var hcaptcha = this._hcaptcha; | ||
//Render hCaptcha widget and provide necessary callbacks - hCaptcha | ||
var captchaId = hcaptcha.render(this.ref.current, renderParams); | ||
@@ -275,9 +224,11 @@ this.setState({ | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} // Reset captcha state, removes stored token and unticks checkbox | ||
} | ||
// Reset captcha state, removes stored token and unticks checkbox | ||
hcaptcha.reset(captchaId); | ||
this.sentryHub.addBreadcrumb({ | ||
category: _constants.scopeTag.value, | ||
message: _constants.breadcrumbMessages.reset | ||
}); | ||
} | ||
@@ -289,7 +240,5 @@ }, { | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} | ||
this.setState({ | ||
@@ -301,2 +250,6 @@ isRemoved: true | ||
}); | ||
this.sentryHub.addBreadcrumb({ | ||
category: _constants.scopeTag.value, | ||
message: _constants.breadcrumbMessages.removed | ||
}); | ||
} | ||
@@ -307,15 +260,19 @@ }, { | ||
var _this4 = this; | ||
this.setState({ | ||
isApiReady: true | ||
}, function () { | ||
var element = (0, _utils.getMountElement)(_this4.props.scriptLocation); | ||
var frame = (0, _utils.getFrame)(element); | ||
_this4._hcaptcha = frame.window.hcaptcha; // render captcha and wait for captcha id | ||
try { | ||
var element = (0, _utils.getMountElement)(_this4.props.scriptLocation); | ||
var frame = (0, _utils.getFrame)(element); | ||
_this4._hcaptcha = frame.window.hcaptcha; | ||
_this4.renderCaptcha(function () { | ||
// trigger onLoad if it exists | ||
var onLoad = _this4.props.onLoad; | ||
if (onLoad) onLoad(); | ||
}); | ||
// render captcha and wait for captcha id | ||
_this4.renderCaptcha(function () { | ||
// trigger onLoad if it exists | ||
var onLoad = _this4.props.onLoad; | ||
if (onLoad) onLoad(); | ||
}); | ||
} catch (error) { | ||
_this4.sentryHub.captureException(error); | ||
} | ||
}); | ||
@@ -328,10 +285,8 @@ } | ||
var _this$state = this.state, | ||
isRemoved = _this$state.isRemoved, | ||
captchaId = _this$state.captchaId; | ||
isRemoved = _this$state.isRemoved, | ||
captchaId = _this$state.captchaId; | ||
var hcaptcha = this._hcaptcha; | ||
if (typeof hcaptcha === 'undefined' || isRemoved) return; | ||
var token = hcaptcha.getResponse(captchaId); //Get response token from hCaptcha widget | ||
var ekey = hcaptcha.getRespKey(captchaId); //Get current challenge session id from hCaptcha widget | ||
if (onVerify) onVerify(token, ekey); //Dispatch event to verify user response | ||
@@ -345,10 +300,12 @@ } | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} | ||
hcaptcha.reset(captchaId); // If hCaptcha runs into error, reset captcha - hCaptcha | ||
if (onExpire) onExpire(); | ||
this.sentryHub.addBreadcrumb({ | ||
category: _constants.scopeTag.value, | ||
message: _constants.breadcrumbMessages.expired | ||
}); | ||
} | ||
@@ -361,3 +318,2 @@ }, { | ||
var hcaptcha = this._hcaptcha; | ||
if (this.isReady()) { | ||
@@ -367,3 +323,2 @@ // If hCaptcha runs into error, reset captcha - hCaptcha | ||
} | ||
if (onError) onError(event); | ||
@@ -375,4 +330,4 @@ } | ||
var _this$state2 = this.state, | ||
isApiReady = _this$state2.isApiReady, | ||
isRemoved = _this$state2.isRemoved; | ||
isApiReady = _this$state2.isApiReady, | ||
isRemoved = _this$state2.isRemoved; | ||
return isApiReady && !isRemoved; | ||
@@ -386,3 +341,2 @@ } | ||
} | ||
this.props.onOpen(); | ||
@@ -396,3 +350,2 @@ } | ||
} | ||
this.props.onClose(); | ||
@@ -406,3 +359,2 @@ } | ||
} | ||
this.props.onChalExpired(); | ||
@@ -414,14 +366,15 @@ } | ||
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; | ||
var captchaId = this.state.captchaId; | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
try { | ||
var captchaId = this.state.captchaId; | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} | ||
if (opts && (0, _typeof2["default"])(opts) !== "object") { | ||
opts = null; | ||
} | ||
return hcaptcha.execute(captchaId, opts); | ||
} catch (error) { | ||
this.sentryHub.captureException(error); | ||
} | ||
if (opts && (0, _typeof2["default"])(opts) !== "object") { | ||
opts = null; | ||
} | ||
return hcaptcha.execute(captchaId, opts); | ||
} | ||
@@ -433,11 +386,8 @@ }, { | ||
var hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} | ||
if (data && (0, _typeof2["default"])(data) !== "object") { | ||
data = null; | ||
} | ||
hcaptcha.setData(captchaId, data); | ||
@@ -469,5 +419,4 @@ } | ||
}(React.Component); | ||
var _default = HCaptcha; | ||
exports["default"] = _default; | ||
module.exports = exports.default; |
"use strict"; | ||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.generateQuery = generateQuery; | ||
exports.getFrame = getFrame; | ||
exports.getMountElement = getMountElement; | ||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); | ||
function generateQuery(params) { | ||
return Object.entries(params).filter(function (_ref) { | ||
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2), | ||
key = _ref2[0], | ||
value = _ref2[1]; | ||
return value || value === false; | ||
}).map(function (_ref3) { | ||
var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2), | ||
key = _ref4[0], | ||
value = _ref4[1]; | ||
return "".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value)); | ||
}).join("&"); | ||
} | ||
; | ||
function getFrame(element) { | ||
@@ -40,5 +16,4 @@ var doc = element && element.ownerDocument || document; | ||
} | ||
function getMountElement(element) { | ||
return element || document.head; | ||
} |
{ | ||
"name": "@hcaptcha/react-hcaptcha", | ||
"version": "1.8.1", | ||
"version": "1.9.0", | ||
"types": "types/index.d.ts", | ||
@@ -61,4 +61,5 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"@babel/runtime": "^7.17.9" | ||
"@babel/runtime": "^7.17.9", | ||
"@hcaptcha/loader": "^1.0.8" | ||
} | ||
} |
@@ -141,2 +141,3 @@ # React hCaptcha Component Library | ||
|`sentry`|String|No|`-`|See enterprise docs.| | ||
| `cleanup` | Boolean | No | `true` | Remove script tag after setup.| | ||
|`custom`|Boolean|No|`-`|See enterprise docs.| | ||
@@ -143,0 +144,0 @@ |`loadAsync`|Boolean|No|`true`|Set if the script should be loaded asynchronously.| |
135
src/index.js
import * as React from 'react'; | ||
import { generateQuery, getFrame, getMountElement } from './utils.js'; | ||
import { hCaptchaLoader, initSentry } from '@hcaptcha/loader'; | ||
const SCRIPT_ID = 'hcaptcha-api-script-id'; | ||
const HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad'; | ||
import { getFrame, getMountElement } from './utils.js'; | ||
import { breadcrumbMessages, scopeTag } from "./constants"; | ||
// Prevent loading API script multiple times | ||
const scripts = []; | ||
// Generate hCaptcha API script | ||
const mountCaptchaScript = (params = {}) => { | ||
const element = getMountElement(params.scriptLocation); | ||
delete params.scriptLocation; | ||
const frame = getFrame(element); | ||
const script = scripts.find(({ scope }) => scope === frame.window); | ||
if (frame.document.getElementById(SCRIPT_ID) && script) { | ||
// API was already requested | ||
return script.promise; | ||
} | ||
const promise = new Promise((resolve, reject) => { | ||
// Create global onload callback | ||
frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve; | ||
const domain = params.apihost || "https://js.hcaptcha.com"; | ||
delete params.apihost; | ||
const script = frame.document.createElement("script"); | ||
script.id = SCRIPT_ID; | ||
script.src = `${domain}/1/api.js?render=explicit&onload=${HCAPTCHA_LOAD_FN_NAME}`; | ||
script.async = params.loadAsync !== undefined? params.loadAsync : true; | ||
delete params.loadAsync; | ||
script.onerror = (event) => reject('script-error'); | ||
const query = generateQuery(params); | ||
script.src += query !== ""? `&${query}` : ""; | ||
element.appendChild(script); | ||
}); | ||
scripts.push({ promise, scope: frame.window }); | ||
return promise; | ||
}; | ||
class HCaptcha extends React.Component { | ||
@@ -81,2 +38,3 @@ constructor (props) { | ||
this.apiScriptRequested = false; | ||
this.sentryHub = null; | ||
@@ -98,2 +56,9 @@ this.state = { | ||
this.sentryHub = initSentry(this.props.sentry, scopeTag); | ||
this.sentryHub.addBreadcrumb({ | ||
category: scopeTag.value, | ||
message: breadcrumbMessages.mounted, | ||
}); | ||
/* | ||
@@ -131,2 +96,7 @@ * Check if hCaptcha has already been loaded, | ||
hcaptcha.remove(captchaId); | ||
this.sentryHub.addBreadcrumb({ | ||
category: scopeTag.value, | ||
message: breadcrumbMessages.unmounted, | ||
}); | ||
} | ||
@@ -174,5 +144,7 @@ | ||
loadAsync, | ||
scriptLocation | ||
scriptLocation, | ||
cleanup = true, | ||
} = this.props; | ||
const mountParams = { | ||
render: 'explicit', | ||
apihost, | ||
@@ -184,3 +156,3 @@ assethost, | ||
imghost, | ||
recaptchacompat: reCaptchaCompat === false? "off" : null, | ||
recaptchacompat: reCaptchaCompat === false? 'off' : null, | ||
reportapi, | ||
@@ -191,7 +163,9 @@ sentry, | ||
scriptLocation, | ||
cleanup | ||
}; | ||
mountCaptchaScript(mountParams) | ||
.then(this.handleOnLoad) | ||
.catch(this.handleError); | ||
hCaptchaLoader(mountParams) | ||
.then(this.handleOnLoad, this.handleError) | ||
.catch(this.handleError); | ||
this.apiScriptRequested = true; | ||
@@ -234,2 +208,7 @@ } | ||
hcaptcha.reset(captchaId) | ||
this.sentryHub.addBreadcrumb({ | ||
category: scopeTag.value, | ||
message: breadcrumbMessages.reset, | ||
}); | ||
} | ||
@@ -249,17 +228,29 @@ | ||
}); | ||
this.sentryHub.addBreadcrumb({ | ||
category: scopeTag.value, | ||
message: breadcrumbMessages.removed, | ||
}); | ||
} | ||
handleOnLoad () { | ||
handleOnLoad () { | ||
this.setState({ isApiReady: true }, () => { | ||
const element = getMountElement(this.props.scriptLocation); | ||
const frame = getFrame(element); | ||
try { | ||
const element = getMountElement(this.props.scriptLocation); | ||
const frame = getFrame(element); | ||
this._hcaptcha = frame.window.hcaptcha; | ||
this._hcaptcha = frame.window.hcaptcha; | ||
// render captcha and wait for captcha id | ||
this.renderCaptcha(() => { | ||
// render captcha and wait for captcha id | ||
this.renderCaptcha(() => { | ||
// trigger onLoad if it exists | ||
const { onLoad } = this.props; | ||
if (onLoad) onLoad(); | ||
}); | ||
}); | ||
} catch (error) { | ||
this.sentryHub.captureException(error); | ||
} | ||
}); | ||
@@ -292,2 +283,7 @@ } | ||
if (onExpire) onExpire(); | ||
this.sentryHub.addBreadcrumb({ | ||
category: scopeTag.value, | ||
message: breadcrumbMessages.expired, | ||
}); | ||
} | ||
@@ -339,14 +335,19 @@ | ||
execute (opts = null) { | ||
const { captchaId } = this.state; | ||
const hcaptcha = this._hcaptcha; | ||
try { | ||
const { captchaId } = this.state; | ||
const hcaptcha = this._hcaptcha; | ||
if (!this.isReady()) { | ||
return; | ||
} | ||
if (opts && typeof opts !== "object") { | ||
opts = null; | ||
if (!this.isReady()) { | ||
return; | ||
} | ||
if (opts && typeof opts !== "object") { | ||
opts = null; | ||
} | ||
return hcaptcha.execute(captchaId, opts); | ||
} catch (error) { | ||
this.sentryHub.captureException(error); | ||
} | ||
return hcaptcha.execute(captchaId, opts); | ||
} | ||
@@ -353,0 +354,0 @@ |
@@ -1,9 +0,1 @@ | ||
function generateQuery(params) { | ||
return Object.entries(params) | ||
.filter(([key, value]) => value || value === false) | ||
.map(([key, value]) => { | ||
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}` | ||
}).join("&"); | ||
}; | ||
function getFrame(element) { | ||
@@ -21,5 +13,4 @@ const doc = (element && element.ownerDocument) || document; | ||
export { | ||
generateQuery, | ||
getFrame, | ||
getMountElement | ||
}; | ||
}; |
@@ -33,2 +33,4 @@ // Type definitions for @hcaptcha/react-hcaptcha 0.1 | ||
scriptLocation?: HTMLElement | null; | ||
sentry?: boolean; | ||
cleanup?: boolean; | ||
} | ||
@@ -35,0 +37,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
13
1133
224
51419
4
+ Added@hcaptcha/loader@^1.0.8
+ Added@hcaptcha/loader@1.2.4(transitive)