@hcaptcha/react-hcaptcha 0.3.4 → 0.3.8

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 CHANGED
@@ -33,13 +33,6 @@ import HCaptcha from '@hcaptcha/react-hcaptcha';
33
33
  </FormComponent>
34
34
  ```
35
35
 
36
- #### Usage with TypeScript
37
- Add the types from DefinitelyTyped
38
-
39
- ```
40
- npm i -D @types/hcaptcha__react-hcaptcha
41
- ```
42
-
43
36
  **A note about TypeScript usage:** If you want to reassign the component name, you could consider making a util that imports the component, then re-exports it as a default. Example:
44
37
 
45
38
  ```ts
@@ -78,6 +71,7 @@ In these instances, you'll most likely want to use `ref` to handle the callbacks
78
71
  |`imghost`|String|No|`-`|See enterprise docs.|
79
72
  |`reportapi`|String|No|`-`|See enterprise docs.|
80
73
  |`sentry`|String|No|`-`|See enterprise docs.|
74
+ |`custom`|Boolean|No|`-`|See enterprise docs.|
81
75
 
82
76
  ### Events
83
77
 
@@ -86,12 +80,13 @@ In these instances, you'll most likely want to use `ref` to handle the callbacks
86
80
  |`onError`|`err`|When an error occurs. Component will reset immediately after an error.|
87
81
  |`onVerify`|`token, eKey`|When challenge is completed. The response `token` and an `eKey` (session id) are passed along.|
88
82
  |`onExpire`|-|When the current token expires.|
83
+ |`onLoad`|-|When the hCaptcha API loads.|
89
84
 
90
85
  ### Methods
91
86
 
92
87
  |Method|Description|
93
88
  |---|---|
94
- |`execute()`|Programmatically trigger a challenge request|
89
+ |`execute()`|Programmatically trigger a challenge request. Additionally, this method can be run asynchronously and returns a promise with the `token` and `eKey` when the challenge is completed.|
95
90
  |`resetCaptcha()`|Reset the current challenge|
96
91
 
97
92
 
package/dist/index.js CHANGED
@@ -1,33 +1,31 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
4
 
5
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
5
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
6
6
 
7
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
7
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
8
8
 
9
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
9
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
10
10
 
11
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
11
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
12
12
 
13
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
13
+ var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
14
14
 
15
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
15
+ var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
16
16
 
17
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
17
+ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
18
18
 
19
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
19
+ var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
20
20
 
21
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
21
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
22
22
 
23
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
23
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
24
24
 
25
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
25
+ 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); }; }
26
26
 
27
27
  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; } }
28
28
 
29
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
30
-
31
29
  var React = require('react');
32
30
 
33
31
  var _require = require("./utils.js"),
@@ -35,12 +33,12 @@ var _require = require("./utils.js"),
35
33
 
36
34
 
37
35
  var onLoadListeners = [];
38
- var captchaScriptCreated = false; // Generate hCaptcha API Script
36
+ var apiScriptRequested = false; // Generate hCaptcha API Script
39
37
 
