@hcaptcha/react-hcaptcha 1.8.1 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/constants.js +19 -0
- package/dist/esm/constants.js +11 -0
- package/dist/esm/index.js +90 -152
- package/dist/esm/utils.js +1 -17
- package/dist/index.js +89 -140
- package/dist/utils.js +0 -25
- package/package.json +3 -2
- package/src/constants.js +13 -0
- package/src/index.js +68 -67
- package/src/utils.js +1 -10
- package/types/index.d.ts +2 -0
package/README.md
CHANGED
|
@@ -138,6 +138,7 @@ return <HCaptcha ref={captchaRef} onLoad={onLoad} sitekey={sitekey} {...props} /
|
|
|
138
138
|
|`imghost`|String|No|`-`|See enterprise docs.|
|
|
139
139
|
|`reportapi`|String|No|`-`|See enterprise docs.|
|
|
140
140
|
|`sentry`|String|No|`-`|See enterprise docs.|
|
|
141
|
+
| `cleanup` | Boolean | No | `true` | Remove script tag after setup.|
|
|
141
142
|
|`custom`|Boolean|No|`-`|See enterprise docs.|
|
|
142
143
|
|`loadAsync`|Boolean|No|`true`|Set if the script should be loaded asynchronously.|
|
|
143
144
|
|`scriptLocation`|Element|No|`document.head`| Location of where to append the script tag. Make sure to add it to an area that will persist to prevent loading multiple times in the same document view. Note: If `null` is provided, the `document.head` will be used.|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.breadcrumbMessages = exports.scopeTag = void 0;
|
|
7
|
+
var scopeTag = {
|
|
8
|
+
key: 'source',
|
|
9
|
+
value: '@hCaptcha/react'
|
|
10
|
+
};
|
|
11
|
+
exports.scopeTag = scopeTag;
|
|
12
|
+
var breadcrumbMessages = {
|
|
13
|
+
mounted: 'hCaptcha component mounted',
|
|
14
|
+
expired: 'hCaptcha expired',
|
|
15
|
+
unmounted: 'hCaptcha component unmounted',
|
|
16
|
+
reset: 'hCaptcha reset',
|
|
17
|
+
removed: 'hCaptcha removed'
|
|
18
|
+
};
|
|
19
|
+
exports.breadcrumbMessages = breadcrumbMessages;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export var scopeTag = {
|
|
2
|
+
key: 'source',
|
|
3
|
+
value: '@hCaptcha/react'
|
|
4
|
+
};
|
|
5
|
+
export var breadcrumbMessages = {
|
|
6
|
+
mounted: 'hCaptcha component mounted',
|
|
7
|
+
expired: 'hCaptcha expired',
|
|
8
|
+
unmounted: 'hCaptcha component unmounted',
|
|
9
|
+
reset: 'hCaptcha reset',
|
|
10
|
+
removed: 'hCaptcha removed'
|
|
11
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -1,77 +1,30 @@
|
|
|
1
1
|
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
|
|
2
2
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
var scripts = []; // Generate hCaptcha API script
|
|
9
|
-
|
|
10
|
-
var mountCaptchaScript = function mountCaptchaScript(params) {
|
|
11
|
-
if (params === void 0) {
|
|
12
|
-
params = {};
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
var element = getMountElement(params.scriptLocation);
|
|
16
|
-
delete params.scriptLocation;
|
|
17
|
-
var frame = getFrame(element);
|
|
18
|
-
var script = scripts.find(function (_ref) {
|
|
19
|
-
var scope = _ref.scope;
|
|
20
|
-
return scope === frame.window;
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
if (frame.document.getElementById(SCRIPT_ID) && script) {
|
|
24
|
-
// API was already requested
|
|
25
|
-
return script.promise;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
var promise = new Promise(function (resolve, reject) {
|
|
29
|
-
// Create global onload callback
|
|
30
|
-
frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve;
|
|
31
|
-
var domain = params.apihost || "https://js.hcaptcha.com";
|
|
32
|
-
delete params.apihost;
|
|
33
|
-
var script = frame.document.createElement("script");
|
|
34
|
-
script.id = SCRIPT_ID;
|
|
35
|
-
script.src = domain + "/1/api.js?render=explicit&onload=" + HCAPTCHA_LOAD_FN_NAME;
|
|
36
|
-
script.async = params.loadAsync !== undefined ? params.loadAsync : true;
|
|
37
|
-
delete params.loadAsync;
|
|
38
|
-
|
|
39
|
-
script.onerror = function (event) {
|
|
40
|
-
return reject('script-error');
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
var query = generateQuery(params);
|
|
44
|
-
script.src += query !== "" ? "&" + query : "";
|
|
45
|
-
element.appendChild(script);
|
|
46
|
-
});
|
|
47
|
-
scripts.push({
|
|
48
|
-
promise: promise,
|
|
49
|
-
scope: frame.window
|
|
50
|
-
});
|
|
51
|
-
return promise;
|
|
52
|
-
};
|
|
53
|
-
|
|
4
|
+
import { hCaptchaLoader, initSentry } from '@hcaptcha/loader';
|
|
5
|
+
import { getFrame, getMountElement } from './utils.js';
|
|
6
|
+
import { breadcrumbMessages, scopeTag } from "./constants";
|
|
54
7
|
var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
55
8
|
_inheritsLoose(HCaptcha, _React$Component);
|
|
56
|
-
|
|
57
9
|
function HCaptcha(props) {
|
|
58
10
|
var _this;
|
|
59
|
-
|
|
60
11
|
_this = _React$Component.call(this, props) || this;
|
|
12
|
+
|
|
61
13
|
/**
|
|
62
14
|
* Internal reference to track hCaptcha API
|
|
63
15
|
*
|
|
64
16
|
* Required as window is relative to initialization in application
|
|
65
17
|
* not where the script and iFrames have been loaded.
|
|
66
18
|
*/
|
|
19
|
+
_this._hcaptcha = undefined;
|
|
67
20
|
|
|
68
|
-
|
|
69
|
-
|
|
21
|
+
// API Methods
|
|
70
22
|
_this.renderCaptcha = _this.renderCaptcha.bind(_assertThisInitialized(_this));
|
|
71
23
|
_this.resetCaptcha = _this.resetCaptcha.bind(_assertThisInitialized(_this));
|
|
72
24
|
_this.removeCaptcha = _this.removeCaptcha.bind(_assertThisInitialized(_this));
|
|
73
|
-
_this.isReady = _this.isReady.bind(_assertThisInitialized(_this));
|
|
25
|
+
_this.isReady = _this.isReady.bind(_assertThisInitialized(_this));
|
|
74
26
|
|
|
27
|
+
// Event Handlers
|
|
75
28
|
_this.loadCaptcha = _this.loadCaptcha.bind(_assertThisInitialized(_this));
|
|
76
29
|
_this.handleOnLoad = _this.handleOnLoad.bind(_assertThisInitialized(_this));
|
|
77
30
|
_this.handleSubmit = _this.handleSubmit.bind(_assertThisInitialized(_this));
|
|
@@ -82,6 +35,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
82
35
|
_this.handleChallengeExpired = _this.handleChallengeExpired.bind(_assertThisInitialized(_this));
|
|
83
36
|
_this.ref = /*#__PURE__*/React.createRef();
|
|
84
37
|
_this.apiScriptRequested = false;
|
|
38
|
+
_this.sentryHub = null;
|
|
85
39
|
_this.state = {
|
|
86
40
|
isApiReady: false,
|
|
87
41
|
isRemoved: false,
|
|
@@ -90,23 +44,25 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
90
44
|
};
|
|
91
45
|
return _this;
|
|
92
46
|
}
|
|
93
|
-
|
|
94
47
|
var _proto = HCaptcha.prototype;
|
|
95
|
-
|
|
96
48
|
_proto.componentDidMount = function componentDidMount() {
|
|
97
49
|
var _this2 = this;
|
|
98
|
-
|
|
99
50
|
// Once captcha is mounted intialize hCaptcha - hCaptcha
|
|
100
51
|
var element = getMountElement(this.props.scriptLocation);
|
|
101
52
|
var frame = getFrame(element);
|
|
102
53
|
this._hcaptcha = frame.window.hcaptcha || undefined;
|
|
103
54
|
var isApiReady = typeof this._hcaptcha !== 'undefined';
|
|
55
|
+
this.sentryHub = initSentry(this.props.sentry, scopeTag);
|
|
56
|
+
this.sentryHub.addBreadcrumb({
|
|
57
|
+
category: scopeTag.value,
|
|
58
|
+
message: breadcrumbMessages.mounted
|
|
59
|
+
});
|
|
60
|
+
|
|
104
61
|
/*
|
|
105
62
|
* Check if hCaptcha has already been loaded,
|
|
106
63
|
* If Yes, render the captcha
|
|
107
64
|
* If No, create script tag and wait to render the captcha
|
|
108
65
|
*/
|
|
109
|
-
|
|
110
66
|
if (isApiReady) {
|
|
111
67
|
this.setState({
|
|
112
68
|
isApiReady: true
|
|
@@ -115,85 +71,84 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
115
71
|
});
|
|
116
72
|
return;
|
|
117
73
|
}
|
|
118
|
-
|
|
119
74
|
this.loadCaptcha();
|
|
120
75
|
};
|
|
121
|
-
|
|
122
76
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
|
123
77
|
var captchaId = this.state.captchaId;
|
|
124
78
|
var hcaptcha = this._hcaptcha;
|
|
125
|
-
|
|
126
79
|
if (!this.isReady()) {
|
|
127
80
|
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
81
|
+
}
|
|
130
82
|
|
|
83
|
+
// Reset any stored variables / timers when unmounting
|
|
131
84
|
hcaptcha.reset(captchaId);
|
|
132
85
|
hcaptcha.remove(captchaId);
|
|
86
|
+
this.sentryHub.addBreadcrumb({
|
|
87
|
+
category: scopeTag.value,
|
|
88
|
+
message: breadcrumbMessages.unmounted
|
|
89
|
+
});
|
|
133
90
|
};
|
|
134
|
-
|
|
135
91
|
_proto.shouldComponentUpdate = function shouldComponentUpdate(nextProps, nextState) {
|
|
136
92
|
// Prevent component re-rendering when these internal state variables are updated
|
|
137
93
|
if (this.state.isApiReady !== nextState.isApiReady || this.state.isRemoved !== nextState.isRemoved) {
|
|
138
94
|
return false;
|
|
139
95
|
}
|
|
140
|
-
|
|
141
96
|
return true;
|
|
142
97
|
};
|
|
143
|
-
|
|
144
98
|
_proto.componentDidUpdate = function componentDidUpdate(prevProps) {
|
|
145
99
|
var _this3 = this;
|
|
146
|
-
|
|
147
100
|
// Prop Keys that could change
|
|
148
|
-
var keys = ['sitekey', 'size', 'theme', 'tabindex', 'languageOverride', 'endpoint'];
|
|
149
|
-
|
|
101
|
+
var keys = ['sitekey', 'size', 'theme', 'tabindex', 'languageOverride', 'endpoint'];
|
|
102
|
+
// See if any props changed during component update
|
|
150
103
|
var match = keys.every(function (key) {
|
|
151
104
|
return prevProps[key] === _this3.props[key];
|
|
152
|
-
});
|
|
105
|
+
});
|
|
153
106
|
|
|
107
|
+
// If they have changed, remove current captcha and render a new one
|
|
154
108
|
if (!match) {
|
|
155
109
|
this.removeCaptcha(function () {
|
|
156
110
|
_this3.renderCaptcha();
|
|
157
111
|
});
|
|
158
112
|
}
|
|
159
113
|
};
|
|
160
|
-
|
|
161
114
|
_proto.loadCaptcha = function loadCaptcha() {
|
|
162
115
|
if (this.apiScriptRequested) {
|
|
163
116
|
return;
|
|
164
117
|
}
|
|
165
|
-
|
|
166
118
|
var _this$props = this.props,
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
119
|
+
apihost = _this$props.apihost,
|
|
120
|
+
assethost = _this$props.assethost,
|
|
121
|
+
endpoint = _this$props.endpoint,
|
|
122
|
+
host = _this$props.host,
|
|
123
|
+
imghost = _this$props.imghost,
|
|
124
|
+
hl = _this$props.languageOverride,
|
|
125
|
+
reCaptchaCompat = _this$props.reCaptchaCompat,
|
|
126
|
+
reportapi = _this$props.reportapi,
|
|
127
|
+
sentry = _this$props.sentry,
|
|
128
|
+
custom = _this$props.custom,
|
|
129
|
+
loadAsync = _this$props.loadAsync,
|
|
130
|
+
scriptLocation = _this$props.scriptLocation,
|
|
131
|
+
_this$props$cleanup = _this$props.cleanup,
|
|
132
|
+
cleanup = _this$props$cleanup === void 0 ? true : _this$props$cleanup;
|
|
179
133
|
var mountParams = {
|
|
134
|
+
render: 'explicit',
|
|
180
135
|
apihost: apihost,
|
|
181
136
|
assethost: assethost,
|
|
182
137
|
endpoint: endpoint,
|
|
183
138
|
hl: hl,
|
|
184
139
|
host: host,
|
|
185
140
|
imghost: imghost,
|
|
186
|
-
recaptchacompat: reCaptchaCompat === false ?
|
|
141
|
+
recaptchacompat: reCaptchaCompat === false ? 'off' : null,
|
|
187
142
|
reportapi: reportapi,
|
|
188
143
|
sentry: sentry,
|
|
189
144
|
custom: custom,
|
|
190
145
|
loadAsync: loadAsync,
|
|
191
|
-
scriptLocation: scriptLocation
|
|
146
|
+
scriptLocation: scriptLocation,
|
|
147
|
+
cleanup: cleanup
|
|
192
148
|
};
|
|
193
|
-
|
|
149
|
+
hCaptchaLoader(mountParams).then(this.handleOnLoad, this.handleError)["catch"](this.handleError);
|
|
194
150
|
this.apiScriptRequested = true;
|
|
195
151
|
};
|
|
196
|
-
|
|
197
152
|
_proto.renderCaptcha = function renderCaptcha(onReady) {
|
|
198
153
|
var isApiReady = this.state.isApiReady;
|
|
199
154
|
if (!isApiReady) return;
|
|
@@ -208,8 +163,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
208
163
|
hl: this.props.hl || this.props.languageOverride,
|
|
209
164
|
languageOverride: undefined
|
|
210
165
|
});
|
|
211
|
-
var hcaptcha = this._hcaptcha;
|
|
212
|
-
|
|
166
|
+
var hcaptcha = this._hcaptcha;
|
|
167
|
+
//Render hCaptcha widget and provide necessary callbacks - hCaptcha
|
|
213
168
|
var captchaId = hcaptcha.render(this.ref.current, renderParams);
|
|
214
169
|
this.setState({
|
|
215
170
|
isRemoved: false,
|
|
@@ -218,169 +173,154 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
218
173
|
onReady && onReady();
|
|
219
174
|
});
|
|
220
175
|
};
|
|
221
|
-
|
|
222
176
|
_proto.resetCaptcha = function resetCaptcha() {
|
|
223
177
|
var captchaId = this.state.captchaId;
|
|
224
178
|
var hcaptcha = this._hcaptcha;
|
|
225
|
-
|
|
226
179
|
if (!this.isReady()) {
|
|
227
180
|
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
|
|
181
|
+
}
|
|
182
|
+
// Reset captcha state, removes stored token and unticks checkbox
|
|
231
183
|
hcaptcha.reset(captchaId);
|
|
184
|
+
this.sentryHub.addBreadcrumb({
|
|
185
|
+
category: scopeTag.value,
|
|
186
|
+
message: breadcrumbMessages.reset
|
|
187
|
+
});
|
|
232
188
|
};
|
|
233
|
-
|
|
234
189
|
_proto.removeCaptcha = function removeCaptcha(callback) {
|
|
235
190
|
var captchaId = this.state.captchaId;
|
|
236
191
|
var hcaptcha = this._hcaptcha;
|
|
237
|
-
|
|
238
192
|
if (!this.isReady()) {
|
|
239
193
|
return;
|
|
240
194
|
}
|
|
241
|
-
|
|
242
195
|
this.setState({
|
|
243
196
|
isRemoved: true
|
|
244
197
|
}, function () {
|
|
245
198
|
hcaptcha.remove(captchaId);
|
|
246
199
|
callback && callback();
|
|
247
200
|
});
|
|
201
|
+
this.sentryHub.addBreadcrumb({
|
|
202
|
+
category: scopeTag.value,
|
|
203
|
+
message: breadcrumbMessages.removed
|
|
204
|
+
});
|
|
248
205
|
};
|
|
249
|
-
|
|
250
206
|
_proto.handleOnLoad = function handleOnLoad() {
|
|
251
207
|
var _this4 = this;
|
|
252
|
-
|
|
253
208
|
this.setState({
|
|
254
209
|
isApiReady: true
|
|
255
210
|
}, function () {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
//
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
211
|
+
try {
|
|
212
|
+
var element = getMountElement(_this4.props.scriptLocation);
|
|
213
|
+
var frame = getFrame(element);
|
|
214
|
+
_this4._hcaptcha = frame.window.hcaptcha;
|
|
215
|
+
|
|
216
|
+
// render captcha and wait for captcha id
|
|
217
|
+
_this4.renderCaptcha(function () {
|
|
218
|
+
// trigger onLoad if it exists
|
|
219
|
+
var onLoad = _this4.props.onLoad;
|
|
220
|
+
if (onLoad) onLoad();
|
|
221
|
+
});
|
|
222
|
+
} catch (error) {
|
|
223
|
+
_this4.sentryHub.captureException(error);
|
|
224
|
+
}
|
|
265
225
|
});
|
|
266
226
|
};
|
|
267
|
-
|
|
268
227
|
_proto.handleSubmit = function handleSubmit(event) {
|
|
269
228
|
var onVerify = this.props.onVerify;
|
|
270
229
|
var _this$state = this.state,
|
|
271
|
-
|
|
272
|
-
|
|
230
|
+
isRemoved = _this$state.isRemoved,
|
|
231
|
+
captchaId = _this$state.captchaId;
|
|
273
232
|
var hcaptcha = this._hcaptcha;
|
|
274
233
|
if (typeof hcaptcha === 'undefined' || isRemoved) return;
|
|
275
234
|
var token = hcaptcha.getResponse(captchaId); //Get response token from hCaptcha widget
|
|
276
|
-
|
|
277
235
|
var ekey = hcaptcha.getRespKey(captchaId); //Get current challenge session id from hCaptcha widget
|
|
278
|
-
|
|
279
236
|
if (onVerify) onVerify(token, ekey); //Dispatch event to verify user response
|
|
280
237
|
};
|
|
281
|
-
|
|
282
238
|
_proto.handleExpire = function handleExpire() {
|
|
283
239
|
var onExpire = this.props.onExpire;
|
|
284
240
|
var captchaId = this.state.captchaId;
|
|
285
241
|
var hcaptcha = this._hcaptcha;
|
|
286
|
-
|
|
287
242
|
if (!this.isReady()) {
|
|
288
243
|
return;
|
|
289
244
|
}
|
|
290
|
-
|
|
291
245
|
hcaptcha.reset(captchaId); // If hCaptcha runs into error, reset captcha - hCaptcha
|
|
292
246
|
|
|
293
247
|
if (onExpire) onExpire();
|
|
248
|
+
this.sentryHub.addBreadcrumb({
|
|
249
|
+
category: scopeTag.value,
|
|
250
|
+
message: breadcrumbMessages.expired
|
|
251
|
+
});
|
|
294
252
|
};
|
|
295
|
-
|
|
296
253
|
_proto.handleError = function handleError(event) {
|
|
297
254
|
var onError = this.props.onError;
|
|
298
255
|
var captchaId = this.state.captchaId;
|
|
299
256
|
var hcaptcha = this._hcaptcha;
|
|
300
|
-
|
|
301
257
|
if (this.isReady()) {
|
|
302
258
|
// If hCaptcha runs into error, reset captcha - hCaptcha
|
|
303
259
|
hcaptcha.reset(captchaId);
|
|
304
260
|
}
|
|
305
|
-
|
|
306
261
|
if (onError) onError(event);
|
|
307
262
|
};
|
|
308
|
-
|
|
309
263
|
_proto.isReady = function isReady() {
|
|
310
264
|
var _this$state2 = this.state,
|
|
311
|
-
|
|
312
|
-
|
|
265
|
+
isApiReady = _this$state2.isApiReady,
|
|
266
|
+
isRemoved = _this$state2.isRemoved;
|
|
313
267
|
return isApiReady && !isRemoved;
|
|
314
268
|
};
|
|
315
|
-
|
|
316
269
|
_proto.handleOpen = function handleOpen() {
|
|
317
270
|
if (!this.isReady() || !this.props.onOpen) {
|
|
318
271
|
return;
|
|
319
272
|
}
|
|
320
|
-
|
|
321
273
|
this.props.onOpen();
|
|
322
274
|
};
|
|
323
|
-
|
|
324
275
|
_proto.handleClose = function handleClose() {
|
|
325
276
|
if (!this.isReady() || !this.props.onClose) {
|
|
326
277
|
return;
|
|
327
278
|
}
|
|
328
|
-
|
|
329
279
|
this.props.onClose();
|
|
330
280
|
};
|
|
331
|
-
|
|
332
281
|
_proto.handleChallengeExpired = function handleChallengeExpired() {
|
|
333
282
|
if (!this.isReady() || !this.props.onChalExpired) {
|
|
334
283
|
return;
|
|
335
284
|
}
|
|
336
|
-
|
|
337
285
|
this.props.onChalExpired();
|
|
338
286
|
};
|
|
339
|
-
|
|
340
287
|
_proto.execute = function execute(opts) {
|
|
341
288
|
if (opts === void 0) {
|
|
342
289
|
opts = null;
|
|
343
290
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
291
|
+
try {
|
|
292
|
+
var captchaId = this.state.captchaId;
|
|
293
|
+
var hcaptcha = this._hcaptcha;
|
|
294
|
+
if (!this.isReady()) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (opts && typeof opts !== "object") {
|
|
298
|
+
opts = null;
|
|
299
|
+
}
|
|
300
|
+
return hcaptcha.execute(captchaId, opts);
|
|
301
|
+
} catch (error) {
|
|
302
|
+
this.sentryHub.captureException(error);
|
|
354
303
|
}
|
|
355
|
-
|
|
356
|
-
return hcaptcha.execute(captchaId, opts);
|
|
357
304
|
};
|
|
358
|
-
|
|
359
305
|
_proto.setData = function setData(data) {
|
|
360
306
|
var captchaId = this.state.captchaId;
|
|
361
307
|
var hcaptcha = this._hcaptcha;
|
|
362
|
-
|
|
363
308
|
if (!this.isReady()) {
|
|
364
309
|
return;
|
|
365
310
|
}
|
|
366
|
-
|
|
367
311
|
if (data && typeof data !== "object") {
|
|
368
312
|
data = null;
|
|
369
313
|
}
|
|
370
|
-
|
|
371
314
|
hcaptcha.setData(captchaId, data);
|
|
372
315
|
};
|
|
373
|
-
|
|
374
316
|
_proto.getResponse = function getResponse() {
|
|
375
317
|
var hcaptcha = this._hcaptcha;
|
|
376
318
|
return hcaptcha.getResponse(this.state.captchaId);
|
|
377
319
|
};
|
|
378
|
-
|
|
379
320
|
_proto.getRespKey = function getRespKey() {
|
|
380
321
|
var hcaptcha = this._hcaptcha;
|
|
381
322
|
return hcaptcha.getRespKey(this.state.captchaId);
|
|
382
323
|
};
|
|
383
|
-
|
|
384
324
|
_proto.render = function render() {
|
|
385
325
|
var elementId = this.state.elementId;
|
|
386
326
|
return /*#__PURE__*/React.createElement("div", {
|
|
@@ -388,8 +328,6 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
388
328
|
id: elementId
|
|
389
329
|
});
|
|
390
330
|
};
|
|
391
|
-
|
|
392
331
|
return HCaptcha;
|
|
393
332
|
}(React.Component);
|
|
394
|
-
|
|
395
333
|
export default HCaptcha;
|
package/dist/esm/utils.js
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
function generateQuery(params) {
|
|
2
|
-
return Object.entries(params).filter(function (_ref) {
|
|
3
|
-
var key = _ref[0],
|
|
4
|
-
value = _ref[1];
|
|
5
|
-
return value || value === false;
|
|
6
|
-
}).map(function (_ref2) {
|
|
7
|
-
var key = _ref2[0],
|
|
8
|
-
value = _ref2[1];
|
|
9
|
-
return encodeURIComponent(key) + "=" + encodeURIComponent(value);
|
|
10
|
-
}).join("&");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
;
|
|
14
|
-
|
|
15
1
|
function getFrame(element) {
|
|
16
2
|
var doc = element && element.ownerDocument || document;
|
|
17
3
|
var win = doc.defaultView || doc.parentWindow || window;
|
|
@@ -20,9 +6,7 @@ function getFrame(element) {
|
|
|
20
6
|
window: win
|
|
21
7
|
};
|
|
22
8
|
}
|
|
23
|
-
|
|
24
9
|
function getMountElement(element) {
|
|
25
10
|
return element || document.head;
|
|
26
11
|
}
|
|
27
|
-
|
|
28
|
-
export { generateQuery, getFrame, getMountElement };
|
|
12
|
+
export { getFrame, getMountElement };
|
package/dist/index.js
CHANGED
|
@@ -1,106 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
|
|
4
|
-
|
|
5
4
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
6
|
-
|
|
7
5
|
Object.defineProperty(exports, "__esModule", {
|
|
8
6
|
value: true
|
|
9
7
|
});
|
|
10
8
|
exports["default"] = void 0;
|
|
11
|
-
|
|
12
9
|
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
13
|
-
|
|
14
10
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
15
|
-
|
|
16
11
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
17
|
-
|
|
18
12
|
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
|
|
19
|
-
|
|
20
13
|
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
|
|
21
|
-
|
|
22
14
|
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
|
|
23
|
-
|
|
24
15
|
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
|
|
25
|
-
|
|
26
16
|
var React = _interopRequireWildcard(require("react"));
|
|
27
|
-
|
|
17
|
+
var _loader = require("@hcaptcha/loader");
|
|
28
18
|
var _utils = require("./utils.js");
|
|
29
|
-
|
|
19
|
+
var _constants = require("./constants");
|
|
30
20
|
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); }; }
|
|
31
|
-
|
|
32
21
|
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; } }
|
|
33
|
-
|
|
34
|
-
var SCRIPT_ID = 'hcaptcha-api-script-id';
|
|
35
|
-
var HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad'; // Prevent loading API script multiple times
|
|
36
|
-
|
|
37
|
-
var scripts = []; // Generate hCaptcha API script
|
|
38
|
-
|
|
39
|
-
var mountCaptchaScript = function mountCaptchaScript() {
|
|
40
|
-
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
41
|
-
var element = (0, _utils.getMountElement)(params.scriptLocation);
|
|
42
|
-
delete params.scriptLocation;
|
|
43
|
-
var frame = (0, _utils.getFrame)(element);
|
|
44
|
-
var script = scripts.find(function (_ref) {
|
|
45
|
-
var scope = _ref.scope;
|
|
46
|
-
return scope === frame.window;
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
if (frame.document.getElementById(SCRIPT_ID) && script) {
|
|
50
|
-
// API was already requested
|
|
51
|
-
return script.promise;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
var promise = new Promise(function (resolve, reject) {
|
|
55
|
-
// Create global onload callback
|
|
56
|
-
frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve;
|
|
57
|
-
var domain = params.apihost || "https://js.hcaptcha.com";
|
|
58
|
-
delete params.apihost;
|
|
59
|
-
var script = frame.document.createElement("script");
|
|
60
|
-
script.id = SCRIPT_ID;
|
|
61
|
-
script.src = "".concat(domain, "/1/api.js?render=explicit&onload=").concat(HCAPTCHA_LOAD_FN_NAME);
|
|
62
|
-
script.async = params.loadAsync !== undefined ? params.loadAsync : true;
|
|
63
|
-
delete params.loadAsync;
|
|
64
|
-
|
|
65
|
-
script.onerror = function (event) {
|
|
66
|
-
return reject('script-error');
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
var query = (0, _utils.generateQuery)(params);
|
|
70
|
-
script.src += query !== "" ? "&".concat(query) : "";
|
|
71
|
-
element.appendChild(script);
|
|
72
|
-
});
|
|
73
|
-
scripts.push({
|
|
74
|
-
promise: promise,
|
|
75
|
-
scope: frame.window
|
|
76
|
-
});
|
|
77
|
-
return promise;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
22
|
var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
81
23
|
(0, _inherits2["default"])(HCaptcha, _React$Component);
|
|
82
|
-
|
|
83
24
|
var _super = _createSuper(HCaptcha);
|
|
84
|
-
|
|
85
25
|
function HCaptcha(props) {
|
|
86
26
|
var _this;
|
|
87
|
-
|
|
88
27
|
(0, _classCallCheck2["default"])(this, HCaptcha);
|
|
89
28
|
_this = _super.call(this, props);
|
|
29
|
+
|
|
90
30
|
/**
|
|
91
31
|
* Internal reference to track hCaptcha API
|
|
92
32
|
*
|
|
93
33
|
* Required as window is relative to initialization in application
|
|
94
34
|
* not where the script and iFrames have been loaded.
|
|
95
35
|
*/
|
|
36
|
+
_this._hcaptcha = undefined;
|
|
96
37
|
|
|
97
|
-
|
|
98
|
-
|
|
38
|
+
// API Methods
|
|
99
39
|
_this.renderCaptcha = _this.renderCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
|
|
100
40
|
_this.resetCaptcha = _this.resetCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
|
|
101
41
|
_this.removeCaptcha = _this.removeCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
|
|
102
|
-
_this.isReady = _this.isReady.bind((0, _assertThisInitialized2["default"])(_this));
|
|
42
|
+
_this.isReady = _this.isReady.bind((0, _assertThisInitialized2["default"])(_this));
|
|
103
43
|
|
|
44
|
+
// Event Handlers
|
|
104
45
|
_this.loadCaptcha = _this.loadCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
|
|
105
46
|
_this.handleOnLoad = _this.handleOnLoad.bind((0, _assertThisInitialized2["default"])(_this));
|
|
106
47
|
_this.handleSubmit = _this.handleSubmit.bind((0, _assertThisInitialized2["default"])(_this));
|
|
@@ -111,6 +52,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
111
52
|
_this.handleChallengeExpired = _this.handleChallengeExpired.bind((0, _assertThisInitialized2["default"])(_this));
|
|
112
53
|
_this.ref = /*#__PURE__*/React.createRef();
|
|
113
54
|
_this.apiScriptRequested = false;
|
|
55
|
+
_this.sentryHub = null;
|
|
114
56
|
_this.state = {
|
|
115
57
|
isApiReady: false,
|
|
116
58
|
isRemoved: false,
|
|
@@ -119,23 +61,26 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
119
61
|
};
|
|
120
62
|
return _this;
|
|
121
63
|
}
|
|
122
|
-
|
|
123
64
|
(0, _createClass2["default"])(HCaptcha, [{
|
|
124
65
|
key: "componentDidMount",
|
|
125
66
|
value: function componentDidMount() {
|
|
126
67
|
var _this2 = this;
|
|
127
|
-
|
|
128
68
|
// Once captcha is mounted intialize hCaptcha - hCaptcha
|
|
129
69
|
var element = (0, _utils.getMountElement)(this.props.scriptLocation);
|
|
130
70
|
var frame = (0, _utils.getFrame)(element);
|
|
131
71
|
this._hcaptcha = frame.window.hcaptcha || undefined;
|
|
132
72
|
var isApiReady = typeof this._hcaptcha !== 'undefined';
|
|
73
|
+
this.sentryHub = (0, _loader.initSentry)(this.props.sentry, _constants.scopeTag);
|
|
74
|
+
this.sentryHub.addBreadcrumb({
|
|
75
|
+
category: _constants.scopeTag.value,
|
|
76
|
+
message: _constants.breadcrumbMessages.mounted
|
|
77
|
+
});
|
|
78
|
+
|
|
133
79
|
/*
|
|
134
80
|
* Check if hCaptcha has already been loaded,
|
|
135
81
|
* If Yes, render the captcha
|
|
136
82
|
* If No, create script tag and wait to render the captcha
|
|
137
83
|
*/
|
|
138
|
-
|
|
139
84
|
if (isApiReady) {
|
|
140
85
|
this.setState({
|
|
141
86
|
isApiReady: true
|
|
@@ -144,7 +89,6 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
144
89
|
});
|
|
145
90
|
return;
|
|
146
91
|
}
|
|
147
|
-
|
|
148
92
|
this.loadCaptcha();
|
|
149
93
|
}
|
|
150
94
|
}, {
|
|
@@ -152,14 +96,17 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
152
96
|
value: function componentWillUnmount() {
|
|
153
97
|
var captchaId = this.state.captchaId;
|
|
154
98
|
var hcaptcha = this._hcaptcha;
|
|
155
|
-
|
|
156
99
|
if (!this.isReady()) {
|
|
157
100
|
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
101
|
+
}
|
|
160
102
|
|
|
103
|
+
// Reset any stored variables / timers when unmounting
|
|
161
104
|
hcaptcha.reset(captchaId);
|
|
162
105
|
hcaptcha.remove(captchaId);
|
|
106
|
+
this.sentryHub.addBreadcrumb({
|
|
107
|
+
category: _constants.scopeTag.value,
|
|
108
|
+
message: _constants.breadcrumbMessages.unmounted
|
|
109
|
+
});
|
|
163
110
|
}
|
|
164
111
|
}, {
|
|
165
112
|
key: "shouldComponentUpdate",
|
|
@@ -168,21 +115,20 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
168
115
|
if (this.state.isApiReady !== nextState.isApiReady || this.state.isRemoved !== nextState.isRemoved) {
|
|
169
116
|
return false;
|
|
170
117
|
}
|
|
171
|
-
|
|
172
118
|
return true;
|
|
173
119
|
}
|
|
174
120
|
}, {
|
|
175
121
|
key: "componentDidUpdate",
|
|
176
122
|
value: function componentDidUpdate(prevProps) {
|
|
177
123
|
var _this3 = this;
|
|
178
|
-
|
|
179
124
|
// Prop Keys that could change
|
|
180
|
-
var keys = ['sitekey', 'size', 'theme', 'tabindex', 'languageOverride', 'endpoint'];
|
|
181
|
-
|
|
125
|
+
var keys = ['sitekey', 'size', 'theme', 'tabindex', 'languageOverride', 'endpoint'];
|
|
126
|
+
// See if any props changed during component update
|
|
182
127
|
var match = keys.every(function (key) {
|
|
183
128
|
return prevProps[key] === _this3.props[key];
|
|
184
|
-
});
|
|
129
|
+
});
|
|
185
130
|
|
|
131
|
+
// If they have changed, remove current captcha and render a new one
|
|
186
132
|
if (!match) {
|
|
187
133
|
this.removeCaptcha(function () {
|
|
188
134
|
_this3.renderCaptcha();
|
|
@@ -195,35 +141,38 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
195
141
|
if (this.apiScriptRequested) {
|
|
196
142
|
return;
|
|
197
143
|
}
|
|
198
|
-
|
|
199
144
|
var _this$props = this.props,
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
145
|
+
apihost = _this$props.apihost,
|
|
146
|
+
assethost = _this$props.assethost,
|
|
147
|
+
endpoint = _this$props.endpoint,
|
|
148
|
+
host = _this$props.host,
|
|
149
|
+
imghost = _this$props.imghost,
|
|
150
|
+
hl = _this$props.languageOverride,
|
|
151
|
+
reCaptchaCompat = _this$props.reCaptchaCompat,
|
|
152
|
+
reportapi = _this$props.reportapi,
|
|
153
|
+
sentry = _this$props.sentry,
|
|
154
|
+
custom = _this$props.custom,
|
|
155
|
+
loadAsync = _this$props.loadAsync,
|
|
156
|
+
scriptLocation = _this$props.scriptLocation,
|
|
157
|
+
_this$props$cleanup = _this$props.cleanup,
|
|
158
|
+
cleanup = _this$props$cleanup === void 0 ? true : _this$props$cleanup;
|
|
212
159
|
var mountParams = {
|
|
160
|
+
render: 'explicit',
|
|
213
161
|
apihost: apihost,
|
|
214
162
|
assethost: assethost,
|
|
215
163
|
endpoint: endpoint,
|
|
216
164
|
hl: hl,
|
|
217
165
|
host: host,
|
|
218
166
|
imghost: imghost,
|
|
219
|
-
recaptchacompat: reCaptchaCompat === false ?
|
|
167
|
+
recaptchacompat: reCaptchaCompat === false ? 'off' : null,
|
|
220
168
|
reportapi: reportapi,
|
|
221
169
|
sentry: sentry,
|
|
222
170
|
custom: custom,
|
|
223
171
|
loadAsync: loadAsync,
|
|
224
|
-
scriptLocation: scriptLocation
|
|
172
|
+
scriptLocation: scriptLocation,
|
|
173
|
+
cleanup: cleanup
|
|
225
174
|
};
|
|
226
|
-
|
|
175
|
+
(0, _loader.hCaptchaLoader)(mountParams).then(this.handleOnLoad, this.handleError)["catch"](this.handleError);
|
|
227
176
|
this.apiScriptRequested = true;
|
|
228
177
|
}
|
|
229
178
|
}, {
|
|
@@ -242,8 +191,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
242
191
|
hl: this.props.hl || this.props.languageOverride,
|
|
243
192
|
languageOverride: undefined
|
|
244
193
|
});
|
|
245
|
-
var hcaptcha = this._hcaptcha;
|
|
246
|
-
|
|
194
|
+
var hcaptcha = this._hcaptcha;
|
|
195
|
+
//Render hCaptcha widget and provide necessary callbacks - hCaptcha
|
|
247
196
|
var captchaId = hcaptcha.render(this.ref.current, renderParams);
|
|
248
197
|
this.setState({
|
|
249
198
|
isRemoved: false,
|
|
@@ -257,48 +206,56 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
257
206
|
value: function resetCaptcha() {
|
|
258
207
|
var captchaId = this.state.captchaId;
|
|
259
208
|
var hcaptcha = this._hcaptcha;
|
|
260
|
-
|
|
261
209
|
if (!this.isReady()) {
|
|
262
210
|
return;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
211
|
+
}
|
|
212
|
+
// Reset captcha state, removes stored token and unticks checkbox
|
|
266
213
|
hcaptcha.reset(captchaId);
|
|
214
|
+
this.sentryHub.addBreadcrumb({
|
|
215
|
+
category: _constants.scopeTag.value,
|
|
216
|
+
message: _constants.breadcrumbMessages.reset
|
|
217
|
+
});
|
|
267
218
|
}
|
|
268
219
|
}, {
|
|
269
220
|
key: "removeCaptcha",
|
|
270
221
|
value: function removeCaptcha(callback) {
|
|
271
222
|
var captchaId = this.state.captchaId;
|
|
272
223
|
var hcaptcha = this._hcaptcha;
|
|
273
|
-
|
|
274
224
|
if (!this.isReady()) {
|
|
275
225
|
return;
|
|
276
226
|
}
|
|
277
|
-
|
|
278
227
|
this.setState({
|
|
279
228
|
isRemoved: true
|
|
280
229
|
}, function () {
|
|
281
230
|
hcaptcha.remove(captchaId);
|
|
282
231
|
callback && callback();
|
|
283
232
|
});
|
|
233
|
+
this.sentryHub.addBreadcrumb({
|
|
234
|
+
category: _constants.scopeTag.value,
|
|
235
|
+
message: _constants.breadcrumbMessages.removed
|
|
236
|
+
});
|
|
284
237
|
}
|
|
285
238
|
}, {
|
|
286
239
|
key: "handleOnLoad",
|
|
287
240
|
value: function handleOnLoad() {
|
|
288
241
|
var _this4 = this;
|
|
289
|
-
|
|
290
242
|
this.setState({
|
|
291
243
|
isApiReady: true
|
|
292
244
|
}, function () {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
//
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
245
|
+
try {
|
|
246
|
+
var element = (0, _utils.getMountElement)(_this4.props.scriptLocation);
|
|
247
|
+
var frame = (0, _utils.getFrame)(element);
|
|
248
|
+
_this4._hcaptcha = frame.window.hcaptcha;
|
|
249
|
+
|
|
250
|
+
// render captcha and wait for captcha id
|
|
251
|
+
_this4.renderCaptcha(function () {
|
|
252
|
+
// trigger onLoad if it exists
|
|
253
|
+
var onLoad = _this4.props.onLoad;
|
|
254
|
+
if (onLoad) onLoad();
|
|
255
|
+
});
|
|
256
|
+
} catch (error) {
|
|
257
|
+
_this4.sentryHub.captureException(error);
|
|
258
|
+
}
|
|
302
259
|
});
|
|
303
260
|
}
|
|
304
261
|
}, {
|
|
@@ -306,14 +263,12 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
306
263
|
value: function handleSubmit(event) {
|
|
307
264
|
var onVerify = this.props.onVerify;
|
|
308
265
|
var _this$state = this.state,
|
|
309
|
-
|
|
310
|
-
|
|
266
|
+
isRemoved = _this$state.isRemoved,
|
|
267
|
+
captchaId = _this$state.captchaId;
|
|
311
268
|
var hcaptcha = this._hcaptcha;
|
|
312
269
|
if (typeof hcaptcha === 'undefined' || isRemoved) return;
|
|
313
270
|
var token = hcaptcha.getResponse(captchaId); //Get response token from hCaptcha widget
|
|
314
|
-
|
|
315
271
|
var ekey = hcaptcha.getRespKey(captchaId); //Get current challenge session id from hCaptcha widget
|
|
316
|
-
|
|
317
272
|
if (onVerify) onVerify(token, ekey); //Dispatch event to verify user response
|
|
318
273
|
}
|
|
319
274
|
}, {
|
|
@@ -322,14 +277,16 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
322
277
|
var onExpire = this.props.onExpire;
|
|
323
278
|
var captchaId = this.state.captchaId;
|
|
324
279
|
var hcaptcha = this._hcaptcha;
|
|
325
|
-
|
|
326
280
|
if (!this.isReady()) {
|
|
327
281
|
return;
|
|
328
282
|
}
|
|
329
|
-
|
|
330
283
|
hcaptcha.reset(captchaId); // If hCaptcha runs into error, reset captcha - hCaptcha
|
|
331
284
|
|
|
332
285
|
if (onExpire) onExpire();
|
|
286
|
+
this.sentryHub.addBreadcrumb({
|
|
287
|
+
category: _constants.scopeTag.value,
|
|
288
|
+
message: _constants.breadcrumbMessages.expired
|
|
289
|
+
});
|
|
333
290
|
}
|
|
334
291
|
}, {
|
|
335
292
|
key: "handleError",
|
|
@@ -337,20 +294,18 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
337
294
|
var onError = this.props.onError;
|
|
338
295
|
var captchaId = this.state.captchaId;
|
|
339
296
|
var hcaptcha = this._hcaptcha;
|
|
340
|
-
|
|
341
297
|
if (this.isReady()) {
|
|
342
298
|
// If hCaptcha runs into error, reset captcha - hCaptcha
|
|
343
299
|
hcaptcha.reset(captchaId);
|
|
344
300
|
}
|
|
345
|
-
|
|
346
301
|
if (onError) onError(event);
|
|
347
302
|
}
|
|
348
303
|
}, {
|
|
349
304
|
key: "isReady",
|
|
350
305
|
value: function isReady() {
|
|
351
306
|
var _this$state2 = this.state,
|
|
352
|
-
|
|
353
|
-
|
|
307
|
+
isApiReady = _this$state2.isApiReady,
|
|
308
|
+
isRemoved = _this$state2.isRemoved;
|
|
354
309
|
return isApiReady && !isRemoved;
|
|
355
310
|
}
|
|
356
311
|
}, {
|
|
@@ -359,7 +314,6 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
359
314
|
if (!this.isReady() || !this.props.onOpen) {
|
|
360
315
|
return;
|
|
361
316
|
}
|
|
362
|
-
|
|
363
317
|
this.props.onOpen();
|
|
364
318
|
}
|
|
365
319
|
}, {
|
|
@@ -368,7 +322,6 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
368
322
|
if (!this.isReady() || !this.props.onClose) {
|
|
369
323
|
return;
|
|
370
324
|
}
|
|
371
|
-
|
|
372
325
|
this.props.onClose();
|
|
373
326
|
}
|
|
374
327
|
}, {
|
|
@@ -377,40 +330,37 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
377
330
|
if (!this.isReady() || !this.props.onChalExpired) {
|
|
378
331
|
return;
|
|
379
332
|
}
|
|
380
|
-
|
|
381
333
|
this.props.onChalExpired();
|
|
382
334
|
}
|
|
383
335
|
}, {
|
|
384
336
|
key: "execute",
|
|
385
337
|
value: function execute() {
|
|
386
338
|
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
339
|
+
try {
|
|
340
|
+
var captchaId = this.state.captchaId;
|
|
341
|
+
var hcaptcha = this._hcaptcha;
|
|
342
|
+
if (!this.isReady()) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
if (opts && (0, _typeof2["default"])(opts) !== "object") {
|
|
346
|
+
opts = null;
|
|
347
|
+
}
|
|
348
|
+
return hcaptcha.execute(captchaId, opts);
|
|
349
|
+
} catch (error) {
|
|
350
|
+
this.sentryHub.captureException(error);
|
|
392
351
|
}
|
|
393
|
-
|
|
394
|
-
if (opts && (0, _typeof2["default"])(opts) !== "object") {
|
|
395
|
-
opts = null;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return hcaptcha.execute(captchaId, opts);
|
|
399
352
|
}
|
|
400
353
|
}, {
|
|
401
354
|
key: "setData",
|
|
402
355
|
value: function setData(data) {
|
|
403
356
|
var captchaId = this.state.captchaId;
|
|
404
357
|
var hcaptcha = this._hcaptcha;
|
|
405
|
-
|
|
406
358
|
if (!this.isReady()) {
|
|
407
359
|
return;
|
|
408
360
|
}
|
|
409
|
-
|
|
410
361
|
if (data && (0, _typeof2["default"])(data) !== "object") {
|
|
411
362
|
data = null;
|
|
412
363
|
}
|
|
413
|
-
|
|
414
364
|
hcaptcha.setData(captchaId, data);
|
|
415
365
|
}
|
|
416
366
|
}, {
|
|
@@ -437,7 +387,6 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
437
387
|
}]);
|
|
438
388
|
return HCaptcha;
|
|
439
389
|
}(React.Component);
|
|
440
|
-
|
|
441
390
|
var _default = HCaptcha;
|
|
442
391
|
exports["default"] = _default;
|
|
443
392
|
module.exports = exports.default;
|
package/dist/utils.js
CHANGED
|
@@ -1,34 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
|
|
5
3
|
Object.defineProperty(exports, "__esModule", {
|
|
6
4
|
value: true
|
|
7
5
|
});
|
|
8
|
-
exports.generateQuery = generateQuery;
|
|
9
6
|
exports.getFrame = getFrame;
|
|
10
7
|
exports.getMountElement = getMountElement;
|
|
11
|
-
|
|
12
|
-
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
13
|
-
|
|
14
|
-
function generateQuery(params) {
|
|
15
|
-
return Object.entries(params).filter(function (_ref) {
|
|
16
|
-
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
|
|
17
|
-
key = _ref2[0],
|
|
18
|
-
value = _ref2[1];
|
|
19
|
-
|
|
20
|
-
return value || value === false;
|
|
21
|
-
}).map(function (_ref3) {
|
|
22
|
-
var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2),
|
|
23
|
-
key = _ref4[0],
|
|
24
|
-
value = _ref4[1];
|
|
25
|
-
|
|
26
|
-
return "".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value));
|
|
27
|
-
}).join("&");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
;
|
|
31
|
-
|
|
32
8
|
function getFrame(element) {
|
|
33
9
|
var doc = element && element.ownerDocument || document;
|
|
34
10
|
var win = doc.defaultView || doc.parentWindow || window;
|
|
@@ -37,7 +13,6 @@ function getFrame(element) {
|
|
|
37
13
|
window: win
|
|
38
14
|
};
|
|
39
15
|
}
|
|
40
|
-
|
|
41
16
|
function getMountElement(element) {
|
|
42
17
|
return element || document.head;
|
|
43
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hcaptcha/react-hcaptcha",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"types": "types/index.d.ts",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"webpack-dev-server": "^4.13.1"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@babel/runtime": "^7.17.9"
|
|
61
|
+
"@babel/runtime": "^7.17.9",
|
|
62
|
+
"@hcaptcha/loader": "^1.0.9"
|
|
62
63
|
}
|
|
63
64
|
}
|
package/src/constants.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const scopeTag = {
|
|
2
|
+
key: 'source',
|
|
3
|
+
value: '@hCaptcha/react'
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export const breadcrumbMessages = {
|
|
7
|
+
mounted: 'hCaptcha component mounted',
|
|
8
|
+
expired: 'hCaptcha expired',
|
|
9
|
+
unmounted: 'hCaptcha component unmounted',
|
|
10
|
+
reset: 'hCaptcha reset',
|
|
11
|
+
removed: 'hCaptcha removed'
|
|
12
|
+
|
|
13
|
+
}
|
package/src/index.js
CHANGED
|
@@ -1,51 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { hCaptchaLoader, initSentry } from '@hcaptcha/loader';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// Prevent loading API script multiple times
|
|
8
|
-
const scripts = [];
|
|
9
|
-
|
|
10
|
-
// Generate hCaptcha API script
|
|
11
|
-
const mountCaptchaScript = (params = {}) => {
|
|
12
|
-
const element = getMountElement(params.scriptLocation);
|
|
13
|
-
delete params.scriptLocation;
|
|
14
|
-
|
|
15
|
-
const frame = getFrame(element);
|
|
16
|
-
const script = scripts.find(({ scope }) => scope === frame.window);
|
|
17
|
-
|
|
18
|
-
if (frame.document.getElementById(SCRIPT_ID) && script) {
|
|
19
|
-
// API was already requested
|
|
20
|
-
return script.promise;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const promise = new Promise((resolve, reject) => {
|
|
24
|
-
// Create global onload callback
|
|
25
|
-
frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve;
|
|
26
|
-
|
|
27
|
-
const domain = params.apihost || "https://js.hcaptcha.com";
|
|
28
|
-
delete params.apihost;
|
|
29
|
-
|
|
30
|
-
const script = frame.document.createElement("script");
|
|
31
|
-
script.id = SCRIPT_ID;
|
|
32
|
-
script.src = `${domain}/1/api.js?render=explicit&onload=${HCAPTCHA_LOAD_FN_NAME}`;
|
|
33
|
-
|
|
34
|
-
script.async = params.loadAsync !== undefined? params.loadAsync : true;
|
|
35
|
-
delete params.loadAsync;
|
|
36
|
-
|
|
37
|
-
script.onerror = (event) => reject('script-error');
|
|
38
|
-
|
|
39
|
-
const query = generateQuery(params);
|
|
40
|
-
script.src += query !== ""? `&${query}` : "";
|
|
41
|
-
|
|
42
|
-
element.appendChild(script);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
scripts.push({ promise, scope: frame.window });
|
|
46
|
-
|
|
47
|
-
return promise;
|
|
48
|
-
};
|
|
4
|
+
import { getFrame, getMountElement } from './utils.js';
|
|
5
|
+
import { breadcrumbMessages, scopeTag } from "./constants";
|
|
49
6
|
|
|
50
7
|
|
|
51
8
|
class HCaptcha extends React.Component {
|
|
@@ -78,6 +35,7 @@ class HCaptcha extends React.Component {
|
|
|
78
35
|
|
|
79
36
|
this.ref = React.createRef();
|
|
80
37
|
this.apiScriptRequested = false;
|
|
38
|
+
this.sentryHub = null;
|
|
81
39
|
|
|
82
40
|
this.state = {
|
|
83
41
|
isApiReady: false,
|
|
@@ -94,6 +52,13 @@ class HCaptcha extends React.Component {
|
|
|
94
52
|
|
|
95
53
|
const isApiReady = typeof this._hcaptcha !== 'undefined';
|
|
96
54
|
|
|
55
|
+
this.sentryHub = initSentry(this.props.sentry, scopeTag);
|
|
56
|
+
|
|
57
|
+
this.sentryHub.addBreadcrumb({
|
|
58
|
+
category: scopeTag.value,
|
|
59
|
+
message: breadcrumbMessages.mounted,
|
|
60
|
+
});
|
|
61
|
+
|
|
97
62
|
/*
|
|
98
63
|
* Check if hCaptcha has already been loaded,
|
|
99
64
|
* If Yes, render the captcha
|
|
@@ -126,6 +91,11 @@ class HCaptcha extends React.Component {
|
|
|
126
91
|
// Reset any stored variables / timers when unmounting
|
|
127
92
|
hcaptcha.reset(captchaId);
|
|
128
93
|
hcaptcha.remove(captchaId);
|
|
94
|
+
|
|
95
|
+
this.sentryHub.addBreadcrumb({
|
|
96
|
+
category: scopeTag.value,
|
|
97
|
+
message: breadcrumbMessages.unmounted,
|
|
98
|
+
});
|
|
129
99
|
}
|
|
130
100
|
|
|
131
101
|
shouldComponentUpdate(nextProps, nextState) {
|
|
@@ -168,26 +138,30 @@ class HCaptcha extends React.Component {
|
|
|
168
138
|
sentry,
|
|
169
139
|
custom,
|
|
170
140
|
loadAsync,
|
|
171
|
-
scriptLocation
|
|
141
|
+
scriptLocation,
|
|
142
|
+
cleanup = true,
|
|
172
143
|
} = this.props;
|
|
173
144
|
const mountParams = {
|
|
145
|
+
render: 'explicit',
|
|
174
146
|
apihost,
|
|
175
147
|
assethost,
|
|
176
148
|
endpoint,
|
|
177
149
|
hl,
|
|
178
150
|
host,
|
|
179
151
|
imghost,
|
|
180
|
-
recaptchacompat: reCaptchaCompat === false?
|
|
152
|
+
recaptchacompat: reCaptchaCompat === false? 'off' : null,
|
|
181
153
|
reportapi,
|
|
182
154
|
sentry,
|
|
183
155
|
custom,
|
|
184
156
|
loadAsync,
|
|
185
157
|
scriptLocation,
|
|
158
|
+
cleanup
|
|
186
159
|
};
|
|
187
160
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
161
|
+
hCaptchaLoader(mountParams)
|
|
162
|
+
.then(this.handleOnLoad, this.handleError)
|
|
163
|
+
.catch(this.handleError);
|
|
164
|
+
|
|
191
165
|
this.apiScriptRequested = true;
|
|
192
166
|
}
|
|
193
167
|
|
|
@@ -225,6 +199,11 @@ class HCaptcha extends React.Component {
|
|
|
225
199
|
}
|
|
226
200
|
// Reset captcha state, removes stored token and unticks checkbox
|
|
227
201
|
hcaptcha.reset(captchaId)
|
|
202
|
+
|
|
203
|
+
this.sentryHub.addBreadcrumb({
|
|
204
|
+
category: scopeTag.value,
|
|
205
|
+
message: breadcrumbMessages.reset,
|
|
206
|
+
});
|
|
228
207
|
}
|
|
229
208
|
|
|
230
209
|
removeCaptcha(callback) {
|
|
@@ -239,21 +218,33 @@ class HCaptcha extends React.Component {
|
|
|
239
218
|
hcaptcha.remove(captchaId);
|
|
240
219
|
callback && callback()
|
|
241
220
|
});
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
this.sentryHub.addBreadcrumb({
|
|
224
|
+
category: scopeTag.value,
|
|
225
|
+
message: breadcrumbMessages.removed,
|
|
226
|
+
});
|
|
242
227
|
}
|
|
243
228
|
|
|
244
|
-
|
|
229
|
+
handleOnLoad () {
|
|
245
230
|
this.setState({ isApiReady: true }, () => {
|
|
246
|
-
|
|
247
|
-
|
|
231
|
+
try {
|
|
232
|
+
const element = getMountElement(this.props.scriptLocation);
|
|
233
|
+
const frame = getFrame(element);
|
|
234
|
+
|
|
235
|
+
this._hcaptcha = frame.window.hcaptcha;
|
|
248
236
|
|
|
249
|
-
this._hcaptcha = frame.window.hcaptcha;
|
|
250
237
|
|
|
251
|
-
|
|
252
|
-
|
|
238
|
+
// render captcha and wait for captcha id
|
|
239
|
+
this.renderCaptcha(() => {
|
|
253
240
|
// trigger onLoad if it exists
|
|
241
|
+
|
|
254
242
|
const { onLoad } = this.props;
|
|
255
243
|
if (onLoad) onLoad();
|
|
256
|
-
|
|
244
|
+
});
|
|
245
|
+
} catch (error) {
|
|
246
|
+
this.sentryHub.captureException(error);
|
|
247
|
+
}
|
|
257
248
|
});
|
|
258
249
|
}
|
|
259
250
|
|
|
@@ -281,6 +272,11 @@ class HCaptcha extends React.Component {
|
|
|
281
272
|
hcaptcha.reset(captchaId) // If hCaptcha runs into error, reset captcha - hCaptcha
|
|
282
273
|
|
|
283
274
|
if (onExpire) onExpire();
|
|
275
|
+
|
|
276
|
+
this.sentryHub.addBreadcrumb({
|
|
277
|
+
category: scopeTag.value,
|
|
278
|
+
message: breadcrumbMessages.expired,
|
|
279
|
+
});
|
|
284
280
|
}
|
|
285
281
|
|
|
286
282
|
handleError (event) {
|
|
@@ -327,18 +323,23 @@ class HCaptcha extends React.Component {
|
|
|
327
323
|
}
|
|
328
324
|
|
|
329
325
|
execute (opts = null) {
|
|
330
|
-
|
|
331
|
-
|
|
326
|
+
try {
|
|
327
|
+
const { captchaId } = this.state;
|
|
328
|
+
const hcaptcha = this._hcaptcha;
|
|
332
329
|
|
|
333
|
-
if (!this.isReady()) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
330
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
331
|
+
if (!this.isReady()) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
340
334
|
|
|
341
|
-
|
|
335
|
+
if (opts && typeof opts !== "object") {
|
|
336
|
+
opts = null;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return hcaptcha.execute(captchaId, opts);
|
|
340
|
+
} catch (error) {
|
|
341
|
+
this.sentryHub.captureException(error);
|
|
342
|
+
}
|
|
342
343
|
}
|
|
343
344
|
|
|
344
345
|
setData (data) {
|
package/src/utils.js
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
function generateQuery(params) {
|
|
2
|
-
return Object.entries(params)
|
|
3
|
-
.filter(([key, value]) => value || value === false)
|
|
4
|
-
.map(([key, value]) => {
|
|
5
|
-
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
|
|
6
|
-
}).join("&");
|
|
7
|
-
};
|
|
8
|
-
|
|
9
1
|
function getFrame(element) {
|
|
10
2
|
const doc = (element && element.ownerDocument) || document;
|
|
11
3
|
const win = doc.defaultView || doc.parentWindow || window;
|
|
@@ -18,7 +10,6 @@ function getMountElement(element) {
|
|
|
18
10
|
}
|
|
19
11
|
|
|
20
12
|
export {
|
|
21
|
-
generateQuery,
|
|
22
13
|
getFrame,
|
|
23
14
|
getMountElement
|
|
24
|
-
};
|
|
15
|
+
};
|