@hcaptcha/react-hcaptcha 1.6.1 → 1.8.0
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 +2 -1
- package/dist/esm/index.js +68 -33
- package/dist/esm/utils.js +15 -1
- package/dist/index.js +69 -35
- package/dist/utils.js +16 -1
- package/package.json +2 -2
- package/src/index.js +61 -26
- package/src/utils.js +15 -1
- package/types/index.d.ts +1 -0
package/README.md
CHANGED
|
@@ -139,7 +139,8 @@ return <HCaptcha ref={captchaRef} onLoad={onLoad} sitekey={sitekey} {...props} /
|
|
|
139
139
|
|`reportapi`|String|No|`-`|See enterprise docs.|
|
|
140
140
|
|`sentry`|String|No|`-`|See enterprise docs.|
|
|
141
141
|
|`custom`|Boolean|No|`-`|See enterprise docs.|
|
|
142
|
-
|`loadAsync`|Boolean|No|`true`|Set if the script should be loaded asynchronously
|
|
142
|
+
|`loadAsync`|Boolean|No|`true`|Set if the script should be loaded asynchronously.|
|
|
143
|
+
|`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.|
|
|
143
144
|
|
|
144
145
|
#### Events
|
|
145
146
|
|
package/dist/esm/index.js
CHANGED
|
@@ -1,45 +1,54 @@
|
|
|
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 { generateQuery } from "./utils.js";
|
|
4
|
+
import { generateQuery, getFrame, getMountElement } from "./utils.js";
|
|
5
5
|
var SCRIPT_ID = 'hcaptcha-api-script-id';
|
|
6
6
|
var HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad'; // Prevent loading API script multiple times
|
|
7
7
|
|
|
8
|
-
var
|
|
9
|
-
var rejectFn;
|
|
10
|
-
var mountPromise = new Promise(function (resolve, reject) {
|
|
11
|
-
resolveFn = resolve;
|
|
12
|
-
rejectFn = reject;
|
|
13
|
-
}); // Generate hCaptcha API script
|
|
8
|
+
var scripts = []; // Generate hCaptcha API script
|
|
14
9
|
|
|
15
10
|
var mountCaptchaScript = function mountCaptchaScript(params) {
|
|
16
11
|
if (params === void 0) {
|
|
17
12
|
params = {};
|
|
18
13
|
}
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
+
});
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
script.id = SCRIPT_ID;
|
|
31
|
-
script.src = domain + "/1/api.js?render=explicit&onload=" + HCAPTCHA_LOAD_FN_NAME;
|
|
32
|
-
script.async = params.loadAsync !== undefined ? params.loadAsync : true;
|
|
33
|
-
delete params.loadAsync;
|
|
23
|
+
if (frame.document.getElementById(SCRIPT_ID) && script) {
|
|
24
|
+
// API was already requested
|
|
25
|
+
return script.promise;
|
|
26
|
+
}
|
|
34
27
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
+
};
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
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;
|
|
43
52
|
};
|
|
44
53
|
|
|
45
54
|
var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
@@ -48,7 +57,17 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
48
57
|
function HCaptcha(props) {
|
|
49
58
|
var _this;
|
|
50
59
|
|
|
51
|
-
_this = _React$Component.call(this, props) || this;
|
|
60
|
+
_this = _React$Component.call(this, props) || this;
|
|
61
|
+
var element = getMountElement(_this.props.scriptLocation);
|
|
62
|
+
var frame = getFrame(element);
|
|
63
|
+
/**
|
|
64
|
+
* Internal reference to track hCaptcha API
|
|
65
|
+
*
|
|
66
|
+
* Required as window is relative to initialization in application
|
|
67
|
+
* not where the script and iFrames have been loaded.
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
_this._hcaptcha = frame.window.hcaptcha || undefined; // API Methods
|
|
52
71
|
|
|
53
72
|
_this.renderCaptcha = _this.renderCaptcha.bind(_assertThisInitialized(_this));
|
|
54
73
|
_this.resetCaptcha = _this.resetCaptcha.bind(_assertThisInitialized(_this));
|
|
@@ -63,7 +82,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
63
82
|
_this.handleOpen = _this.handleOpen.bind(_assertThisInitialized(_this));
|
|
64
83
|
_this.handleClose = _this.handleClose.bind(_assertThisInitialized(_this));
|
|
65
84
|
_this.handleChallengeExpired = _this.handleChallengeExpired.bind(_assertThisInitialized(_this));
|
|
66
|
-
var isApiReady = typeof
|
|
85
|
+
var isApiReady = typeof _this._hcaptcha !== 'undefined';
|
|
67
86
|
_this.ref = /*#__PURE__*/React.createRef();
|
|
68
87
|
_this.apiScriptRequested = false;
|
|
69
88
|
_this.state = {
|
|
@@ -96,6 +115,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
96
115
|
|
|
97
116
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
|
98
117
|
var captchaId = this.state.captchaId;
|
|
118
|
+
var hcaptcha = this._hcaptcha;
|
|
99
119
|
|
|
100
120
|
if (!this.isReady()) {
|
|
101
121
|
return;
|
|
@@ -148,7 +168,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
148
168
|
reportapi = _this$props.reportapi,
|
|
149
169
|
sentry = _this$props.sentry,
|
|
150
170
|
custom = _this$props.custom,
|
|
151
|
-
loadAsync = _this$props.loadAsync
|
|
171
|
+
loadAsync = _this$props.loadAsync,
|
|
172
|
+
scriptLocation = _this$props.scriptLocation;
|
|
152
173
|
var mountParams = {
|
|
153
174
|
apihost: apihost,
|
|
154
175
|
assethost: assethost,
|
|
@@ -160,7 +181,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
160
181
|
reportapi: reportapi,
|
|
161
182
|
sentry: sentry,
|
|
162
183
|
custom: custom,
|
|
163
|
-
loadAsync: loadAsync
|
|
184
|
+
loadAsync: loadAsync,
|
|
185
|
+
scriptLocation: scriptLocation
|
|
164
186
|
};
|
|
165
187
|
mountCaptchaScript(mountParams).then(this.handleOnLoad)["catch"](this.handleError);
|
|
166
188
|
this.apiScriptRequested = true;
|
|
@@ -179,7 +201,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
179
201
|
}, this.props, {
|
|
180
202
|
hl: this.props.hl || this.props.languageOverride,
|
|
181
203
|
languageOverride: undefined
|
|
182
|
-
});
|
|
204
|
+
});
|
|
205
|
+
var hcaptcha = this._hcaptcha; //Render hCaptcha widget and provide necessary callbacks - hCaptcha
|
|
183
206
|
|
|
184
207
|
var captchaId = hcaptcha.render(this.ref.current, renderParams);
|
|
185
208
|
this.setState({
|
|
@@ -192,6 +215,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
192
215
|
|
|
193
216
|
_proto.resetCaptcha = function resetCaptcha() {
|
|
194
217
|
var captchaId = this.state.captchaId;
|
|
218
|
+
var hcaptcha = this._hcaptcha;
|
|
195
219
|
|
|
196
220
|
if (!this.isReady()) {
|
|
197
221
|
return;
|
|
@@ -203,6 +227,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
203
227
|
|
|
204
228
|
_proto.removeCaptcha = function removeCaptcha(callback) {
|
|
205
229
|
var captchaId = this.state.captchaId;
|
|
230
|
+
var hcaptcha = this._hcaptcha;
|
|
206
231
|
|
|
207
232
|
if (!this.isReady()) {
|
|
208
233
|
return;
|
|
@@ -222,7 +247,10 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
222
247
|
this.setState({
|
|
223
248
|
isApiReady: true
|
|
224
249
|
}, function () {
|
|
225
|
-
|
|
250
|
+
var element = getMountElement(_this3.props.scriptLocation);
|
|
251
|
+
var frame = getFrame(element);
|
|
252
|
+
_this3._hcaptcha = frame.window.hcaptcha; // render captcha and wait for captcha id
|
|
253
|
+
|
|
226
254
|
_this3.renderCaptcha(function () {
|
|
227
255
|
// trigger onLoad if it exists
|
|
228
256
|
var onLoad = _this3.props.onLoad;
|
|
@@ -236,6 +264,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
236
264
|
var _this$state = this.state,
|
|
237
265
|
isRemoved = _this$state.isRemoved,
|
|
238
266
|
captchaId = _this$state.captchaId;
|
|
267
|
+
var hcaptcha = this._hcaptcha;
|
|
239
268
|
if (typeof hcaptcha === 'undefined' || isRemoved) return;
|
|
240
269
|
var token = hcaptcha.getResponse(captchaId); //Get response token from hCaptcha widget
|
|
241
270
|
|
|
@@ -247,6 +276,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
247
276
|
_proto.handleExpire = function handleExpire() {
|
|
248
277
|
var onExpire = this.props.onExpire;
|
|
249
278
|
var captchaId = this.state.captchaId;
|
|
279
|
+
var hcaptcha = this._hcaptcha;
|
|
250
280
|
|
|
251
281
|
if (!this.isReady()) {
|
|
252
282
|
return;
|
|
@@ -260,6 +290,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
260
290
|
_proto.handleError = function handleError(event) {
|
|
261
291
|
var onError = this.props.onError;
|
|
262
292
|
var captchaId = this.state.captchaId;
|
|
293
|
+
var hcaptcha = this._hcaptcha;
|
|
263
294
|
|
|
264
295
|
if (this.isReady()) {
|
|
265
296
|
// If hCaptcha runs into error, reset captcha - hCaptcha
|
|
@@ -306,6 +337,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
306
337
|
}
|
|
307
338
|
|
|
308
339
|
var captchaId = this.state.captchaId;
|
|
340
|
+
var hcaptcha = this._hcaptcha;
|
|
309
341
|
|
|
310
342
|
if (!this.isReady()) {
|
|
311
343
|
return;
|
|
@@ -320,6 +352,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
320
352
|
|
|
321
353
|
_proto.setData = function setData(data) {
|
|
322
354
|
var captchaId = this.state.captchaId;
|
|
355
|
+
var hcaptcha = this._hcaptcha;
|
|
323
356
|
|
|
324
357
|
if (!this.isReady()) {
|
|
325
358
|
return;
|
|
@@ -333,10 +366,12 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
333
366
|
};
|
|
334
367
|
|
|
335
368
|
_proto.getResponse = function getResponse() {
|
|
369
|
+
var hcaptcha = this._hcaptcha;
|
|
336
370
|
return hcaptcha.getResponse(this.state.captchaId);
|
|
337
371
|
};
|
|
338
372
|
|
|
339
373
|
_proto.getRespKey = function getRespKey() {
|
|
374
|
+
var hcaptcha = this._hcaptcha;
|
|
340
375
|
return hcaptcha.getRespKey(this.state.captchaId);
|
|
341
376
|
};
|
|
342
377
|
|
package/dist/esm/utils.js
CHANGED
|
@@ -11,4 +11,18 @@ function generateQuery(params) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
;
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
function getFrame(element) {
|
|
16
|
+
var doc = element && element.ownerDocument || document;
|
|
17
|
+
var win = doc.defaultView || doc.parentWindow;
|
|
18
|
+
return {
|
|
19
|
+
document: doc,
|
|
20
|
+
window: win
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getMountElement(element) {
|
|
25
|
+
return element || document.head;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { generateQuery, getFrame, getMountElement };
|
package/dist/index.js
CHANGED
|
@@ -34,39 +34,47 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
|
|
|
34
34
|
var SCRIPT_ID = 'hcaptcha-api-script-id';
|
|
35
35
|
var HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad'; // Prevent loading API script multiple times
|
|
36
36
|
|
|
37
|
-
var
|
|
38
|
-
var rejectFn;
|
|
39
|
-
var mountPromise = new Promise(function (resolve, reject) {
|
|
40
|
-
resolveFn = resolve;
|
|
41
|
-
rejectFn = reject;
|
|
42
|
-
}); // Generate hCaptcha API script
|
|
37
|
+
var scripts = []; // Generate hCaptcha API script
|
|
43
38
|
|
|
44
39
|
var mountCaptchaScript = function mountCaptchaScript() {
|
|
45
40
|
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
46
|
-
|
|
47
|
-
|
|
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) {
|
|
48
50
|
// API was already requested
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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;
|
|
70
78
|
};
|
|
71
79
|
|
|
72
80
|
var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
@@ -78,7 +86,17 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
78
86
|
var _this;
|
|
79
87
|
|
|
80
88
|
(0, _classCallCheck2["default"])(this, HCaptcha);
|
|
81
|
-
_this = _super.call(this, props);
|
|
89
|
+
_this = _super.call(this, props);
|
|
90
|
+
var element = (0, _utils.getMountElement)(_this.props.scriptLocation);
|
|
91
|
+
var frame = (0, _utils.getFrame)(element);
|
|
92
|
+
/**
|
|
93
|
+
* Internal reference to track hCaptcha API
|
|
94
|
+
*
|
|
95
|
+
* Required as window is relative to initialization in application
|
|
96
|
+
* not where the script and iFrames have been loaded.
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
_this._hcaptcha = frame.window.hcaptcha || undefined; // API Methods
|
|
82
100
|
|
|
83
101
|
_this.renderCaptcha = _this.renderCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
|
|
84
102
|
_this.resetCaptcha = _this.resetCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
|
|
@@ -93,7 +111,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
93
111
|
_this.handleOpen = _this.handleOpen.bind((0, _assertThisInitialized2["default"])(_this));
|
|
94
112
|
_this.handleClose = _this.handleClose.bind((0, _assertThisInitialized2["default"])(_this));
|
|
95
113
|
_this.handleChallengeExpired = _this.handleChallengeExpired.bind((0, _assertThisInitialized2["default"])(_this));
|
|
96
|
-
var isApiReady = typeof
|
|
114
|
+
var isApiReady = typeof _this._hcaptcha !== 'undefined';
|
|
97
115
|
_this.ref = /*#__PURE__*/React.createRef();
|
|
98
116
|
_this.apiScriptRequested = false;
|
|
99
117
|
_this.state = {
|
|
@@ -127,6 +145,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
127
145
|
key: "componentWillUnmount",
|
|
128
146
|
value: function componentWillUnmount() {
|
|
129
147
|
var captchaId = this.state.captchaId;
|
|
148
|
+
var hcaptcha = this._hcaptcha;
|
|
130
149
|
|
|
131
150
|
if (!this.isReady()) {
|
|
132
151
|
return;
|
|
@@ -182,7 +201,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
182
201
|
reportapi = _this$props.reportapi,
|
|
183
202
|
sentry = _this$props.sentry,
|
|
184
203
|
custom = _this$props.custom,
|
|
185
|
-
loadAsync = _this$props.loadAsync
|
|
204
|
+
loadAsync = _this$props.loadAsync,
|
|
205
|
+
scriptLocation = _this$props.scriptLocation;
|
|
186
206
|
var mountParams = {
|
|
187
207
|
apihost: apihost,
|
|
188
208
|
assethost: assethost,
|
|
@@ -194,7 +214,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
194
214
|
reportapi: reportapi,
|
|
195
215
|
sentry: sentry,
|
|
196
216
|
custom: custom,
|
|
197
|
-
loadAsync: loadAsync
|
|
217
|
+
loadAsync: loadAsync,
|
|
218
|
+
scriptLocation: scriptLocation
|
|
198
219
|
};
|
|
199
220
|
mountCaptchaScript(mountParams).then(this.handleOnLoad)["catch"](this.handleError);
|
|
200
221
|
this.apiScriptRequested = true;
|
|
@@ -214,7 +235,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
214
235
|
}, this.props, {
|
|
215
236
|
hl: this.props.hl || this.props.languageOverride,
|
|
216
237
|
languageOverride: undefined
|
|
217
|
-
});
|
|
238
|
+
});
|
|
239
|
+
var hcaptcha = this._hcaptcha; //Render hCaptcha widget and provide necessary callbacks - hCaptcha
|
|
218
240
|
|
|
219
241
|
var captchaId = hcaptcha.render(this.ref.current, renderParams);
|
|
220
242
|
this.setState({
|
|
@@ -228,6 +250,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
228
250
|
key: "resetCaptcha",
|
|
229
251
|
value: function resetCaptcha() {
|
|
230
252
|
var captchaId = this.state.captchaId;
|
|
253
|
+
var hcaptcha = this._hcaptcha;
|
|
231
254
|
|
|
232
255
|
if (!this.isReady()) {
|
|
233
256
|
return;
|
|
@@ -240,6 +263,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
240
263
|
key: "removeCaptcha",
|
|
241
264
|
value: function removeCaptcha(callback) {
|
|
242
265
|
var captchaId = this.state.captchaId;
|
|
266
|
+
var hcaptcha = this._hcaptcha;
|
|
243
267
|
|
|
244
268
|
if (!this.isReady()) {
|
|
245
269
|
return;
|
|
@@ -260,7 +284,10 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
260
284
|
this.setState({
|
|
261
285
|
isApiReady: true
|
|
262
286
|
}, function () {
|
|
263
|
-
|
|
287
|
+
var element = (0, _utils.getMountElement)(_this3.props.scriptLocation);
|
|
288
|
+
var frame = (0, _utils.getFrame)(element);
|
|
289
|
+
_this3._hcaptcha = frame.window.hcaptcha; // render captcha and wait for captcha id
|
|
290
|
+
|
|
264
291
|
_this3.renderCaptcha(function () {
|
|
265
292
|
// trigger onLoad if it exists
|
|
266
293
|
var onLoad = _this3.props.onLoad;
|
|
@@ -275,6 +302,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
275
302
|
var _this$state = this.state,
|
|
276
303
|
isRemoved = _this$state.isRemoved,
|
|
277
304
|
captchaId = _this$state.captchaId;
|
|
305
|
+
var hcaptcha = this._hcaptcha;
|
|
278
306
|
if (typeof hcaptcha === 'undefined' || isRemoved) return;
|
|
279
307
|
var token = hcaptcha.getResponse(captchaId); //Get response token from hCaptcha widget
|
|
280
308
|
|
|
@@ -287,6 +315,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
287
315
|
value: function handleExpire() {
|
|
288
316
|
var onExpire = this.props.onExpire;
|
|
289
317
|
var captchaId = this.state.captchaId;
|
|
318
|
+
var hcaptcha = this._hcaptcha;
|
|
290
319
|
|
|
291
320
|
if (!this.isReady()) {
|
|
292
321
|
return;
|
|
@@ -301,6 +330,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
301
330
|
value: function handleError(event) {
|
|
302
331
|
var onError = this.props.onError;
|
|
303
332
|
var captchaId = this.state.captchaId;
|
|
333
|
+
var hcaptcha = this._hcaptcha;
|
|
304
334
|
|
|
305
335
|
if (this.isReady()) {
|
|
306
336
|
// If hCaptcha runs into error, reset captcha - hCaptcha
|
|
@@ -349,6 +379,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
349
379
|
value: function execute() {
|
|
350
380
|
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
351
381
|
var captchaId = this.state.captchaId;
|
|
382
|
+
var hcaptcha = this._hcaptcha;
|
|
352
383
|
|
|
353
384
|
if (!this.isReady()) {
|
|
354
385
|
return;
|
|
@@ -364,6 +395,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
364
395
|
key: "setData",
|
|
365
396
|
value: function setData(data) {
|
|
366
397
|
var captchaId = this.state.captchaId;
|
|
398
|
+
var hcaptcha = this._hcaptcha;
|
|
367
399
|
|
|
368
400
|
if (!this.isReady()) {
|
|
369
401
|
return;
|
|
@@ -378,11 +410,13 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
378
410
|
}, {
|
|
379
411
|
key: "getResponse",
|
|
380
412
|
value: function getResponse() {
|
|
413
|
+
var hcaptcha = this._hcaptcha;
|
|
381
414
|
return hcaptcha.getResponse(this.state.captchaId);
|
|
382
415
|
}
|
|
383
416
|
}, {
|
|
384
417
|
key: "getRespKey",
|
|
385
418
|
value: function getRespKey() {
|
|
419
|
+
var hcaptcha = this._hcaptcha;
|
|
386
420
|
return hcaptcha.getRespKey(this.state.captchaId);
|
|
387
421
|
}
|
|
388
422
|
}, {
|
package/dist/utils.js
CHANGED
|
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
8
|
exports.generateQuery = generateQuery;
|
|
9
|
+
exports.getFrame = getFrame;
|
|
10
|
+
exports.getMountElement = getMountElement;
|
|
9
11
|
|
|
10
12
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
11
13
|
|
|
@@ -25,4 +27,17 @@ function generateQuery(params) {
|
|
|
25
27
|
}).join("&");
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
;
|
|
30
|
+
;
|
|
31
|
+
|
|
32
|
+
function getFrame(element) {
|
|
33
|
+
var doc = element && element.ownerDocument || document;
|
|
34
|
+
var win = doc.defaultView || doc.parentWindow;
|
|
35
|
+
return {
|
|
36
|
+
document: doc,
|
|
37
|
+
window: win
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getMountElement(element) {
|
|
42
|
+
return element || document.head;
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hcaptcha/react-hcaptcha",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"types": "types/index.d.ts",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
],
|
|
12
12
|
"description": "A React library for hCaptcha",
|
|
13
13
|
"scripts": {
|
|
14
|
-
"start": "webpack serve",
|
|
14
|
+
"start": "webpack serve -c ./demo/webpack.config.mjs",
|
|
15
15
|
"test": "jest",
|
|
16
16
|
"watch": "babel src -d dist --copy-files --watch",
|
|
17
17
|
"transpile": "babel src -d dist --copy-files",
|
package/src/index.js
CHANGED
|
@@ -1,44 +1,50 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { generateQuery } from "./utils.js";
|
|
2
|
+
import { generateQuery, getFrame, getMountElement } from "./utils.js";
|
|
3
3
|
|
|
4
4
|
const SCRIPT_ID = 'hcaptcha-api-script-id';
|
|
5
5
|
const HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad';
|
|
6
6
|
|
|
7
7
|
// Prevent loading API script multiple times
|
|
8
|
-
|
|
9
|
-
let rejectFn;
|
|
10
|
-
const mountPromise = new Promise((resolve, reject) => {
|
|
11
|
-
resolveFn = resolve;
|
|
12
|
-
rejectFn = reject;
|
|
13
|
-
});
|
|
8
|
+
const scripts = [];
|
|
14
9
|
|
|
15
10
|
// Generate hCaptcha API script
|
|
16
11
|
const mountCaptchaScript = (params={}) => {
|
|
17
|
-
|
|
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) {
|
|
18
19
|
// API was already requested
|
|
19
|
-
return
|
|
20
|
+
return script.promise;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
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;
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
|
|
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}`;
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
script.src = `${domain}/1/api.js?render=explicit&onload=${HCAPTCHA_LOAD_FN_NAME}`;
|
|
34
|
+
script.async = params.loadAsync !== undefined? params.loadAsync : true;
|
|
35
|
+
delete params.loadAsync;
|
|
31
36
|
|
|
32
|
-
|
|
33
|
-
delete params.loadAsync;
|
|
37
|
+
script.onerror = (event) => reject('script-error');
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
const query = generateQuery(params);
|
|
40
|
+
script.src += query !== ""? `&${query}` : "";
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
element.appendChild(script);
|
|
43
|
+
});
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
scripts.push({ promise, scope: frame.window });
|
|
46
|
+
|
|
47
|
+
return promise;
|
|
42
48
|
};
|
|
43
49
|
|
|
44
50
|
|
|
@@ -46,6 +52,17 @@ class HCaptcha extends React.Component {
|
|
|
46
52
|
constructor (props) {
|
|
47
53
|
super(props);
|
|
48
54
|
|
|
55
|
+
const element = getMountElement(this.props.scriptLocation);
|
|
56
|
+
const frame = getFrame(element);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Internal reference to track hCaptcha API
|
|
60
|
+
*
|
|
61
|
+
* Required as window is relative to initialization in application
|
|
62
|
+
* not where the script and iFrames have been loaded.
|
|
63
|
+
*/
|
|
64
|
+
this._hcaptcha = frame.window.hcaptcha || undefined;
|
|
65
|
+
|
|
49
66
|
// API Methods
|
|
50
67
|
this.renderCaptcha = this.renderCaptcha.bind(this);
|
|
51
68
|
this.resetCaptcha = this.resetCaptcha.bind(this);
|
|
@@ -62,7 +79,8 @@ class HCaptcha extends React.Component {
|
|
|
62
79
|
this.handleClose = this.handleClose.bind(this);
|
|
63
80
|
this.handleChallengeExpired = this.handleChallengeExpired.bind(this);
|
|
64
81
|
|
|
65
|
-
|
|
82
|
+
|
|
83
|
+
const isApiReady = typeof this._hcaptcha !== 'undefined';
|
|
66
84
|
|
|
67
85
|
this.ref = React.createRef();
|
|
68
86
|
this.apiScriptRequested = false;
|
|
@@ -94,6 +112,7 @@ class HCaptcha extends React.Component {
|
|
|
94
112
|
|
|
95
113
|
componentWillUnmount() {
|
|
96
114
|
const { captchaId } = this.state;
|
|
115
|
+
const hcaptcha = this._hcaptcha;
|
|
97
116
|
|
|
98
117
|
if (!this.isReady()) {
|
|
99
118
|
return;
|
|
@@ -143,7 +162,8 @@ class HCaptcha extends React.Component {
|
|
|
143
162
|
reportapi,
|
|
144
163
|
sentry,
|
|
145
164
|
custom,
|
|
146
|
-
loadAsync
|
|
165
|
+
loadAsync,
|
|
166
|
+
scriptLocation
|
|
147
167
|
} = this.props;
|
|
148
168
|
const mountParams = {
|
|
149
169
|
apihost,
|
|
@@ -156,7 +176,8 @@ class HCaptcha extends React.Component {
|
|
|
156
176
|
reportapi,
|
|
157
177
|
sentry,
|
|
158
178
|
custom,
|
|
159
|
-
loadAsync
|
|
179
|
+
loadAsync,
|
|
180
|
+
scriptLocation
|
|
160
181
|
};
|
|
161
182
|
|
|
162
183
|
mountCaptchaScript(mountParams)
|
|
@@ -181,6 +202,7 @@ class HCaptcha extends React.Component {
|
|
|
181
202
|
languageOverride: undefined
|
|
182
203
|
});
|
|
183
204
|
|
|
205
|
+
const hcaptcha = this._hcaptcha;
|
|
184
206
|
//Render hCaptcha widget and provide necessary callbacks - hCaptcha
|
|
185
207
|
const captchaId = hcaptcha.render(this.ref.current, renderParams);
|
|
186
208
|
|
|
@@ -191,6 +213,7 @@ class HCaptcha extends React.Component {
|
|
|
191
213
|
|
|
192
214
|
resetCaptcha() {
|
|
193
215
|
const { captchaId } = this.state;
|
|
216
|
+
const hcaptcha = this._hcaptcha;
|
|
194
217
|
|
|
195
218
|
if (!this.isReady()) {
|
|
196
219
|
return;
|
|
@@ -201,6 +224,7 @@ class HCaptcha extends React.Component {
|
|
|
201
224
|
|
|
202
225
|
removeCaptcha(callback) {
|
|
203
226
|
const { captchaId } = this.state;
|
|
227
|
+
const hcaptcha = this._hcaptcha;
|
|
204
228
|
|
|
205
229
|
if (!this.isReady()) {
|
|
206
230
|
return;
|
|
@@ -214,6 +238,10 @@ class HCaptcha extends React.Component {
|
|
|
214
238
|
|
|
215
239
|
handleOnLoad () {
|
|
216
240
|
this.setState({ isApiReady: true }, () => {
|
|
241
|
+
const element = getMountElement(this.props.scriptLocation);
|
|
242
|
+
const frame = getFrame(element);
|
|
243
|
+
|
|
244
|
+
this._hcaptcha = frame.window.hcaptcha;
|
|
217
245
|
|
|
218
246
|
// render captcha and wait for captcha id
|
|
219
247
|
this.renderCaptcha(() => {
|
|
@@ -227,6 +255,7 @@ class HCaptcha extends React.Component {
|
|
|
227
255
|
handleSubmit (event) {
|
|
228
256
|
const { onVerify } = this.props;
|
|
229
257
|
const { isRemoved, captchaId } = this.state;
|
|
258
|
+
const hcaptcha = this._hcaptcha;
|
|
230
259
|
|
|
231
260
|
if (typeof hcaptcha === 'undefined' || isRemoved) return
|
|
232
261
|
|
|
@@ -238,6 +267,7 @@ class HCaptcha extends React.Component {
|
|
|
238
267
|
handleExpire () {
|
|
239
268
|
const { onExpire } = this.props;
|
|
240
269
|
const { captchaId } = this.state;
|
|
270
|
+
const hcaptcha = this._hcaptcha;
|
|
241
271
|
|
|
242
272
|
if (!this.isReady()) {
|
|
243
273
|
return;
|
|
@@ -251,6 +281,7 @@ class HCaptcha extends React.Component {
|
|
|
251
281
|
handleError (event) {
|
|
252
282
|
const { onError } = this.props;
|
|
253
283
|
const { captchaId } = this.state;
|
|
284
|
+
const hcaptcha = this._hcaptcha;
|
|
254
285
|
|
|
255
286
|
if (this.isReady()) {
|
|
256
287
|
// If hCaptcha runs into error, reset captcha - hCaptcha
|
|
@@ -292,6 +323,7 @@ class HCaptcha extends React.Component {
|
|
|
292
323
|
|
|
293
324
|
execute (opts = null) {
|
|
294
325
|
const { captchaId } = this.state;
|
|
326
|
+
const hcaptcha = this._hcaptcha;
|
|
295
327
|
|
|
296
328
|
if (!this.isReady()) {
|
|
297
329
|
return;
|
|
@@ -306,6 +338,7 @@ class HCaptcha extends React.Component {
|
|
|
306
338
|
|
|
307
339
|
setData (data) {
|
|
308
340
|
const { captchaId } = this.state;
|
|
341
|
+
const hcaptcha = this._hcaptcha;
|
|
309
342
|
|
|
310
343
|
if (!this.isReady()) {
|
|
311
344
|
return;
|
|
@@ -319,10 +352,12 @@ class HCaptcha extends React.Component {
|
|
|
319
352
|
}
|
|
320
353
|
|
|
321
354
|
getResponse() {
|
|
355
|
+
const hcaptcha = this._hcaptcha;
|
|
322
356
|
return hcaptcha.getResponse(this.state.captchaId);
|
|
323
357
|
}
|
|
324
358
|
|
|
325
359
|
getRespKey() {
|
|
360
|
+
const hcaptcha = this._hcaptcha;
|
|
326
361
|
return hcaptcha.getRespKey(this.state.captchaId)
|
|
327
362
|
}
|
|
328
363
|
|
package/src/utils.js
CHANGED
|
@@ -6,4 +6,18 @@ function generateQuery(params) {
|
|
|
6
6
|
}).join("&");
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
function getFrame(element) {
|
|
10
|
+
const doc = (element && element.ownerDocument) || document;
|
|
11
|
+
const win = doc.defaultView || doc.parentWindow;
|
|
12
|
+
return { document: doc, window: win };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getMountElement(element) {
|
|
16
|
+
return element || document.head;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export {
|
|
20
|
+
generateQuery,
|
|
21
|
+
getFrame,
|
|
22
|
+
getMountElement
|
|
23
|
+
};
|