40
- var CaptchaScript = function CaptchaScript() {
38
+ var mountCaptchaScript = function mountCaptchaScript() {
41
39
  var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
40
+ apiScriptRequested = true; // Create global onload callback
42
41
 
43
- // Create global onload callback
44
42
  window.hcaptchaOnLoad = function () {
45
43
  // Iterate over onload listeners, call each listener
46
44
  onLoadListeners = onLoadListeners.filter(function (listener) {
@@ -60,27 +58,25 @@ var CaptchaScript = function CaptchaScript() {
60
58
  };
61
59
 
62
60
  var HCaptcha = /*#__PURE__*/function (_React$Component) {
63
- _inherits(HCaptcha, _React$Component);
61
+ (0, _inherits2["default"])(HCaptcha, _React$Component);
64
62
 
65
63
  var _super = _createSuper(HCaptcha);
66
64
 
67
65
  function HCaptcha(props) {
68
66
  var _this;
69
67
 
70
- _classCallCheck(this, HCaptcha);
71
-
68
+ (0, _classCallCheck2["default"])(this, HCaptcha);
72
69
  _this = _super.call(this, props); // API Methods
73
70
 
74
- _this.renderCaptcha = _this.renderCaptcha.bind(_assertThisInitialized(_this));
75
- _this.resetCaptcha = _this.resetCaptcha.bind(_assertThisInitialized(_this));
76
- _this.removeCaptcha = _this.removeCaptcha.bind(_assertThisInitialized(_this)); // Event Handlers
71
+ _this.renderCaptcha = _this.renderCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
72
+ _this.resetCaptcha = _this.resetCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
73
+ _this.removeCaptcha = _this.removeCaptcha.bind((0, _assertThisInitialized2["default"])(_this)); // Event Handlers
77
74
 
78
- _this.handleOnLoad = _this.handleOnLoad.bind(_assertThisInitialized(_this));
79
- _this.handleSubmit = _this.handleSubmit.bind(_assertThisInitialized(_this));
80
- _this.handleExpire = _this.handleExpire.bind(_assertThisInitialized(_this));
81
- _this.handleError = _this.handleError.bind(_assertThisInitialized(_this));
75
+ _this.handleOnLoad = _this.handleOnLoad.bind((0, _assertThisInitialized2["default"])(_this));
76
+ _this.handleSubmit = _this.handleSubmit.bind((0, _assertThisInitialized2["default"])(_this));
77
+ _this.handleExpire = _this.handleExpire.bind((0, _assertThisInitialized2["default"])(_this));
78
+ _this.handleError = _this.handleError.bind((0, _assertThisInitialized2["default"])(_this));
82
79
  var isApiReady = typeof hcaptcha !== 'undefined';
83
- if (!isApiReady) captchaScriptCreated = false;
84
80
  _this.ref = React.createRef();
85
81
  _this.state = {
86
82
  isApiReady: isApiReady,
@@ -91,7 +87,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
91
87
  return _this;
92
88
  }
93
89
 
94
- _createClass(HCaptcha, [{
90
+ (0, _createClass2["default"])(HCaptcha, [{
95
91
  key: "componentDidMount",
96
92
  value: function componentDidMount() {
97
93
  //Once captcha is mounted intialize hCaptcha - hCaptcha
@@ -104,15 +100,15 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
104
100
  hl = _this$props.languageOverride,
105
101
  reCaptchaCompat = _this$props.reCaptchaCompat,
106
102
  reportapi = _this$props.reportapi,
107
- sentry = _this$props.sentry;
103
+ sentry = _this$props.sentry,
104
+ custom = _this$props.custom;
108
105
  var isApiReady = this.state.isApiReady;
109
106
 
110
107
  if (!isApiReady) {
111
108
  //Check if hCaptcha has already been loaded, if not create script tag and wait to render captcha
112
- if (!captchaScriptCreated) {
109
+ if (!apiScriptRequested) {
113
110
  // Only create the script tag once, use a global variable to track
114
- captchaScriptCreated = true;
115
- CaptchaScript({
111
+ mountCaptchaScript({
116
112
  apihost: apihost,
117
113
  assethost: assethost,
118
114
  endpoint: endpoint,
@@ -121,7 +117,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
121
117
  imghost: imghost,
122
118
  recaptchacompat: reCaptchaCompat === false ? "off" : null,
123
119
  reportapi: reportapi,
124
- sentry: sentry
120
+ sentry: sentry,
121
+ custom: custom
125
122
  });
126
123
  } // Add onload callback to global onload listeners
127
124
 
@@ -221,6 +218,10 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
221
218
  this.setState({
222
219
  isApiReady: true
223
220
  }, function () {
221
+ // trigger onLoad if it exists
222
+ var onLoad = _this3.props.onLoad;
223
+ if (onLoad) onLoad(); // render captcha
224
+
224
225
  _this3.renderCaptcha();
225
226
  });
226
227
  }
@@ -267,12 +268,18 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
267
268
  }, {
268
269
  key: "execute",
269
270
  value: function execute() {
271
+ var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
270
272
  var _this$state7 = this.state,
271
273
  isApiReady = _this$state7.isApiReady,
272
274
  isRemoved = _this$state7.isRemoved,
273
275
  captchaId = _this$state7.captchaId;
274
276
  if (!isApiReady || isRemoved) return;
275
- hcaptcha.execute(captchaId);
277
+
278
+ if (opts && (0, _typeof2["default"])(opts) !== "object") {
279
+ opts = null;
280
+ }
281
+
282
+ return hcaptcha.execute(captchaId, opts);
276
283
  }
277
284
  }, {
278
285
  key: "render",
@@ -284,7 +291,6 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
284
291
  });
285
292
  }
286
293
  }]);
287
-
288
294
  return HCaptcha;
289
295
  }(React.Component);
290
296
 
package/dist/utils.js CHANGED
@@ -1,26 +1,18 @@
1
1
  "use strict";
2
2
 
3
- function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
4
 
5
- function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6
-
7
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8
-
9
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
10
-
11
- function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
12
-
13
- function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
5
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
14
6
 
15
7
  function generateQuery(params) {
16
8
  return Object.entries(params).filter(function (_ref) {
17
- var _ref2 = _slicedToArray(_ref, 2),
9
+ var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
18
10
  key = _ref2[0],
19
11
  value = _ref2[1];
20
12
 
21
13
  return value || value === false;
22
14
  }).map(function (_ref3) {
23
- var _ref4 = _slicedToArray(_ref3, 2),
15
+ var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2),
24
16
  key = _ref4[0],
25
17
  value = _ref4[1];
26
18
 
package/package.json CHANGED
@@ -1,11 +1,18 @@
1
1
  {
2
2
  "name": "@hcaptcha/react-hcaptcha",
3
- "version": "0.3.4",
4
- "description": "A React library for hCaptcha",
3
+ "version": "0.3.8",
4
+ "types": "types/index.d.ts",
5
5
  "main": "dist/index.js",
6
+ "files": [
7
+ "src",
8
+ "dist",
9
+ "types/index.d.ts"
10
+ ],
11
+ "description": "A React library for hCaptcha",
6
12
  "scripts": {
7
13
  "start": "webpack-dev-server --config ./webpack.config.js --mode development",
8
14
  "test": "jest",
15
+ "watch": "babel src -d dist --copy-files --watch",
9
16
  "transpile": "babel src -d dist --copy-files",
10
17
  "build": "npm run transpile",
11
18
  "prepublishOnly": "npm run transpile"
@@ -25,6 +32,7 @@
25
32
  "devDependencies": {
26
33
  "@babel/cli": "^7.12.10",
27
34
  "@babel/core": "^7.12.10",
35
+ "@babel/plugin-transform-runtime": "^7.14.5",
28
36
  "@babel/preset-env": "^7.12.11",
29
37
  "@babel/preset-react": "^7.12.10",
30
38
  "babel-loader": "^8.2.2",
package/src/index.js CHANGED
@@ -3,10 +3,11 @@ const { generateQuery } = require("./utils.js");
3
3
 
4
4
  // Create script to init hCaptcha
5
5
  let onLoadListeners = [];
6
- let captchaScriptCreated = false;
6
+ let apiScriptRequested = false;
7
7
 
8
8
  // Generate hCaptcha API Script
9
- const CaptchaScript = (params={}) => {
9
+ const mountCaptchaScript = (params={}) => {
10
+ apiScriptRequested = true;
10
11
  // Create global onload callback
11
12
  window.hcaptchaOnLoad = () => {
12
13
  // Iterate over onload listeners, call each listener
@@ -47,9 +48,6 @@ class HCaptcha extends React.Component {
47
48
 
48
49
  const isApiReady = typeof hcaptcha !== 'undefined';
49
50
 
50
- if (!isApiReady)
51
- captchaScriptCreated = false;
52
-
53
51
  this.ref = React.createRef();
54
52
 
55
53
  this.state = {
@@ -61,15 +59,14 @@ class HCaptcha extends React.Component {
61
59
  }
62
60
 
63
61
  componentDidMount () { //Once captcha is mounted intialize hCaptcha - hCaptcha
64
- const { apihost, assethost, endpoint, host, imghost, languageOverride:hl, reCaptchaCompat, reportapi, sentry } = this.props;
62
+ const { apihost, assethost, endpoint, host, imghost, languageOverride:hl, reCaptchaCompat, reportapi, sentry, custom } = this.props;
65
63
  const { isApiReady } = this.state;
66
64
 
67
65
  if (!isApiReady) { //Check if hCaptcha has already been loaded, if not create script tag and wait to render captcha
68
66
 
69
- if (!captchaScriptCreated) {
67
+ if (!apiScriptRequested) {
70
68
  // Only create the script tag once, use a global variable to track
71
- captchaScriptCreated = true;
72
- CaptchaScript({
69
+ mountCaptchaScript({
73
70
  apihost,
74
71
  assethost,
75
72
  endpoint,
@@ -78,7 +75,8 @@ class HCaptcha extends React.Component {
78
75
  imghost,
79
76
  recaptchacompat: reCaptchaCompat === false? "off" : null,
80
77
  reportapi,
81
- sentry
78
+ sentry,
79
+ custom
82
80
  });
83
81
  }
84
82
 
@@ -129,9 +127,9 @@ class HCaptcha extends React.Component {
129
127
  const captchaId = hcaptcha.render(this.ref.current,
130
128
  {
131
129
  ...this.props,
132
- "error-callback" : this.handleError,
133
- "expired-callback": this.handleExpire,
134
- "callback" : this.handleSubmit
130
+ "error-callback" : this.handleError,
131
+ "expired-callback" : this.handleExpire,
132
+ "callback" : this.handleSubmit,
135
133
  });
136
134
 
137
135
  this.setState({ isRemoved: false, captchaId });
@@ -158,6 +156,11 @@ class HCaptcha extends React.Component {
158
156
 
159
157
  handleOnLoad () {
160
158
  this.setState({ isApiReady: true }, () => {
159
+ // trigger onLoad if it exists
160
+ const { onLoad } = this.props;
161
+ if (onLoad) onLoad();
162
+
163
+ // render captcha
161
164
  this.renderCaptcha();
162
165
  });
163
166
  }
@@ -193,12 +196,16 @@ class HCaptcha extends React.Component {
193
196
  if (onError) onError(event);
194
197
  }
195
198
 
196
- execute () {
199
+ execute (opts = null) {
197
200
  const { isApiReady, isRemoved, captchaId } = this.state;
198
201
 
199
- if (!isApiReady || isRemoved) return
202
+ if (!isApiReady || isRemoved) return;
203
+
204
+ if (opts && typeof opts !== "object") {
205
+ opts = null;
206
+ }
200
207
 
201
- hcaptcha.execute(captchaId)
208
+ return hcaptcha.execute(captchaId, opts);
202
209
  }
203
210
 
204
211
  render () {
@@ -0,0 +1,44 @@
1
+ // Type definitions for @hcaptcha/react-hcaptcha 0.1
2
+ // Project: https://github.com/hCaptcha/react-hcaptcha
3
+ // Definitions by: Matt Sutkowski <https://github.com/msutkowski>
4
+ // Original Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
5
+ // TypeScript Version: 2.8
6
+
7
+ import * as React from "react";
8
+
9
+ interface HCaptchaState {
10
+ isApiReady: boolean;
11
+ isRemoved: boolean;
12
+ elementId: string;
13
+ captchaId: string;
14
+ }
15
+
16
+ interface HCaptchaProps {
17
+ onExpire?: () => any;
18
+ onError?: (event: string) => any;
19
+ onVerify?: (token: string) => any;
20
+ onLoad?: () => any;
21
+ languageOverride?: string;
22
+ sitekey: string;
23
+ size?: "normal" | "compact" | "invisible";
24
+ theme?: "light" | "dark";
25
+ tabIndex?: number;
26
+ id?: string;
27
+ reCaptchaCompat?: boolean;
28
+ }
29
+
30
+ interface ExecuteResponse {
31
+ response: string;
32
+ key: string;
33
+ }
34
+
35
+ declare class HCaptcha extends React.Component<HCaptchaProps, HCaptchaState> {
36
+ resetCaptcha(): void;
37
+ renderCaptcha(): void;
38
+ removeCaptcha(): void;
39
+ execute(opts: { async: true }): Promise<ExecuteResponse>
40
+ execute(opts?: { async: false }): void;
41
+ execute(opts?: { async: boolean }): Promise<ExecuteResponse> | void;
42
+ }
43
+
44
+ export = HCaptcha;
package/.babelrc DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "presets": [
3
- "@babel/env",
4
- "@babel/react"
5
- ]
6
- }
package/.gitattributes DELETED
@@ -1 +0,0 @@
1
- * text=auto
@@ -1,12 +0,0 @@
1
- name: CI
2
- on: push
3
- jobs:
4
- build:
5
- name: Build & Test
6
- runs-on: ubuntu-latest
7
- steps:
8
- - name: Checkout code
9
- uses: actions/checkout@v2
10
- - run: npm ci
11
- - run: npm run transpile
12
- - run: npm run test
@@ -1,71 +0,0 @@
1
- # For most projects, this workflow file will not need changing; you simply need
2
- # to commit it to your repository.
3
- #
4
- # You may wish to alter this file to override the set of languages analyzed,
5
- # or to provide custom queries or build logic.
6
- name: "CodeQL"
7
-
8
- on:
9
- push:
10
- branches: [master]
11
- pull_request:
12
- # The branches below must be a subset of the branches above
13
- branches: [master]
14
- schedule:
15
- - cron: '0 20 * * 3'
16
-
17
- jobs:
18
- analyze:
19
- name: Analyze
20
- runs-on: ubuntu-latest
21
-
22
- strategy:
23
- fail-fast: false
24
- matrix:
25
- # Override automatic language detection by changing the below list
26
- # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
27
- language: ['javascript']
28
- # Learn more...
29
- # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
30
-
31
- steps:
32
- - name: Checkout repository
33
- uses: actions/checkout@v2
34
- with:
35
- # We must fetch at least the immediate parents so that if this is
36
- # a pull request then we can checkout the head.
37
- fetch-depth: 2
38
-
39
- # If this run was triggered by a pull request event, then checkout
40
- # the head of the pull request instead of the merge commit.
41
- - run: git checkout HEAD^2
42
- if: ${{ github.event_name == 'pull_request' }}
43
-
44
- # Initializes the CodeQL tools for scanning.
45
- - name: Initialize CodeQL
46
- uses: github/codeql-action/init@v1
47
- with:
48
- languages: ${{ matrix.language }}
49
- # If you wish to specify custom queries, you can do so here or in a config file.
50
- # By default, queries listed here will override any specified in a config file.
51
- # Prefix the list here with "+" to use these queries and those in the config file.
52
- # queries: ./path/to/local/query, your-org/your-repo/queries@main
53
-
54
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
55
- # If this step fails, then you should remove it and run the build manually (see below)
56
- - name: Autobuild
57
- uses: github/codeql-action/autobuild@v1
58
-
59
- # ℹ️ Command-line programs to run using the OS shell.
60
- # 📚 https://git.io/JvXDl
61
-
62
- # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
63
- # and modify them (or add more) to build your code if your project
64
- # uses a compiled language
65
-
66
- #- run: |
67
- # make bootstrap
68
- # make release
69
-
70
- - name: Perform CodeQL Analysis
71
- uses: github/codeql-action/analyze@v1
@@ -1,22 +0,0 @@
1
- name: Publish NPM
2
- on:
3
- release:
4
- types: [ created ]
5
- jobs:
6
- build:
7
- name: Build & Test & Publish
8
- runs-on: ubuntu-latest
9
- steps:
10
- - name: Checkout code
11
- uses: actions/checkout@v2
12
- # Setup .npmrc file to publish to npm
13
- - uses: actions/setup-node@v1
14
- with:
15
- node-version: '12.x'
16
- registry-url: 'https://registry.npmjs.org'
17
- - run: npm ci
18
- - run: npm run transpile
19
- - run: npm run test
20
- - run: npm publish
21
- env:
22
- NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
@@ -1,9 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>hCaptcha React Demo</title>
5
- </head>
6
- <body>
7
- <div id="app"></div>
8
- </body>
9
- </html>
@@ -1,89 +0,0 @@
1
- const React = require('react');
2
- const {render} = require('react-dom');
3
- const HCaptcha = require('../../dist/');
4
-
5
- class ReactDemo extends React.Component {
6
-
7
- constructor(props) {
8
- super(props);
9
-
10
- this.state = {isVerified: false};
11
- this.captcha = React.createRef();
12
-
13
- this.handleChange = this.handleChange.bind(this);
14
- this.handleReset = this.handleReset.bind(this);
15
- this.onVerifyCaptcha = this.onVerifyCaptcha.bind(this);
16
- // Leave languageOverride unset or null for browser autodetection.
17
- // To force a language, use the code: https://hcaptcha.com/docs/languages
18
- this.languageOverride = null; // "fr";
19
- }
20
-
21
- handleChange(event) {
22
- this.setState({isVerified: true});
23
- }
24
-
25
- onVerifyCaptcha (token) {
26
- console.log("Verified: " + token);
27
- this.setState({isVerified: true})
28
- }
29
-
30
- handleSubmit(event) {
31
- event.preventDefault()
32
- this.child.execute()
33
- }
34
-
35
- handleReset(event) {
36
- event.preventDefault()
37
- this.captcha.current.resetCaptcha()
38
- this.setState({isVerified: false})
39
- }
40
-
41
- render() {
42
- const { isVerified } = this.state;
43
-
44
- return (
45
- <div>
46
- <p>
47
- Set your sitekey and onVerify callback as props, and drop into your form. From here, we'll take care of the rest.
48
- </p>
49
- <div>
50
- <HCaptcha ref={this.captcha} onVerify={this.onVerifyCaptcha} languageOverride={this.languageOverride}
51
- sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
52
- theme="light"
53
- />
54
- </div>
55
-
56
- <div>
57
- <HCaptcha ref={this.captcha} onVerify={this.onVerifyCaptcha} languageOverride={this.languageOverride}
58
- sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
59
- theme="dark"
60
- />
61
- </div>
62
-
63
- <div>
64
- <HCaptcha ref={this.captcha} onVerify={this.onVerifyCaptcha} languageOverride={this.languageOverride}
65
- sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
66
- size="compact"
67
- theme="dark"
68
- />
69
- </div>
70
-
71
- {isVerified &&
72
- <div>
73
- <p>Open your console to see the Verified response.</p>
74
- <button onClick={this.handleReset}>Reset Captcha</button>
75
- </div>
76
- }
77
-
78
- </div>
79
- );
80
- }
81
- }
82
-
83
- render(
84
- <div>
85
- <h1>HCaptcha React Demo</h1>
86
- <ReactDemo/>
87
- </div>,
88
- document.getElementById('app')
89
- );
package/jest.config.js DELETED
@@ -1,15 +0,0 @@
1
- "use strict";
2
-
3
- // For a detailed explanation regarding each configuration property, visit:
4
- // https://jestjs.io/docs/en/configuration.html
5
-
6
- module.exports = {
7
- // Automatically clear mock calls and instances between every test
8
- clearMocks: true,
9
-
10
- // The glob patterns Jest uses to detect test files
11
- testMatch: ["**/?(*.)+(spec|test).js?(x)"],
12
-
13
- // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
14
- testPathIgnorePatterns: ["/node_modules/", "webpack.config.test.js"],
15
- };
@@ -1,19 +0,0 @@
1
- export const MOCK_WIDGET_ID = 'mock-widget-id';
2
- export const MOCK_TOKEN = 'mock-token';
3
- export const MOCK_EKEY = 'mock-ekey';
4
-
5
- /*global jest*/
6
-
7
- export function getMockedHcaptcha() {
8
- return {
9
- // eslint-disable-next-line no-unused-vars
10
- setData: jest.fn((id, data) => {}),
11
- // eslint-disable-next-line no-unused-vars
12
- render: jest.fn((container, opt) => MOCK_WIDGET_ID),
13
- getResponse: jest.fn(() => MOCK_TOKEN),
14
- getRespKey: jest.fn(() => MOCK_EKEY),
15
- reset: jest.fn(),
16
- execute: jest.fn(),
17
- remove: jest.fn(),
18
- };
19
- }
@@ -1,263 +0,0 @@
1
- import React from "react";
2
- import ReactDOM from "react-dom";
3
- import ReactTestUtils, { act } from "react-dom/test-utils";
4
- import HCaptcha from "../src/index";
5
- import {getMockedHcaptcha, MOCK_EKEY, MOCK_TOKEN, MOCK_WIDGET_ID} from "./hcaptcha.mock";
6
-
7
-
8
- const TEST_PROPS = {
9
- sitekey: "10000000-ffff-ffff-ffff-000000000001",
10
- theme: "light",
11
- size: "invisible",
12
- tabindex: 0,
13
- };
14
-
15
- describe("hCaptcha", () => {
16
- let instance;
17
- let mockFns;
18
-
19
- beforeEach(() => {
20
- mockFns = {
21
- onChange: jest.fn(),
22
- onVerify: jest.fn(),
23
- onError: jest.fn(),
24
- onExpire: jest.fn(),
25
- };
26
- window.hcaptcha = getMockedHcaptcha();
27
- instance = ReactTestUtils.renderIntoDocument(
28
- <HCaptcha
29
- sitekey={TEST_PROPS.sitekey}
30
- theme={TEST_PROPS.theme}
31
- size={TEST_PROPS.size}
32
- tabindex={TEST_PROPS.tabindex}
33
- onChange={mockFns.onChange}
34
- onVerify={mockFns.onVerify}
35
- onError={mockFns.onError}
36
- onExpire={mockFns.onExpire}
37
- />,
38
- );
39
- });
40
-
41
- it("renders into a div", () => {
42
- expect(ReactDOM.findDOMNode(instance).nodeName).toBe("DIV");
43
- });
44
-
45
- it("has functions", () => {
46
- expect(typeof instance.execute).toBe("function");
47
- expect(typeof instance.resetCaptcha).toBe("function");
48
- expect(instance.execute).toBeDefined();
49
- expect(instance.resetCaptcha).toBeDefined();
50
- });
51
-
52
- it("can execute", () => {
53
- expect(window.hcaptcha.execute.mock.calls.length).toBe(0);
54
- instance.execute();
55
- expect(window.hcaptcha.execute.mock.calls.length).toBe(1);
56
- expect(window.hcaptcha.execute.mock.calls[0][0]).toBe(MOCK_WIDGET_ID);
57
- });
58
-
59
- it("can reset", () => {
60
- expect(window.hcaptcha.reset.mock.calls.length).toBe(0);
61
- instance.resetCaptcha();
62
- expect(window.hcaptcha.reset.mock.calls.length).toBe(1);
63
- expect(window.hcaptcha.reset.mock.calls[0][0]).toBe(MOCK_WIDGET_ID);
64
- });
65
-
66
- it("can remove", () => {
67
- expect(window.hcaptcha.remove.mock.calls.length).toBe(0);
68
- instance.removeCaptcha();
69
- expect(window.hcaptcha.remove.mock.calls.length).toBe(1);
70
- expect(window.hcaptcha.remove.mock.calls[0][0]).toBe(MOCK_WIDGET_ID);
71
- });
72
-
73
- it("emits verify with token and eKey", () => {
74
- expect(mockFns.onVerify.mock.calls.length).toBe(0);
75
- instance.handleSubmit();
76
- expect(mockFns.onVerify.mock.calls.length).toBe(1);
77
- expect(mockFns.onVerify.mock.calls[0][0]).toBe(MOCK_TOKEN);
78
- expect(mockFns.onVerify.mock.calls[0][1]).toBe(MOCK_EKEY);
79
- });
80
-
81
- it("emits error and calls reset", () => {
82
- expect(mockFns.onError.mock.calls.length).toBe(0);
83
- const error = "invalid-input-response";
84
- instance.handleError(error);
85
- expect(mockFns.onError.mock.calls.length).toBe(1);
86
- expect(mockFns.onError.mock.calls[0][0]).toBe(error);
87
- expect(window.hcaptcha.reset.mock.calls.length).toBe(1);
88
- });
89
-
90
- it("emits expire and calls reset", () => {
91
- expect(mockFns.onExpire.mock.calls.length).toBe(0);
92
- instance.handleExpire();
93
- expect(mockFns.onExpire.mock.calls.length).toBe(1);
94
- expect(window.hcaptcha.reset.mock.calls.length).toBe(1);
95
- });
96
-
97
- it("el renders after api loads and a widget id is set", () => {
98
- expect(instance.state.captchaId).toBe(MOCK_WIDGET_ID);
99
- expect(window.hcaptcha.render.mock.calls.length).toBe(1);
100
- expect(window.hcaptcha.render.mock.calls[0][1]).toMatchObject({
101
- sitekey: TEST_PROPS.sitekey,
102
- theme: TEST_PROPS.theme,
103
- size: TEST_PROPS.size,
104
- tabindex: TEST_PROPS.tabindex
105
- });
106
- });
107
-
108
- it("should set id if id prop is passed", () => {
109
- instance = ReactTestUtils.renderIntoDocument(
110
- <HCaptcha
111
- sitekey={TEST_PROPS.sitekey}
112
- id="test-id-1"
113
- />,
114
- );
115
- const node = ReactDOM.findDOMNode(instance);
116
- expect(node.getAttribute("id")).toBe("test-id-1");
117
- });
118
-
119
- it("should not set id if no id prop is passed", () => {
120
- process.env.NODE_ENV = "development";
121
- instance = ReactTestUtils.renderIntoDocument(
122
- <HCaptcha
123
- sitekey={TEST_PROPS.sitekey}
124
- />,
125
- );
126
- const node = ReactDOM.findDOMNode(instance);
127
- expect(node.getAttribute("id")).toBe(null);
128
- });
129
-
130
- describe("Query parameter", () => {
131
-
132
- beforeEach(() => {
133
- // Setup hCaptcha as undefined to load script
134
- window.hcaptcha = undefined;
135
- });
136
-
137
- afterEach(() => {
138
- // Clean up created script tag
139
- document.querySelectorAll("head > script")
140
- .forEach(script => document.head.removeChild(script));
141
- });
142
-
143
- it("validate src without", () => {
144
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
145
- sitekey={TEST_PROPS.sitekey}
146
- />);
147
-
148
- const script = document.querySelector("head > script");
149
- expect(script.src).toEqual("https://hcaptcha.com/1/api.js?render=explicit&onload=hcaptchaOnLoad");
150
- });
151
-
152
- it("apihost should change script src, but not be added as query", () => {
153
- const ExpectHost = "https://test.com";
154
-
155
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
156
- apihost={ExpectHost}
157
- sitekey={TEST_PROPS.sitekey}
158
- />);
159
-
160
- const script = document.querySelector("head > script");
161
- expect(script.src).toContain(ExpectHost);
162
- expect(script.src).not.toContain(`apihost=${encodeURIComponent(ExpectHost)}`);
163
- });
164
-
165
- it("assethost should be found when prop is set", () => {
166
- const ExpectHost = "https://test.com";
167
-
168
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
169
- assethost={ExpectHost}
170
- sitekey={TEST_PROPS.sitekey}
171
- />);
172
-
173
- const script = document.querySelector("head > script");
174
- expect(script.src).toContain(`assethost=${encodeURIComponent(ExpectHost)}`);
175
- });
176
-
177
- it("endpoint should be found when prop is set", () => {
178
- const ExpectHost = "https://test.com";
179
-
180
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
181
- endpoint={ExpectHost}
182
- sitekey={TEST_PROPS.sitekey}
183
- />);
184
-
185
- const script = document.querySelector("head > script");
186
- expect(script.src).toContain(`endpoint=${encodeURIComponent(ExpectHost)}`);
187
- });
188
-
189
- it("imghost should be found when prop is set", () => {
190
- const ExpectHost = "https://test.com";
191
-
192
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
193
- imghost={ExpectHost}
194
- sitekey={TEST_PROPS.sitekey}
195
- />);
196
-
197
- const script = document.querySelector("head > script");
198
- expect(script.src).toContain(`imghost=${encodeURIComponent(ExpectHost)}`);
199
- });
200
-
201
- it("reportapi should be found when prop is set", () => {
202
- const ExpectHost = "https://test.com";
203
-
204
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
205
- reportapi={ExpectHost}
206
- sitekey={TEST_PROPS.sitekey}
207
- />);
208
-
209
- const script = document.querySelector("head > script");
210
- expect(script.src).toContain(`reportapi=${encodeURIComponent(ExpectHost)}`);
211
- });
212
-
213
- it("hl should be found when prop languageOverride is set", () => {
214
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
215
- languageOverride="fr"
216
- sitekey={TEST_PROPS.sitekey}
217
- />);
218
-
219
- const script = document.querySelector("head > script");
220
- expect(script.src).toContain("hl=fr");
221
- });
222
-
223
- it("reCaptchaCompat should be found when prop is set to false", () => {
224
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
225
- reCaptchaCompat={false}
226
- sitekey={TEST_PROPS.sitekey}
227
- />);
228
-
229
- const script = document.querySelector("head > script");
230
- expect(script.src).toContain("recaptchacompat=off");
231
- });
232
-
233
- it("reCaptchaCompat should not be found when prop is set to anything except false", () => {
234
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
235
- reCaptchaCompat={true}
236
- sitekey={TEST_PROPS.sitekey}
237
- />);
238
-
239
- const script = document.querySelector("head > script");
240
- expect(script.src).not.toContain("recaptchacompat");
241
- });
242
-
243
- it("sentry should be found when prop is set", () => {
244
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
245
- sentry={true}
246
- sitekey={TEST_PROPS.sitekey}
247
- />);
248
-
249
- const script = document.querySelector("head > script");
250
- expect(script.src).toContain("sentry=true");
251
- });
252
-
253
- it("host should be found when prop is set", () => {
254
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
255
- host="test.com"
256
- sitekey={TEST_PROPS.sitekey}
257
- />);
258
-
259
- const script = document.querySelector("head > script");
260
- expect(script.src).toContain("host=test.com");
261
- });
262
- });
263
- });
@@ -1,44 +0,0 @@
1
- import { generateQuery } from "../src/utils.js";
2
-
3
- describe("Encode query", () => {
4
-
5
- it("Property foo to equal bar as string foo=bar:", () => {
6
- const params = {
7
- foo: "bar"
8
- };
9
- expect(generateQuery(params)).toBe("foo=bar");
10
- });
11
-
12
- it("Spaces to be encoded with %20", () => {
13
- const params = {
14
- foo: "bar baz bah"
15
- };
16
- expect(generateQuery(params)).toBe("foo=bar%20baz%20bah");
17
- });
18
-
19
- it("Chain multiple parameters", () => {
20
- const params = {
21
- foo: "bar",
22
- baz: true
23
- };
24
- expect(generateQuery(params)).toBe("foo=bar&baz=true");
25
- });
26
-
27
- it("false should be a valid query value", () => {
28
- const params = {
29
- foo: false
30
- };
31
- expect(generateQuery(params)).toBe("foo=false");
32
- });
33
-
34
- it("Null, undefined, and empty string values should be removed", () => {
35
- const params = {
36
- foo: "",
37
- bar: null,
38
- baz: undefined,
39
- bah: true
40
- };
41
- expect(generateQuery(params)).toBe("bah=true");
42
- });
43
-
44
- });
package/webpack.config.js DELETED
@@ -1,42 +0,0 @@
1
- // NPM Modules
2
- const Webpack = require('webpack');
3
- const Path = require('path');
4
- const HtmlWebpackPlugin = require("html-webpack-plugin");
5
-
6
- // Webpack Plugins
7
- const htmlPlugin = new HtmlWebpackPlugin({
8
- template: Path.join(__dirname, "./examples/src/index.html"),
9
- filename: "./index.html"
10
- });
11
-
12
- module.exports = {
13
- entry: Path.join(__dirname, "./examples/src/index.js"),
14
-
15
- module: {
16
- rules: [
17
- {
18
- test: /\.(js|jsx)$/,
19
- exclude: /node_modules/,
20
- use: ['babel-loader']
21
- }
22
- ]
23
- },
24
-
25
- resolve: {
26
- extensions: ['*', '.js', '.jsx']
27
- },
28
-
29
- output: {
30
- path: __dirname + '/dist',
31
- publicPath: '/',
32
- filename: 'bundle.js'
33
- },
34
-
35
- plugins: [
36
- htmlPlugin
37
- ],
38
-
39
- devServer: {
40
- port: 9000
41
- }
42
- };