Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

solid-hcaptcha

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

solid-hcaptcha - npm Package Compare versions

Comparing version 0.1.0 to 0.2.0

164

dist/esm/index.js
import { effect, setAttribute, template } from 'solid-js/web';
import { createSignal, onMount, onCleanup } from 'solid-js';
import { createScriptLoader } from '@solid-primitives/script-loader';
import { onMount, onCleanup } from 'solid-js';
import { createStore } from 'solid-js/store';
const generateQuery = params => {
const entries = Object.entries(params);
const values = entries.filter(([_key, value]) => value || value === false);
const queries = values.map(([key, value]) => {
if (!value) return;
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
});
const query = queries.join("&");
return query;
const generateScriptUrl = (params, onLoadFunctionName, apihost) => {
const domain = apihost || "https://js.hcaptcha.com";
const url = new URL(domain);
url.pathname = "/1/api.js";
for (const [key, value] of Object.entries(params)) {
if (!value) continue;
url.searchParams.set(encodeURIComponent(key), encodeURIComponent(value));
} // Tell hCaptcha to not automatically render the widget.
url.searchParams.set("render", "explicit");
url.searchParams.set("onload", onLoadFunctionName);
return url.toString();
};
const _tmpl$ = /*#__PURE__*/template(`<div></div>`, 2);
// Create script to init hCaptcha.
const [_onLoadListeners, setOnLoadListeners] = createSignal([]);
const [apiScriptRequested, setApiScriptRequested] = createSignal(false);
/** Generate hCaptcha API script. */
const mountCaptchaScript = (params = {}) => {
setApiScriptRequested(true); // Create global onload callback.
/** The name of the function that will be triggered when hCaptcha is loaded. */
const HCAPTCHA_ONLOAD_FUNCTION_NAME = "__hCaptchaOnLoad__";
window._hcaptchaOnLoad = () => {
// Iterate over onload listeners, call each listener.
setOnLoadListeners(listeners => listeners.filter(listener => {
listener();
return false;
}));
};
const domain = params.apihost || "https://js.hcaptcha.com";
delete params.apihost;
const script = document.createElement("script");
script.src = `${domain}/1/api.js?render=explicit&onload=_hcaptchaOnLoad`;
script.async = true;
const query = generateQuery(params);
script.src += query !== "" ? `&${query}` : "";
document.head.appendChild(script);
};
const HCaptcha = props => {
/** Reference of the div captcha element. */
let captcha_ref;
const [state, setState] = createStore({
isApiReady: false,
isRemoved: false,
elementId: props.id || "solid-hcaptcha-script",
captchaId: null
});
const config = props.config || {};
const script_url = generateScriptUrl({
assethost: config.assethost,
endpoint: config.endpoint,
hl: config.hl,
host: config.host,
imghost: config.imghost,
recaptchacompat: config.recaptchacompat === false ? "off" : null,
reportapi: config.reportapi,
sentry: config.sentry,
custom: config.custom
}, HCAPTCHA_ONLOAD_FUNCTION_NAME, config.apihost);
/** Whether the hCaptcha API (in `window`) is ready. */

@@ -60,52 +48,18 @@

const {
isApiReady,
isRemoved
} = state;
return isApiReady && !isRemoved;
return isApiReady() && !isRemoved;
};
/** Once component is mounted, intialize hCaptcha. */
/** Reference of the hCaptcha widget element. */
onMount(() => {
// Check if hCaptcha has already been loaded,
// if not create script tag and wait to render captcha.
if (!isApiReady()) {
// Only create the script tag once, use a global variable to track.
if (!apiScriptRequested()) {
const config = props.config || {};
mountCaptchaScript({
apihost: config.apihost,
assethost: config.assethost,
endpoint: config.endpoint,
hl: config.hl,
host: config.host,
imghost: config.imghost,
recaptchacompat: config.recaptchacompat === false ? "off" : null,
reportapi: config.reportapi,
sentry: config.sentry,
custom: config.custom
});
} // Add onLoad callback to global onLoad listeners.
setOnLoadListeners(listeners => [...listeners, handleOnLoad]);
} else renderCaptcha();
let captcha_ref;
const [state, setState] = createStore({
isRemoved: false,
elementId: props.id,
captchaId: null
});
/** On unmount, reset the hCaptcha widget. */
onCleanup(() => {
const {
captchaId
} = state;
if (!isReady() || !captchaId) return; // Reset any stored variables / timers when unmounting.
hcaptcha.reset(captchaId);
hcaptcha.remove(captchaId);
});
const renderCaptcha = onReady => {
const {
isApiReady
} = state;
if (!isApiReady || !captcha_ref) return;
if (!captcha_ref) return;
/** Parameters for the hCaptcha widget. */

@@ -224,6 +178,4 @@

const handleOnLoad = () => {
setState({
isApiReady: true
});
/** Render captcha and wait for captcha ID. */
/** Remove the function when it has been loaded. */
window[HCAPTCHA_ONLOAD_FUNCTION_NAME] = () => undefined;

@@ -234,4 +186,2 @@ renderCaptcha(() => {

} = props;
/** Trigger `onLoad` prop if it exists. */
if (onLoad) onLoad(hcaptcha_functions);

@@ -314,3 +264,37 @@ });

};
/** On mount, initialize and load the hCaptcha script. */
onMount(() => {
if (!isApiReady()) {
/** Create the hCaptcha main load function. */
window[HCAPTCHA_ONLOAD_FUNCTION_NAME] = () => handleOnLoad();
/** Insert the script in the `head` element. */
createScriptLoader({
src: script_url
});
} else handleOnLoad();
});
/** On unmount, reset and remove the hCaptcha widget. */
onCleanup(() => {
const {
captchaId
} = state;
if (!isReady() || !captchaId) return; // Reset any stored variables / timers when unmounting.
hcaptcha.reset(captchaId);
hcaptcha.remove(captchaId);
/**
* We need to remove also the hCaptcha API on cleanup
* because `script-loader` automatically removes the script
* also on cleanup.
*
* See here: <https://github.com/solidjs-community/solid-primitives/blob/main/packages/script-loader/src/index.ts>.
*/
window.hcaptcha = undefined;
});
return (() => {

@@ -317,0 +301,0 @@ const _el$ = _tmpl$.cloneNode(true);

@@ -1,36 +0,20 @@

import { onMount, onCleanup, createSignal } from "solid-js";
import { createScriptLoader } from "@solid-primitives/script-loader";
import { onCleanup, onMount } from "solid-js";
import { createStore } from "solid-js/store";
import { generateQuery } from "./utils";
// Create script to init hCaptcha.
const [_onLoadListeners, setOnLoadListeners] = createSignal([]);
const [apiScriptRequested, setApiScriptRequested] = createSignal(false);
/** Generate hCaptcha API script. */
const mountCaptchaScript = (params = {}) => {
setApiScriptRequested(true);
// Create global onload callback.
window._hcaptchaOnLoad = () => {
// Iterate over onload listeners, call each listener.
setOnLoadListeners(listeners => listeners.filter(listener => {
listener();
return false;
}));
};
const domain = params.apihost || "https://js.hcaptcha.com";
delete params.apihost;
const script = document.createElement("script");
script.src = `${domain}/1/api.js?render=explicit&onload=_hcaptchaOnLoad`;
script.async = true;
const query = generateQuery(params);
script.src += query !== "" ? `&${query}` : "";
document.head.appendChild(script);
};
import { generateScriptUrl } from "./utils";
/** The name of the function that will be triggered when hCaptcha is loaded. */
const HCAPTCHA_ONLOAD_FUNCTION_NAME = "__hCaptchaOnLoad__";
const HCaptcha = (props) => {
/** Reference of the div captcha element. */
let captcha_ref;
const [state, setState] = createStore({
isApiReady: false,
isRemoved: false,
elementId: props.id || "solid-hcaptcha-script",
captchaId: null
});
const config = props.config || {};
const script_url = generateScriptUrl({
assethost: config.assethost,
endpoint: config.endpoint,
hl: config.hl,
host: config.host,
imghost: config.imghost,
recaptchacompat: config.recaptchacompat === false ? "off" : null,
reportapi: config.reportapi,
sentry: config.sentry,
custom: config.custom
}, HCAPTCHA_ONLOAD_FUNCTION_NAME, config.apihost);
/** Whether the hCaptcha API (in `window`) is ready. */

@@ -40,44 +24,14 @@ const isApiReady = () => typeof window.hcaptcha !== "undefined";

const isReady = () => {
const { isApiReady, isRemoved } = state;
return isApiReady && !isRemoved;
const { isRemoved } = state;
return isApiReady() && !isRemoved;
};
/** Once component is mounted, intialize hCaptcha. */
onMount(() => {
// Check if hCaptcha has already been loaded,
// if not create script tag and wait to render captcha.
if (!isApiReady()) {
// Only create the script tag once, use a global variable to track.
if (!apiScriptRequested()) {
const config = props.config || {};
mountCaptchaScript({
apihost: config.apihost,
assethost: config.assethost,
endpoint: config.endpoint,
hl: config.hl,
host: config.host,
imghost: config.imghost,
recaptchacompat: config.recaptchacompat === false ? "off" : null,
reportapi: config.reportapi,
sentry: config.sentry,
custom: config.custom
});
}
// Add onLoad callback to global onLoad listeners.
setOnLoadListeners(listeners => [...listeners, handleOnLoad]);
}
else
renderCaptcha();
/** Reference of the hCaptcha widget element. */
let captcha_ref;
const [state, setState] = createStore({
isRemoved: false,
elementId: props.id,
captchaId: null
});
/** On unmount, reset the hCaptcha widget. */
onCleanup(() => {
const { captchaId } = state;
if (!isReady() || !captchaId)
return;
// Reset any stored variables / timers when unmounting.
hcaptcha.reset(captchaId);
hcaptcha.remove(captchaId);
});
const renderCaptcha = (onReady) => {
const { isApiReady } = state;
if (!isApiReady || !captcha_ref)
if (!captcha_ref)
return;

@@ -171,7 +125,6 @@ /** Parameters for the hCaptcha widget. */

const handleOnLoad = () => {
setState({ isApiReady: true });
/** Render captcha and wait for captcha ID. */
/** Remove the function when it has been loaded. */
window[HCAPTCHA_ONLOAD_FUNCTION_NAME] = () => undefined;
renderCaptcha(() => {
const { onLoad } = props;
/** Trigger `onLoad` prop if it exists. */
if (onLoad)

@@ -239,4 +192,34 @@ onLoad(hcaptcha_functions);

};
/** On mount, initialize and load the hCaptcha script. */
onMount(() => {
if (!isApiReady()) {
/** Create the hCaptcha main load function. */
window[HCAPTCHA_ONLOAD_FUNCTION_NAME] = () => handleOnLoad();
/** Insert the script in the `head` element. */
createScriptLoader({
src: script_url
});
}
else
handleOnLoad();
});
/** On unmount, reset and remove the hCaptcha widget. */
onCleanup(() => {
const { captchaId } = state;
if (!isReady() || !captchaId)
return;
// Reset any stored variables / timers when unmounting.
hcaptcha.reset(captchaId);
hcaptcha.remove(captchaId);
/**
* We need to remove also the hCaptcha API on cleanup
* because `script-loader` automatically removes the script
* also on cleanup.
*
* See here: <https://github.com/solidjs-community/solid-primitives/blob/main/packages/script-loader/src/index.ts>.
*/
window.hcaptcha = undefined;
});
return (<div ref={captcha_ref} id={state.elementId}/>);
};
export default HCaptcha;

@@ -1,11 +0,14 @@

export const generateQuery = (params) => {
const entries = Object.entries(params);
const values = entries.filter(([_key, value]) => value || value === false);
const queries = values.map(([key, value]) => {
export const generateScriptUrl = (params, onLoadFunctionName, apihost) => {
const domain = apihost || "https://js.hcaptcha.com";
const url = new URL(domain);
url.pathname = "/1/api.js";
for (const [key, value] of Object.entries(params)) {
if (!value)
return;
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
});
const query = queries.join("&");
return query;
continue;
url.searchParams.set(encodeURIComponent(key), encodeURIComponent(value));
}
// Tell hCaptcha to not automatically render the widget.
url.searchParams.set("render", "explicit");
url.searchParams.set("onload", onLoadFunctionName);
return url.toString();
};
import type { Component } from "solid-js";
import type { HCaptchaProps } from "./types";
/** The name of the function that will be triggered when hCaptcha is loaded. */
declare const HCAPTCHA_ONLOAD_FUNCTION_NAME = "__hCaptchaOnLoad__";
declare global {
interface Window {
/** Function called when the hCaptcha script is loaded. */
_hcaptchaOnLoad: () => void;
[HCAPTCHA_ONLOAD_FUNCTION_NAME]: () => void;
}

@@ -8,0 +9,0 @@ }

/// <reference types="@hcaptcha/types" />
export interface HCaptchaState {
/** Whether the captcha is ready or not. */
isApiReady: boolean;
/** Whether the captcha was removed or not. */
isRemoved: boolean;
/** ID of the `div` element that contains the hCaptcha widget. */
elementId: string;
elementId?: string;
/** Captcha identifier given by hCaptcha. */

@@ -44,3 +42,3 @@ captchaId: string | null;

*
* Defaults to `normal`.
* @default "normal".
*/

@@ -51,3 +49,3 @@ size?: "normal" | "compact" | "invisible";

*
* Defaults to `light`.
* @default "light".
*/

@@ -59,11 +57,9 @@ theme?: "light" | "dark";

*
* Defaults to 0.
* @default 0
*/
tabindex?: number;
/**
* Manually set the ID of the hCaptcha component.
* Set an ID to the hCaptcha widget.
* Make sure each hCaptcha component generated on a single
* page has its own unique ID when using this prop.
*
* Defaults to "solid-hcaptcha-script".
*/

@@ -70,0 +66,0 @@ id?: string;

@@ -1,4 +0,4 @@

export interface GenerateQueryParams {
export interface HCaptchaUrlParams {
[key: string]: string | boolean | number | undefined | null;
}
export declare const generateQuery: (params: GenerateQueryParams) => string;
export declare const generateScriptUrl: (params: HCaptchaUrlParams, onLoadFunctionName: string, apihost?: string | undefined) => string;
{
"name": "solid-hcaptcha",
"description": "Unofficial port of react-hcaptcha for Solid.",
"version": "0.1.0",
"version": "0.2.0",
"license": "MIT",

@@ -46,3 +46,6 @@ "source": "./src/index.tsx",

"solid-js": "^1.4.2"
},
"dependencies": {
"@solid-primitives/script-loader": "^1.1.0"
}
}
# Solid hCaptcha Component Library
> This is an unofficial port of [`react-hcaptcha`](https://github.com/hCaptcha/react-hcaptcha) for [Solid](https://www.solidjs.com).
> This is an unofficial port of [`@hcaptcha/react-hcaptcha`](https://github.com/hCaptcha/react-hcaptcha) for [Solid](https://www.solidjs.com).

@@ -13,7 +13,5 @@ ## Description

This package is in development ! Please come back later...
You can install this library via your favorite package manager.
<!-- You can install this library via your favorite package manager. -->
<!-- ```bash
```bash
# NPM

@@ -27,3 +25,3 @@ npm install solid-hcaptcha --save

pnpm add solid-hcaptcha
``` -->
```

@@ -33,10 +31,58 @@ ## Usage

> You can see multiple use cases on the [example website](https://vexcited.github.io/solid-hcaptcha).
<!-- ```typescript
### Basic Usage
```tsx
import HCaptcha from "solid-hcaptcha";
const App: Component = () => {
return (
<HCaptcha
sitekey="10000000-ffff-ffff-ffff-000000000001"
onVerify={token => console.log(token)}
/>
);
};
``` -->
export default App;
```
Please, come back later, it's coming very soon...
### Programmatic Usage
```tsx
import type { HCaptchaFunctions } from "solid-hcaptcha";
import HCaptcha from "solid-hcaptcha";
const App: Component = () => {
let hcaptcha: HCaptchaFunctions | undefined;
const submitCaptcha = async () => {
if (!hcaptcha) return; // Check if the widget has loaded.
// Execute the captcha and get the response.
const response = await hcaptcha.execute();
console.log(response);
}
return (
<div>
<HCaptcha
sitekey="10000000-ffff-ffff-ffff-000000000001"
onLoad={hcaptcha_instance => (hcaptcha = hcaptcha_instance)}
size="invisible"
/>
<button onClick={submitCaptcha}>
Open captcha
</button>
</div>
);
};
export default App;
```
<!-- ## API -->
## Development

@@ -43,0 +89,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc