@hcaptcha/react-hcaptcha 1.7.0 → 1.8.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/dist/esm/index.js +77 -42
- package/dist/esm/utils.js +15 -1
- package/dist/index.js +78 -43
- package/dist/utils.js +16 -1
- package/package.json +2 -2
- package/src/index.js +65 -32
- package/src/utils.js +21 -6
package/dist/esm/index.js
CHANGED
|
@@ -1,49 +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
|
|
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
|
-
var
|
|
15
|
+
var element = getMountElement(params.scriptLocation);
|
|
21
16
|
delete params.scriptLocation;
|
|
22
|
-
var
|
|
17
|
+
var frame = getFrame(element);
|
|
18
|
+
var script = scripts.find(function (_ref) {
|
|
19
|
+
var scope = _ref.scope;
|
|
20
|
+
return scope === frame.window;
|
|
21
|
+
});
|
|
23
22
|
|
|
24
|
-
if (
|
|
23
|
+
if (frame.document.getElementById(SCRIPT_ID) && script) {
|
|
25
24
|
// API was already requested
|
|
26
|
-
return
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
window[HCAPTCHA_LOAD_FN_NAME] = resolveFn;
|
|
31
|
-
var domain = params.apihost || "https://js.hcaptcha.com";
|
|
32
|
-
delete params.apihost;
|
|
33
|
-
var script = doc.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;
|
|
25
|
+
return script.promise;
|
|
26
|
+
}
|
|
38
27
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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;
|
|
47
52
|
};
|
|
48
53
|
|
|
49
54
|
var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
@@ -52,7 +57,15 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
52
57
|
function HCaptcha(props) {
|
|
53
58
|
var _this;
|
|
54
59
|
|
|
55
|
-
_this = _React$Component.call(this, props) || this;
|
|
60
|
+
_this = _React$Component.call(this, props) || this;
|
|
61
|
+
/**
|
|
62
|
+
* Internal reference to track hCaptcha API
|
|
63
|
+
*
|
|
64
|
+
* Required as window is relative to initialization in application
|
|
65
|
+
* not where the script and iFrames have been loaded.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
_this._hcaptcha = undefined; // API Methods
|
|
56
69
|
|
|
57
70
|
_this.renderCaptcha = _this.renderCaptcha.bind(_assertThisInitialized(_this));
|
|
58
71
|
_this.resetCaptcha = _this.resetCaptcha.bind(_assertThisInitialized(_this));
|
|
@@ -67,11 +80,10 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
67
80
|
_this.handleOpen = _this.handleOpen.bind(_assertThisInitialized(_this));
|
|
68
81
|
_this.handleClose = _this.handleClose.bind(_assertThisInitialized(_this));
|
|
69
82
|
_this.handleChallengeExpired = _this.handleChallengeExpired.bind(_assertThisInitialized(_this));
|
|
70
|
-
var isApiReady = typeof hcaptcha !== 'undefined';
|
|
71
83
|
_this.ref = /*#__PURE__*/React.createRef();
|
|
72
84
|
_this.apiScriptRequested = false;
|
|
73
85
|
_this.state = {
|
|
74
|
-
isApiReady:
|
|
86
|
+
isApiReady: false,
|
|
75
87
|
isRemoved: false,
|
|
76
88
|
elementId: props.id,
|
|
77
89
|
captchaId: ''
|
|
@@ -82,8 +94,13 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
82
94
|
var _proto = HCaptcha.prototype;
|
|
83
95
|
|
|
84
96
|
_proto.componentDidMount = function componentDidMount() {
|
|
97
|
+
var _this2 = this;
|
|
98
|
+
|
|
85
99
|
// Once captcha is mounted intialize hCaptcha - hCaptcha
|
|
86
|
-
var
|
|
100
|
+
var element = getMountElement(this.props.scriptLocation);
|
|
101
|
+
var frame = getFrame(element);
|
|
102
|
+
this._hcaptcha = frame.window.hcaptcha || undefined;
|
|
103
|
+
var isApiReady = typeof this._hcaptcha !== 'undefined';
|
|
87
104
|
/*
|
|
88
105
|
* Check if hCaptcha has already been loaded,
|
|
89
106
|
* If Yes, render the captcha
|
|
@@ -91,7 +108,11 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
91
108
|
*/
|
|
92
109
|
|
|
93
110
|
if (isApiReady) {
|
|
94
|
-
this.
|
|
111
|
+
this.setState({
|
|
112
|
+
isApiReady: true
|
|
113
|
+
}, function () {
|
|
114
|
+
_this2.renderCaptcha();
|
|
115
|
+
});
|
|
95
116
|
return;
|
|
96
117
|
}
|
|
97
118
|
|
|
@@ -100,6 +121,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
100
121
|
|
|
101
122
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
|
102
123
|
var captchaId = this.state.captchaId;
|
|
124
|
+
var hcaptcha = this._hcaptcha;
|
|
103
125
|
|
|
104
126
|
if (!this.isReady()) {
|
|
105
127
|
return;
|
|
@@ -120,18 +142,18 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
120
142
|
};
|
|
121
143
|
|
|
122
144
|
_proto.componentDidUpdate = function componentDidUpdate(prevProps) {
|
|
123
|
-
var
|
|
145
|
+
var _this3 = this;
|
|
124
146
|
|
|
125
147
|
// Prop Keys that could change
|
|
126
148
|
var keys = ['sitekey', 'size', 'theme', 'tabindex', 'languageOverride', 'endpoint']; // See if any props changed during component update
|
|
127
149
|
|
|
128
150
|
var match = keys.every(function (key) {
|
|
129
|
-
return prevProps[key] ===
|
|
151
|
+
return prevProps[key] === _this3.props[key];
|
|
130
152
|
}); // If they have changed, remove current captcha and render a new one
|
|
131
153
|
|
|
132
154
|
if (!match) {
|
|
133
155
|
this.removeCaptcha(function () {
|
|
134
|
-
|
|
156
|
+
_this3.renderCaptcha();
|
|
135
157
|
});
|
|
136
158
|
}
|
|
137
159
|
};
|
|
@@ -185,7 +207,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
185
207
|
}, this.props, {
|
|
186
208
|
hl: this.props.hl || this.props.languageOverride,
|
|
187
209
|
languageOverride: undefined
|
|
188
|
-
});
|
|
210
|
+
});
|
|
211
|
+
var hcaptcha = this._hcaptcha; //Render hCaptcha widget and provide necessary callbacks - hCaptcha
|
|
189
212
|
|
|
190
213
|
var captchaId = hcaptcha.render(this.ref.current, renderParams);
|
|
191
214
|
this.setState({
|
|
@@ -198,6 +221,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
198
221
|
|
|
199
222
|
_proto.resetCaptcha = function resetCaptcha() {
|
|
200
223
|
var captchaId = this.state.captchaId;
|
|
224
|
+
var hcaptcha = this._hcaptcha;
|
|
201
225
|
|
|
202
226
|
if (!this.isReady()) {
|
|
203
227
|
return;
|
|
@@ -209,6 +233,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
209
233
|
|
|
210
234
|
_proto.removeCaptcha = function removeCaptcha(callback) {
|
|
211
235
|
var captchaId = this.state.captchaId;
|
|
236
|
+
var hcaptcha = this._hcaptcha;
|
|
212
237
|
|
|
213
238
|
if (!this.isReady()) {
|
|
214
239
|
return;
|
|
@@ -223,15 +248,18 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
223
248
|
};
|
|
224
249
|
|
|
225
250
|
_proto.handleOnLoad = function handleOnLoad() {
|
|
226
|
-
var
|
|
251
|
+
var _this4 = this;
|
|
227
252
|
|
|
228
253
|
this.setState({
|
|
229
254
|
isApiReady: true
|
|
230
255
|
}, function () {
|
|
231
|
-
|
|
232
|
-
|
|
256
|
+
var element = getMountElement(_this4.props.scriptLocation);
|
|
257
|
+
var frame = getFrame(element);
|
|
258
|
+
_this4._hcaptcha = frame.window.hcaptcha; // render captcha and wait for captcha id
|
|
259
|
+
|
|
260
|
+
_this4.renderCaptcha(function () {
|
|
233
261
|
// trigger onLoad if it exists
|
|
234
|
-
var onLoad =
|
|
262
|
+
var onLoad = _this4.props.onLoad;
|
|
235
263
|
if (onLoad) onLoad();
|
|
236
264
|
});
|
|
237
265
|
});
|
|
@@ -242,6 +270,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
242
270
|
var _this$state = this.state,
|
|
243
271
|
isRemoved = _this$state.isRemoved,
|
|
244
272
|
captchaId = _this$state.captchaId;
|
|
273
|
+
var hcaptcha = this._hcaptcha;
|
|
245
274
|
if (typeof hcaptcha === 'undefined' || isRemoved) return;
|
|
246
275
|
var token = hcaptcha.getResponse(captchaId); //Get response token from hCaptcha widget
|
|
247
276
|
|
|
@@ -253,6 +282,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
253
282
|
_proto.handleExpire = function handleExpire() {
|
|
254
283
|
var onExpire = this.props.onExpire;
|
|
255
284
|
var captchaId = this.state.captchaId;
|
|
285
|
+
var hcaptcha = this._hcaptcha;
|
|
256
286
|
|
|
257
287
|
if (!this.isReady()) {
|
|
258
288
|
return;
|
|
@@ -266,6 +296,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
266
296
|
_proto.handleError = function handleError(event) {
|
|
267
297
|
var onError = this.props.onError;
|
|
268
298
|
var captchaId = this.state.captchaId;
|
|
299
|
+
var hcaptcha = this._hcaptcha;
|
|
269
300
|
|
|
270
301
|
if (this.isReady()) {
|
|
271
302
|
// If hCaptcha runs into error, reset captcha - hCaptcha
|
|
@@ -312,6 +343,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
312
343
|
}
|
|
313
344
|
|
|
314
345
|
var captchaId = this.state.captchaId;
|
|
346
|
+
var hcaptcha = this._hcaptcha;
|
|
315
347
|
|
|
316
348
|
if (!this.isReady()) {
|
|
317
349
|
return;
|
|
@@ -326,6 +358,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
326
358
|
|
|
327
359
|
_proto.setData = function setData(data) {
|
|
328
360
|
var captchaId = this.state.captchaId;
|
|
361
|
+
var hcaptcha = this._hcaptcha;
|
|
329
362
|
|
|
330
363
|
if (!this.isReady()) {
|
|
331
364
|
return;
|
|
@@ -339,10 +372,12 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
339
372
|
};
|
|
340
373
|
|
|
341
374
|
_proto.getResponse = function getResponse() {
|
|
375
|
+
var hcaptcha = this._hcaptcha;
|
|
342
376
|
return hcaptcha.getResponse(this.state.captchaId);
|
|
343
377
|
};
|
|
344
378
|
|
|
345
379
|
_proto.getRespKey = function getRespKey() {
|
|
380
|
+
var hcaptcha = this._hcaptcha;
|
|
346
381
|
return hcaptcha.getRespKey(this.state.captchaId);
|
|
347
382
|
};
|
|
348
383
|
|
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 || window;
|
|
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,42 +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
|
-
var
|
|
41
|
+
var element = (0, _utils.getMountElement)(params.scriptLocation);
|
|
47
42
|
delete params.scriptLocation;
|
|
48
|
-
var
|
|
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
|
+
});
|
|
49
48
|
|
|
50
|
-
if (
|
|
49
|
+
if (frame.document.getElementById(SCRIPT_ID) && script) {
|
|
51
50
|
// API was already requested
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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;
|
|
73
78
|
};
|
|
74
79
|
|
|
75
80
|
var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
@@ -81,7 +86,15 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
81
86
|
var _this;
|
|
82
87
|
|
|
83
88
|
(0, _classCallCheck2["default"])(this, HCaptcha);
|
|
84
|
-
_this = _super.call(this, props);
|
|
89
|
+
_this = _super.call(this, props);
|
|
90
|
+
/**
|
|
91
|
+
* Internal reference to track hCaptcha API
|
|
92
|
+
*
|
|
93
|
+
* Required as window is relative to initialization in application
|
|
94
|
+
* not where the script and iFrames have been loaded.
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
_this._hcaptcha = undefined; // API Methods
|
|
85
98
|
|
|
86
99
|
_this.renderCaptcha = _this.renderCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
|
|
87
100
|
_this.resetCaptcha = _this.resetCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
|
|
@@ -96,11 +109,10 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
96
109
|
_this.handleOpen = _this.handleOpen.bind((0, _assertThisInitialized2["default"])(_this));
|
|
97
110
|
_this.handleClose = _this.handleClose.bind((0, _assertThisInitialized2["default"])(_this));
|
|
98
111
|
_this.handleChallengeExpired = _this.handleChallengeExpired.bind((0, _assertThisInitialized2["default"])(_this));
|
|
99
|
-
var isApiReady = typeof hcaptcha !== 'undefined';
|
|
100
112
|
_this.ref = /*#__PURE__*/React.createRef();
|
|
101
113
|
_this.apiScriptRequested = false;
|
|
102
114
|
_this.state = {
|
|
103
|
-
isApiReady:
|
|
115
|
+
isApiReady: false,
|
|
104
116
|
isRemoved: false,
|
|
105
117
|
elementId: props.id,
|
|
106
118
|
captchaId: ''
|
|
@@ -111,8 +123,13 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
111
123
|
(0, _createClass2["default"])(HCaptcha, [{
|
|
112
124
|
key: "componentDidMount",
|
|
113
125
|
value: function componentDidMount() {
|
|
126
|
+
var _this2 = this;
|
|
127
|
+
|
|
114
128
|
// Once captcha is mounted intialize hCaptcha - hCaptcha
|
|
115
|
-
var
|
|
129
|
+
var element = (0, _utils.getMountElement)(this.props.scriptLocation);
|
|
130
|
+
var frame = (0, _utils.getFrame)(element);
|
|
131
|
+
this._hcaptcha = frame.window.hcaptcha || undefined;
|
|
132
|
+
var isApiReady = typeof this._hcaptcha !== 'undefined';
|
|
116
133
|
/*
|
|
117
134
|
* Check if hCaptcha has already been loaded,
|
|
118
135
|
* If Yes, render the captcha
|
|
@@ -120,7 +137,11 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
120
137
|
*/
|
|
121
138
|
|
|
122
139
|
if (isApiReady) {
|
|
123
|
-
this.
|
|
140
|
+
this.setState({
|
|
141
|
+
isApiReady: true
|
|
142
|
+
}, function () {
|
|
143
|
+
_this2.renderCaptcha();
|
|
144
|
+
});
|
|
124
145
|
return;
|
|
125
146
|
}
|
|
126
147
|
|
|
@@ -130,6 +151,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
130
151
|
key: "componentWillUnmount",
|
|
131
152
|
value: function componentWillUnmount() {
|
|
132
153
|
var captchaId = this.state.captchaId;
|
|
154
|
+
var hcaptcha = this._hcaptcha;
|
|
133
155
|
|
|
134
156
|
if (!this.isReady()) {
|
|
135
157
|
return;
|
|
@@ -152,18 +174,18 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
152
174
|
}, {
|
|
153
175
|
key: "componentDidUpdate",
|
|
154
176
|
value: function componentDidUpdate(prevProps) {
|
|
155
|
-
var
|
|
177
|
+
var _this3 = this;
|
|
156
178
|
|
|
157
179
|
// Prop Keys that could change
|
|
158
180
|
var keys = ['sitekey', 'size', 'theme', 'tabindex', 'languageOverride', 'endpoint']; // See if any props changed during component update
|
|
159
181
|
|
|
160
182
|
var match = keys.every(function (key) {
|
|
161
|
-
return prevProps[key] ===
|
|
183
|
+
return prevProps[key] === _this3.props[key];
|
|
162
184
|
}); // If they have changed, remove current captcha and render a new one
|
|
163
185
|
|
|
164
186
|
if (!match) {
|
|
165
187
|
this.removeCaptcha(function () {
|
|
166
|
-
|
|
188
|
+
_this3.renderCaptcha();
|
|
167
189
|
});
|
|
168
190
|
}
|
|
169
191
|
}
|
|
@@ -219,7 +241,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
219
241
|
}, this.props, {
|
|
220
242
|
hl: this.props.hl || this.props.languageOverride,
|
|
221
243
|
languageOverride: undefined
|
|
222
|
-
});
|
|
244
|
+
});
|
|
245
|
+
var hcaptcha = this._hcaptcha; //Render hCaptcha widget and provide necessary callbacks - hCaptcha
|
|
223
246
|
|
|
224
247
|
var captchaId = hcaptcha.render(this.ref.current, renderParams);
|
|
225
248
|
this.setState({
|
|
@@ -233,6 +256,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
233
256
|
key: "resetCaptcha",
|
|
234
257
|
value: function resetCaptcha() {
|
|
235
258
|
var captchaId = this.state.captchaId;
|
|
259
|
+
var hcaptcha = this._hcaptcha;
|
|
236
260
|
|
|
237
261
|
if (!this.isReady()) {
|
|
238
262
|
return;
|
|
@@ -245,6 +269,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
245
269
|
key: "removeCaptcha",
|
|
246
270
|
value: function removeCaptcha(callback) {
|
|
247
271
|
var captchaId = this.state.captchaId;
|
|
272
|
+
var hcaptcha = this._hcaptcha;
|
|
248
273
|
|
|
249
274
|
if (!this.isReady()) {
|
|
250
275
|
return;
|
|
@@ -260,15 +285,18 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
260
285
|
}, {
|
|
261
286
|
key: "handleOnLoad",
|
|
262
287
|
value: function handleOnLoad() {
|
|
263
|
-
var
|
|
288
|
+
var _this4 = this;
|
|
264
289
|
|
|
265
290
|
this.setState({
|
|
266
291
|
isApiReady: true
|
|
267
292
|
}, function () {
|
|
268
|
-
|
|
269
|
-
|
|
293
|
+
var element = (0, _utils.getMountElement)(_this4.props.scriptLocation);
|
|
294
|
+
var frame = (0, _utils.getFrame)(element);
|
|
295
|
+
_this4._hcaptcha = frame.window.hcaptcha; // render captcha and wait for captcha id
|
|
296
|
+
|
|
297
|
+
_this4.renderCaptcha(function () {
|
|
270
298
|
// trigger onLoad if it exists
|
|
271
|
-
var onLoad =
|
|
299
|
+
var onLoad = _this4.props.onLoad;
|
|
272
300
|
if (onLoad) onLoad();
|
|
273
301
|
});
|
|
274
302
|
});
|
|
@@ -280,6 +308,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
280
308
|
var _this$state = this.state,
|
|
281
309
|
isRemoved = _this$state.isRemoved,
|
|
282
310
|
captchaId = _this$state.captchaId;
|
|
311
|
+
var hcaptcha = this._hcaptcha;
|
|
283
312
|
if (typeof hcaptcha === 'undefined' || isRemoved) return;
|
|
284
313
|
var token = hcaptcha.getResponse(captchaId); //Get response token from hCaptcha widget
|
|
285
314
|
|
|
@@ -292,6 +321,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
292
321
|
value: function handleExpire() {
|
|
293
322
|
var onExpire = this.props.onExpire;
|
|
294
323
|
var captchaId = this.state.captchaId;
|
|
324
|
+
var hcaptcha = this._hcaptcha;
|
|
295
325
|
|
|
296
326
|
if (!this.isReady()) {
|
|
297
327
|
return;
|
|
@@ -306,6 +336,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
306
336
|
value: function handleError(event) {
|
|
307
337
|
var onError = this.props.onError;
|
|
308
338
|
var captchaId = this.state.captchaId;
|
|
339
|
+
var hcaptcha = this._hcaptcha;
|
|
309
340
|
|
|
310
341
|
if (this.isReady()) {
|
|
311
342
|
// If hCaptcha runs into error, reset captcha - hCaptcha
|
|
@@ -354,6 +385,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
354
385
|
value: function execute() {
|
|
355
386
|
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
356
387
|
var captchaId = this.state.captchaId;
|
|
388
|
+
var hcaptcha = this._hcaptcha;
|
|
357
389
|
|
|
358
390
|
if (!this.isReady()) {
|
|
359
391
|
return;
|
|
@@ -369,6 +401,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
369
401
|
key: "setData",
|
|
370
402
|
value: function setData(data) {
|
|
371
403
|
var captchaId = this.state.captchaId;
|
|
404
|
+
var hcaptcha = this._hcaptcha;
|
|
372
405
|
|
|
373
406
|
if (!this.isReady()) {
|
|
374
407
|
return;
|
|
@@ -383,11 +416,13 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
|
|
|
383
416
|
}, {
|
|
384
417
|
key: "getResponse",
|
|
385
418
|
value: function getResponse() {
|
|
419
|
+
var hcaptcha = this._hcaptcha;
|
|
386
420
|
return hcaptcha.getResponse(this.state.captchaId);
|
|
387
421
|
}
|
|
388
422
|
}, {
|
|
389
423
|
key: "getRespKey",
|
|
390
424
|
value: function getRespKey() {
|
|
425
|
+
var hcaptcha = this._hcaptcha;
|
|
391
426
|
return hcaptcha.getRespKey(this.state.captchaId);
|
|
392
427
|
}
|
|
393
428
|
}, {
|
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 || window;
|
|
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.1",
|
|
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,49 +1,50 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { generateQuery } from
|
|
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
|
-
const mountCaptchaScript = (params={}) => {
|
|
17
|
-
const
|
|
11
|
+
const mountCaptchaScript = (params = {}) => {
|
|
12
|
+
const element = getMountElement(params.scriptLocation);
|
|
18
13
|
delete params.scriptLocation;
|
|
19
14
|
|
|
20
|
-
const
|
|
15
|
+
const frame = getFrame(element);
|
|
16
|
+
const script = scripts.find(({ scope }) => scope === frame.window);
|
|
21
17
|
|
|
22
|
-
if (
|
|
18
|
+
if (frame.document.getElementById(SCRIPT_ID) && script) {
|
|
23
19
|
// API was already requested
|
|
24
|
-
return
|
|
20
|
+
return script.promise;
|
|
25
21
|
}
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
const promise = new Promise((resolve, reject) => {
|
|
24
|
+
// Create global onload callback
|
|
25
|
+
frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve;
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
const domain = params.apihost || "https://js.hcaptcha.com";
|
|
28
|
+
delete params.apihost;
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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}`;
|
|
36
33
|
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
script.async = params.loadAsync !== undefined? params.loadAsync : true;
|
|
35
|
+
delete params.loadAsync;
|
|
39
36
|
|
|
40
|
-
|
|
37
|
+
script.onerror = (event) => reject('script-error');
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
const query = generateQuery(params);
|
|
40
|
+
script.src += query !== ""? `&${query}` : "";
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
element.appendChild(script);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
scripts.push({ promise, scope: frame.window });
|
|
46
|
+
|
|
47
|
+
return promise;
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
|
|
@@ -51,6 +52,14 @@ class HCaptcha extends React.Component {
|
|
|
51
52
|
constructor (props) {
|
|
52
53
|
super(props);
|
|
53
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Internal reference to track hCaptcha API
|
|
57
|
+
*
|
|
58
|
+
* Required as window is relative to initialization in application
|
|
59
|
+
* not where the script and iFrames have been loaded.
|
|
60
|
+
*/
|
|
61
|
+
this._hcaptcha = undefined;
|
|
62
|
+
|
|
54
63
|
// API Methods
|
|
55
64
|
this.renderCaptcha = this.renderCaptcha.bind(this);
|
|
56
65
|
this.resetCaptcha = this.resetCaptcha.bind(this);
|
|
@@ -67,13 +76,11 @@ class HCaptcha extends React.Component {
|
|
|
67
76
|
this.handleClose = this.handleClose.bind(this);
|
|
68
77
|
this.handleChallengeExpired = this.handleChallengeExpired.bind(this);
|
|
69
78
|
|
|
70
|
-
const isApiReady = typeof hcaptcha !== 'undefined';
|
|
71
|
-
|
|
72
79
|
this.ref = React.createRef();
|
|
73
80
|
this.apiScriptRequested = false;
|
|
74
81
|
|
|
75
82
|
this.state = {
|
|
76
|
-
isApiReady,
|
|
83
|
+
isApiReady: false,
|
|
77
84
|
isRemoved: false,
|
|
78
85
|
elementId: props.id,
|
|
79
86
|
captchaId: ''
|
|
@@ -81,7 +88,11 @@ class HCaptcha extends React.Component {
|
|
|
81
88
|
}
|
|
82
89
|
|
|
83
90
|
componentDidMount () { // Once captcha is mounted intialize hCaptcha - hCaptcha
|
|
84
|
-
const
|
|
91
|
+
const element = getMountElement(this.props.scriptLocation);
|
|
92
|
+
const frame = getFrame(element);
|
|
93
|
+
this._hcaptcha = frame.window.hcaptcha || undefined;
|
|
94
|
+
|
|
95
|
+
const isApiReady = typeof this._hcaptcha !== 'undefined';
|
|
85
96
|
|
|
86
97
|
/*
|
|
87
98
|
* Check if hCaptcha has already been loaded,
|
|
@@ -89,7 +100,14 @@ class HCaptcha extends React.Component {
|
|
|
89
100
|
* If No, create script tag and wait to render the captcha
|
|
90
101
|
*/
|
|
91
102
|
if (isApiReady) {
|
|
92
|
-
this.
|
|
103
|
+
this.setState(
|
|
104
|
+
{
|
|
105
|
+
isApiReady: true
|
|
106
|
+
},
|
|
107
|
+
() => {
|
|
108
|
+
this.renderCaptcha();
|
|
109
|
+
}
|
|
110
|
+
);
|
|
93
111
|
|
|
94
112
|
return;
|
|
95
113
|
}
|
|
@@ -99,6 +117,7 @@ class HCaptcha extends React.Component {
|
|
|
99
117
|
|
|
100
118
|
componentWillUnmount() {
|
|
101
119
|
const { captchaId } = this.state;
|
|
120
|
+
const hcaptcha = this._hcaptcha;
|
|
102
121
|
|
|
103
122
|
if (!this.isReady()) {
|
|
104
123
|
return;
|
|
@@ -163,7 +182,7 @@ class HCaptcha extends React.Component {
|
|
|
163
182
|
sentry,
|
|
164
183
|
custom,
|
|
165
184
|
loadAsync,
|
|
166
|
-
scriptLocation
|
|
185
|
+
scriptLocation,
|
|
167
186
|
};
|
|
168
187
|
|
|
169
188
|
mountCaptchaScript(mountParams)
|
|
@@ -188,6 +207,7 @@ class HCaptcha extends React.Component {
|
|
|
188
207
|
languageOverride: undefined
|
|
189
208
|
});
|
|
190
209
|
|
|
210
|
+
const hcaptcha = this._hcaptcha;
|
|
191
211
|
//Render hCaptcha widget and provide necessary callbacks - hCaptcha
|
|
192
212
|
const captchaId = hcaptcha.render(this.ref.current, renderParams);
|
|
193
213
|
|
|
@@ -198,6 +218,7 @@ class HCaptcha extends React.Component {
|
|
|
198
218
|
|
|
199
219
|
resetCaptcha() {
|
|
200
220
|
const { captchaId } = this.state;
|
|
221
|
+
const hcaptcha = this._hcaptcha;
|
|
201
222
|
|
|
202
223
|
if (!this.isReady()) {
|
|
203
224
|
return;
|
|
@@ -208,6 +229,7 @@ class HCaptcha extends React.Component {
|
|
|
208
229
|
|
|
209
230
|
removeCaptcha(callback) {
|
|
210
231
|
const { captchaId } = this.state;
|
|
232
|
+
const hcaptcha = this._hcaptcha;
|
|
211
233
|
|
|
212
234
|
if (!this.isReady()) {
|
|
213
235
|
return;
|
|
@@ -221,6 +243,10 @@ class HCaptcha extends React.Component {
|
|
|
221
243
|
|
|
222
244
|
handleOnLoad () {
|
|
223
245
|
this.setState({ isApiReady: true }, () => {
|
|
246
|
+
const element = getMountElement(this.props.scriptLocation);
|
|
247
|
+
const frame = getFrame(element);
|
|
248
|
+
|
|
249
|
+
this._hcaptcha = frame.window.hcaptcha;
|
|
224
250
|
|
|
225
251
|
// render captcha and wait for captcha id
|
|
226
252
|
this.renderCaptcha(() => {
|
|
@@ -234,6 +260,7 @@ class HCaptcha extends React.Component {
|
|
|
234
260
|
handleSubmit (event) {
|
|
235
261
|
const { onVerify } = this.props;
|
|
236
262
|
const { isRemoved, captchaId } = this.state;
|
|
263
|
+
const hcaptcha = this._hcaptcha;
|
|
237
264
|
|
|
238
265
|
if (typeof hcaptcha === 'undefined' || isRemoved) return
|
|
239
266
|
|
|
@@ -245,6 +272,7 @@ class HCaptcha extends React.Component {
|
|
|
245
272
|
handleExpire () {
|
|
246
273
|
const { onExpire } = this.props;
|
|
247
274
|
const { captchaId } = this.state;
|
|
275
|
+
const hcaptcha = this._hcaptcha;
|
|
248
276
|
|
|
249
277
|
if (!this.isReady()) {
|
|
250
278
|
return;
|
|
@@ -258,6 +286,7 @@ class HCaptcha extends React.Component {
|
|
|
258
286
|
handleError (event) {
|
|
259
287
|
const { onError } = this.props;
|
|
260
288
|
const { captchaId } = this.state;
|
|
289
|
+
const hcaptcha = this._hcaptcha;
|
|
261
290
|
|
|
262
291
|
if (this.isReady()) {
|
|
263
292
|
// If hCaptcha runs into error, reset captcha - hCaptcha
|
|
@@ -299,6 +328,7 @@ class HCaptcha extends React.Component {
|
|
|
299
328
|
|
|
300
329
|
execute (opts = null) {
|
|
301
330
|
const { captchaId } = this.state;
|
|
331
|
+
const hcaptcha = this._hcaptcha;
|
|
302
332
|
|
|
303
333
|
if (!this.isReady()) {
|
|
304
334
|
return;
|
|
@@ -313,6 +343,7 @@ class HCaptcha extends React.Component {
|
|
|
313
343
|
|
|
314
344
|
setData (data) {
|
|
315
345
|
const { captchaId } = this.state;
|
|
346
|
+
const hcaptcha = this._hcaptcha;
|
|
316
347
|
|
|
317
348
|
if (!this.isReady()) {
|
|
318
349
|
return;
|
|
@@ -326,10 +357,12 @@ class HCaptcha extends React.Component {
|
|
|
326
357
|
}
|
|
327
358
|
|
|
328
359
|
getResponse() {
|
|
360
|
+
const hcaptcha = this._hcaptcha;
|
|
329
361
|
return hcaptcha.getResponse(this.state.captchaId);
|
|
330
362
|
}
|
|
331
363
|
|
|
332
364
|
getRespKey() {
|
|
365
|
+
const hcaptcha = this._hcaptcha;
|
|
333
366
|
return hcaptcha.getRespKey(this.state.captchaId)
|
|
334
367
|
}
|
|
335
368
|
|
package/src/utils.js
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
function generateQuery(params) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
7
|
};
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
function getFrame(element) {
|
|
10
|
+
const doc = (element && element.ownerDocument) || document;
|
|
11
|
+
const win = doc.defaultView || doc.parentWindow || window;
|
|
12
|
+
|
|
13
|
+
return { document: doc, window: win };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getMountElement(element) {
|
|
17
|
+
return element || document.head;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
generateQuery,
|
|
22
|
+
getFrame,
|
|
23
|
+
getMountElement
|
|
24
|
+
};
|