@hcaptcha/react-hcaptcha 1.4.4 → 1.5.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 CHANGED
@@ -1,13 +1,19 @@
1
1
  # React hCaptcha Component Library
2
2
 
3
- ## Description
4
3
 
5
4
  hCaptcha Component Library for ReactJS.
6
5
 
7
- [hCaptcha](https://www.hcaptcha.com) is a drop-replacement for reCAPTCHA that protects user privacy, rewards websites, and helps companies get their data labeled.
6
+ [hCaptcha](https://www.hcaptcha.com) is a drop-replacement for reCAPTCHA that protects user privacy.
8
7
 
9
8
  Sign up at [hCaptcha](https://www.hcaptcha.com) to get your sitekey today. **You need a sitekey to use this library.**
10
9
 
10
+ *Also compatible with Preact.*
11
+
12
+ 1. [Installation](#installation)
13
+ 2. [References](#references)
14
+ 3. [Debugging](#debugging)
15
+ 4. [Contributing](#contributing)
16
+
11
17
  ## Installation
12
18
 
13
19
  You can install this library via npm with:
@@ -16,11 +22,11 @@ You can install this library via npm with:
16
22
  npm install @hcaptcha/react-hcaptcha --save
17
23
  ```
18
24
 
19
- ### Usage
25
+ ### Implementation
20
26
  The two requirements for usage are the `sitekey` [prop](#props) and a `parent component` such as a `<form />`. The component will automatically include and load the
21
27
  hCaptcha API library and append it to the parent component. This is designed for ease of use with the hCaptcha API!
22
28
 
23
- #### Basic Usage
29
+ #### Standard
24
30
 
25
31
  ```js
26
32
  import HCaptcha from '@hcaptcha/react-hcaptcha';
@@ -33,21 +39,7 @@ import HCaptcha from '@hcaptcha/react-hcaptcha';
33
39
  </FormComponent>
34
40
  ```
35
41
 
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:
37
-
38
- ```ts
39
- // utils/captcha.ts
40
- import HCaptcha from '@hcaptcha/react-hcaptcha';
41
- export default HCaptcha;
42
-
43
- // MyFormComponent.tsx
44
- import { default as RenamedCaptcha } from '../utils/captcha';
45
- <FormComponent>
46
- <RenamedCaptcha sitekey="your-sitekey" />
47
- </FormComponent>
48
- ```
49
-
50
- #### Programmatic Usage
42
+ #### Programmatic
51
43
  In the event you want to call the hCaptcha client API directly, you can do so by using the hook `useRef` and waiting for `onLoad` to be called. By waiting for `onLoad` the hCaptcha API will be ready and the hCaptcha client will have been setup. See the following example:
52
44
 
53
45
  ```js
@@ -86,7 +78,22 @@ export default function Form() {
86
78
  }
87
79
  ```
88
80
 
89
- #### Advanced usage
81
+ **Typescript Support** \
82
+ 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.
83
+
84
+ ```ts
85
+ // utils/captcha.ts
86
+ import HCaptcha from '@hcaptcha/react-hcaptcha';
87
+ export default HCaptcha;
88
+
89
+ // MyFormComponent.tsx
90
+ import { default as RenamedCaptcha } from '../utils/captcha';
91
+ <FormComponent>
92
+ <RenamedCaptcha sitekey="your-sitekey" />
93
+ </FormComponent>
94
+ ```
95
+
96
+ #### Advanced
90
97
 
91
98
  In most real-world implementations, you'll probably be using a form library such as [Formik](https://github.com/jaredpalmer/formik) or [React Hook Form](https://github.com/react-hook-form/react-hook-form).
92
99
 
@@ -111,8 +118,9 @@ const onLoad = () => {
111
118
  return <HCaptcha ref={captchaRef} onLoad={onLoad} sitekey={sitekey} {...props} />;
112
119
  ```
113
120
 
121
+ ### References
114
122
 
115
- ### Props
123
+ #### Props
116
124
 
117
125
  |Name|Values/Type|Required|Default|Description|
118
126
  |---|---|---|---|---|
@@ -132,7 +140,7 @@ return <HCaptcha ref={captchaRef} onLoad={onLoad} sitekey={sitekey} {...props} /
132
140
  |`sentry`|String|No|`-`|See enterprise docs.|
133
141
  |`custom`|Boolean|No|`-`|See enterprise docs.|
134
142
 
135
- ### Events
143
+ #### Events
136
144
 
137
145
  |Event|Params|Description|
138
146
  |---|---|---|
@@ -144,7 +152,7 @@ return <HCaptcha ref={captchaRef} onLoad={onLoad} sitekey={sitekey} {...props} /
144
152
  |`onClose`|-|When the user dismisses a challenge.|
145
153
  |`onChalExpired`|-|When the user display of a challenge times out with no answer.|
146
154
 
147
- ### Methods
155
+ #### Methods
148
156
 
149
157
  |Method|Description|
150
158
  |---|---|
@@ -155,7 +163,8 @@ return <HCaptcha ref={captchaRef} onLoad={onLoad} sitekey={sitekey} {...props} /
155
163
  |`setData()`|See enterprise docs.|
156
164
 
157
165
 
158
- **NOTE**: Make sure to reset the hCaptcha state when you submit your form by calling the method `.resetCaptcha` on your hCaptcha React Component! Passcodes are one-time use, so if your user submits the same passcode twice then it will be rejected by the server the second time.
166
+ > **Note** \
167
+ > Make sure to reset the hCaptcha state when you submit your form by calling the method `.resetCaptcha` on your hCaptcha React Component! Passcodes are one-time use, so if your user submits the same passcode twice then it will be rejected by the server the second time.
159
168
 
160
169
  Please refer to the demo for examples of basic usage and an invisible hCaptcha.
161
170
 
@@ -163,9 +172,24 @@ Alternatively, see [this sandbox code](https://codesandbox.io/s/react-hcaptchafo
163
172
 
164
173
  Please note that "invisible" simply means that no hCaptcha button will be rendered. Whether a challenge shows up will depend on the sitekey difficulty level. Note to hCaptcha Enterprise ([BotStop](https://www.botstop.com)) users: select "Passive" or "99.9% Passive" modes to get this No-CAPTCHA behavior.
165
174
 
166
- ---
167
175
 
168
- ### Note for maintainers
176
+
177
+
178
+ ### Debugging
179
+
180
+ 1. #### Invalid hCaptcha Id: <hcaptcha_id>
181
+ This issue generally occurs when the component is re-rendered causing the current `useRef` to become stale, meaning the `ref` being used is no longer available in the DOM.
182
+
183
+
184
+ 2. #### Make sure you don't double-import the api.js script
185
+ Importing the JS SDK twice can cause unpredictable behavior, so don't do a direct import separately if you are using react-hcaptcha.
186
+
187
+ 3. #### Make sure you are using `reCaptchaCompat=false` if you have the reCAPTCHA JS loaded on the same page.
188
+ The hCaptcha "compatibility mode" will interfere with reCAPTCHA, as it adds properties with the same name. If for any reason you are running both hCaptcha and reCAPTCHA in parallel (we recommend only running hCaptcha) then please disable our compatibility mode.
189
+
190
+
191
+ ---
192
+ ### Contributing
169
193
 
170
194
  #### Scripts
171
195
 
@@ -188,8 +212,9 @@ Please see: [Local Development Notes](https://docs.hcaptcha.com/#localdev).
188
212
 
189
213
  Summary:
190
214
 
191
- `sudo echo "127.0.0.1 fakelocal.com" >> /private/etc/hosts`
192
-
193
- `npm start -- --disable-host-check`
215
+ ```
216
+ sudo echo "127.0.0.1 fakelocal.com" >> /private/etc/hosts
217
+ npm start -- --disable-host-check
218
+ ```
194
219
 
195
220
  open [http://fakelocal.com:9000](http://fakelocal.com:9000) to start the example.
package/dist/esm/index.js CHANGED
@@ -29,7 +29,8 @@ var mountCaptchaScript = function mountCaptchaScript(params) {
29
29
  var script = document.createElement("script");
30
30
  script.id = SCRIPT_ID;
31
31
  script.src = domain + "/1/api.js?render=explicit&onload=" + HCAPTCHA_LOAD_FN_NAME;
32
- script.async = true;
32
+ script.async = params.loadAsync !== undefined ? params.loadAsync : true;
33
+ delete params.loadAsync;
33
34
 
34
35
  script.onerror = function (event) {
35
36
  return rejectFn('script-error');
@@ -146,7 +147,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
146
147
  reCaptchaCompat = _this$props.reCaptchaCompat,
147
148
  reportapi = _this$props.reportapi,
148
149
  sentry = _this$props.sentry,
149
- custom = _this$props.custom;
150
+ custom = _this$props.custom,
151
+ loadAsync = _this$props.loadAsync;
150
152
  var mountParams = {
151
153
  apihost: apihost,
152
154
  assethost: assethost,
@@ -157,7 +159,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
157
159
  recaptchacompat: reCaptchaCompat === false ? "off" : null,
158
160
  reportapi: reportapi,
159
161
  sentry: sentry,
160
- custom: custom
162
+ custom: custom,
163
+ loadAsync: loadAsync
161
164
  };
162
165
  mountCaptchaScript(mountParams).then(this.handleOnLoad)["catch"](this.handleError);
163
166
  this.apiScriptRequested = true;
package/dist/index.js CHANGED
@@ -56,7 +56,8 @@ var mountCaptchaScript = function mountCaptchaScript() {
56
56
  var script = document.createElement("script");
57
57
  script.id = SCRIPT_ID;
58
58
  script.src = "".concat(domain, "/1/api.js?render=explicit&onload=").concat(HCAPTCHA_LOAD_FN_NAME);
59
- script.async = true;
59
+ script.async = params.loadAsync !== undefined ? params.loadAsync : true;
60
+ delete params.loadAsync;
60
61
 
61
62
  script.onerror = function (event) {
62
63
  return rejectFn('script-error');
@@ -180,7 +181,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
180
181
  reCaptchaCompat = _this$props.reCaptchaCompat,
181
182
  reportapi = _this$props.reportapi,
182
183
  sentry = _this$props.sentry,
183
- custom = _this$props.custom;
184
+ custom = _this$props.custom,
185
+ loadAsync = _this$props.loadAsync;
184
186
  var mountParams = {
185
187
  apihost: apihost,
186
188
  assethost: assethost,
@@ -191,7 +193,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
191
193
  recaptchacompat: reCaptchaCompat === false ? "off" : null,
192
194
  reportapi: reportapi,
193
195
  sentry: sentry,
194
- custom: custom
196
+ custom: custom,
197
+ loadAsync: loadAsync
195
198
  };
196
199
  mountCaptchaScript(mountParams).then(this.handleOnLoad)["catch"](this.handleError);
197
200
  this.apiScriptRequested = true;
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@hcaptcha/react-hcaptcha",
3
- "version": "1.4.4",
3
+ "version": "1.5.0",
4
4
  "types": "types/index.d.ts",
5
+ "type": "module",
5
6
  "main": "dist/index.js",
6
7
  "module": "dist/esm/index.js",
7
8
  "files": [
@@ -11,7 +12,7 @@
11
12
  ],
12
13
  "description": "A React library for hCaptcha",
13
14
  "scripts": {
14
- "start": "webpack-dev-server --config ./webpack.config.js --mode development",
15
+ "start": "webpack serve",
15
16
  "test": "jest",
16
17
  "watch": "babel src -d dist --copy-files --watch",
17
18
  "transpile": "babel src -d dist --copy-files",
@@ -37,23 +38,25 @@
37
38
  },
38
39
  "license": "MIT",
39
40
  "devDependencies": {
40
- "@babel/cli": "^7.12.10",
41
+ "@babel/cli": "^7.12.1",
41
42
  "@babel/core": "^7.12.10",
42
43
  "@babel/plugin-transform-runtime": "^7.14.5",
43
44
  "@babel/preset-env": "^7.12.11",
44
45
  "@babel/preset-react": "^7.12.10",
46
+ "@jest/globals": "^29.5.0",
45
47
  "@types/react": "^16.0.0",
46
48
  "babel-loader": "^8.2.2",
47
49
  "babel-plugin-add-module-exports": "^1.0.4",
48
50
  "cross-env": "^7.0.3",
49
- "html-webpack-plugin": "^3.2.0",
50
- "jest": "^26.6.3",
51
+ "html-webpack-plugin": "^5.5.0",
52
+ "jest": "^29.5.0",
53
+ "jest-environment-jsdom": "^29.5.0",
51
54
  "react": "^16.14.0",
52
55
  "react-dom": "^16.14.0",
53
56
  "rimraf": "^3.0.2",
54
- "webpack": "^4.44.2",
55
- "webpack-cli": "^3.3.12",
56
- "webpack-dev-server": "^3.11.0"
57
+ "webpack": "^5.76.3",
58
+ "webpack-cli": "^5.0.1",
59
+ "webpack-dev-server": "^4.13.1"
57
60
  },
58
61
  "dependencies": {
59
62
  "@babel/runtime": "^7.17.9"
package/src/index.js CHANGED
@@ -28,7 +28,10 @@ const mountCaptchaScript = (params={}) => {
28
28
  const script = document.createElement("script");
29
29
  script.id = SCRIPT_ID;
30
30
  script.src = `${domain}/1/api.js?render=explicit&onload=${HCAPTCHA_LOAD_FN_NAME}`;
31
- script.async = true;
31
+
32
+ script.async = params.loadAsync !== undefined? params.loadAsync : true;
33
+ delete params.loadAsync;
34
+
32
35
  script.onerror = (event) => rejectFn('script-error');
33
36
 
34
37
  const query = generateQuery(params);
@@ -139,7 +142,8 @@ class HCaptcha extends React.Component {
139
142
  reCaptchaCompat,
140
143
  reportapi,
141
144
  sentry,
142
- custom
145
+ custom,
146
+ loadAsync
143
147
  } = this.props;
144
148
  const mountParams = {
145
149
  apihost,
@@ -151,7 +155,8 @@ class HCaptcha extends React.Component {
151
155
  recaptchacompat: reCaptchaCompat === false? "off" : null,
152
156
  reportapi,
153
157
  sentry,
154
- custom
158
+ custom,
159
+ loadAsync
155
160
  };
156
161
 
157
162
  mountCaptchaScript(mountParams)
@@ -323,7 +328,7 @@ class HCaptcha extends React.Component {
323
328
 
324
329
  render () {
325
330
  const { elementId } = this.state;
326
- return <div ref={this.ref} id={elementId}></div>
331
+ return <div ref={this.ref} id={elementId}></div>;
327
332
  }
328
333
  }
329
334
 
package/types/index.d.ts CHANGED
@@ -28,6 +28,7 @@ interface HCaptchaProps {
28
28
  tabIndex?: number;
29
29
  id?: string;
30
30
  reCaptchaCompat?: boolean;
31
+ loadAsync?: boolean;
31
32
  }
32
33
 
33
34
  interface ExecuteResponse {