solid-hcaptcha
Advanced tools
Comparing version 0.2.6 to 0.3.0
@@ -21,18 +21,17 @@ import { effect, setAttribute, template, use } from 'solid-js/web'; | ||
const _tmpl$ = /*#__PURE__*/template(`<div></div>`, 2); | ||
const _tmpl$ = /*#__PURE__*/template(`<div>`); | ||
/** The name of the function that will be triggered when hCaptcha is loaded. */ | ||
const HCAPTCHA_ONLOAD_FUNCTION_NAME = "__hCaptchaOnLoad__"; | ||
const HCaptcha = props => { | ||
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); | ||
const script_url = () => generateScriptUrl({ | ||
assethost: props.config?.assethost, | ||
endpoint: props.config?.endpoint, | ||
hl: props.config?.hl, | ||
host: props.config?.host, | ||
imghost: props.config?.imghost, | ||
recaptchacompat: props.config?.recaptchacompat === false ? "off" : null, | ||
reportapi: props.config?.reportapi, | ||
sentry: props.config?.sentry, | ||
custom: props.config?.custom | ||
}, HCAPTCHA_ONLOAD_FUNCTION_NAME, props.config?.apihost); | ||
@@ -54,3 +53,2 @@ /** Whether the hCaptcha API (in `window`) is ready. */ | ||
isRemoved: false, | ||
elementId: props.id, | ||
captchaId: null | ||
@@ -88,27 +86,18 @@ }); | ||
const resetCaptcha = () => { | ||
const { | ||
captchaId | ||
} = state; | ||
if (!isReady() || !captchaId) return; | ||
if (!isReady() || !state.captchaId) return; | ||
// Reset captcha state, removes stored token and unticks checkbox. | ||
hcaptcha.reset(captchaId); | ||
hcaptcha.reset(state.captchaId); | ||
}; | ||
const removeCaptcha = callback => { | ||
const { | ||
captchaId | ||
} = state; | ||
if (!isReady() || !captchaId) return; | ||
if (!isReady() || !state.captchaId) return; | ||
setState({ | ||
isRemoved: true | ||
}); | ||
hcaptcha.remove(captchaId); | ||
hcaptcha.remove(state.captchaId); | ||
callback && callback(); | ||
}; | ||
const executeSync = () => { | ||
const { | ||
captchaId | ||
} = state; | ||
if (!isReady() || !captchaId) return; | ||
return hcaptcha.execute(captchaId, { | ||
if (!isReady() || !state.captchaId) return; | ||
return hcaptcha.execute(state.captchaId, { | ||
async: false | ||
@@ -118,7 +107,4 @@ }); | ||
const execute = async () => { | ||
const { | ||
captchaId | ||
} = state; | ||
if (!isReady() || !captchaId) return; | ||
const response = await hcaptcha.execute(captchaId, { | ||
if (!isReady() || !state.captchaId) return; | ||
const response = await hcaptcha.execute(state.captchaId, { | ||
async: true | ||
@@ -129,21 +115,12 @@ }); | ||
const setData = data => { | ||
const { | ||
captchaId | ||
} = state; | ||
if (!isReady() || !captchaId) return; | ||
return hcaptcha.setData(captchaId, data); | ||
if (!isReady() || !state.captchaId) return; | ||
return hcaptcha.setData(state.captchaId, data); | ||
}; | ||
const getResponse = () => { | ||
const { | ||
captchaId | ||
} = state; | ||
if (!captchaId) return null; | ||
return hcaptcha.getResponse(captchaId); | ||
if (!state.captchaId) return null; | ||
return hcaptcha.getResponse(state.captchaId); | ||
}; | ||
const getRespKey = () => { | ||
const { | ||
captchaId | ||
} = state; | ||
if (!captchaId) return null; | ||
return hcaptcha.getRespKey(captchaId); | ||
if (!state.captchaId) return null; | ||
return hcaptcha.getRespKey(state.captchaId); | ||
}; | ||
@@ -170,8 +147,4 @@ | ||
window[HCAPTCHA_ONLOAD_FUNCTION_NAME] = () => undefined; | ||
renderCaptcha(() => { | ||
const { | ||
onLoad | ||
} = props; | ||
if (onLoad) onLoad(hcaptcha_functions); | ||
}); | ||
const onReady = () => props.onLoad?.(hcaptcha_functions); | ||
renderCaptcha(onReady); | ||
}; | ||
@@ -184,19 +157,12 @@ | ||
const handleSubmit = () => { | ||
const { | ||
isRemoved, | ||
captchaId | ||
} = state; | ||
if (typeof hcaptcha === "undefined" || isRemoved || !captchaId) return; | ||
const { | ||
onVerify | ||
} = props; | ||
if (!onVerify) return; | ||
if (typeof hcaptcha === "undefined" || state.isRemoved || !state.captchaId) return; | ||
if (!props.onVerify) return; | ||
// Get response token from hCaptcha widget. | ||
const token = hcaptcha.getResponse(captchaId); | ||
const token = hcaptcha.getResponse(state.captchaId); | ||
// Get current challenge session ID from hCaptcha widget. | ||
const ekey = hcaptcha.getRespKey(captchaId); | ||
const ekey = hcaptcha.getRespKey(state.captchaId); | ||
// Dispatch event to verify user response. | ||
onVerify(token, ekey); | ||
props.onVerify(token, ekey); | ||
}; | ||
@@ -206,13 +172,7 @@ | ||
const handleExpire = () => { | ||
const { | ||
onExpire | ||
} = props; | ||
const { | ||
captchaId | ||
} = state; | ||
if (!isReady() || !captchaId) return; | ||
if (!isReady() || !state.captchaId) return; | ||
// Reset captcha when running into error. | ||
hcaptcha.reset(captchaId); | ||
if (onExpire) onExpire(); | ||
hcaptcha.reset(state.captchaId); | ||
props.onExpire?.(); | ||
}; | ||
@@ -222,13 +182,7 @@ | ||
const handleError = event => { | ||
const { | ||
onError | ||
} = props; | ||
const { | ||
captchaId | ||
} = state; | ||
if (!isReady() || !captchaId) return; | ||
if (!isReady() || !state.captchaId) return; | ||
// Reset captcha when running into error. | ||
hcaptcha.reset(captchaId); | ||
if (onError) onError(event); | ||
hcaptcha.reset(state.captchaId); | ||
props.onError?.(event); | ||
}; | ||
@@ -238,4 +192,4 @@ | ||
const handleOpen = () => { | ||
if (!isReady() || !props.onOpen) return; | ||
props.onOpen(); | ||
if (!isReady()) return; | ||
props.onOpen?.(); | ||
}; | ||
@@ -245,4 +199,4 @@ | ||
const handleClose = () => { | ||
if (!isReady() || !props.onClose) return; | ||
props.onClose(); | ||
if (!isReady()) return; | ||
props.onClose?.(); | ||
}; | ||
@@ -252,4 +206,4 @@ | ||
const handleChallengeExpired = () => { | ||
if (!isReady() || !props.onChallengeExpired) return; | ||
props.onChallengeExpired(); | ||
if (!isReady()) return; | ||
props.onChallengeExpired?.(); | ||
}; | ||
@@ -261,7 +215,7 @@ | ||
/** Create the hCaptcha main load function. */ | ||
window[HCAPTCHA_ONLOAD_FUNCTION_NAME] = () => handleOnLoad(); | ||
window[HCAPTCHA_ONLOAD_FUNCTION_NAME] = handleOnLoad; | ||
/** Insert the script in the `head` element. */ | ||
createScriptLoader({ | ||
src: script_url | ||
src: script_url() | ||
}); | ||
@@ -278,10 +232,7 @@ } | ||
onCleanup(() => { | ||
const { | ||
captchaId | ||
} = state; | ||
if (!isReady() || !captchaId) return; | ||
if (!isReady() || !state.captchaId) return; | ||
// Reset any stored variables / timers when unmounting. | ||
hcaptcha.reset(captchaId); | ||
hcaptcha.remove(captchaId); | ||
hcaptcha.reset(state.captchaId); | ||
hcaptcha.remove(state.captchaId); | ||
@@ -298,6 +249,6 @@ /** | ||
return (() => { | ||
const _el$ = _tmpl$.cloneNode(true); | ||
const _el$ = _tmpl$(); | ||
const _ref$ = captcha_ref; | ||
typeof _ref$ === "function" ? use(_ref$, _el$) : captcha_ref = _el$; | ||
effect(() => setAttribute(_el$, "id", state.elementId)); | ||
effect(() => setAttribute(_el$, "id", props.id)); | ||
return _el$; | ||
@@ -304,0 +255,0 @@ })(); |
@@ -8,14 +8,13 @@ import { createScriptLoader } from "@solid-primitives/script-loader"; | ||
const HCaptcha = (props) => { | ||
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); | ||
const script_url = () => generateScriptUrl({ | ||
assethost: props.config?.assethost, | ||
endpoint: props.config?.endpoint, | ||
hl: props.config?.hl, | ||
host: props.config?.host, | ||
imghost: props.config?.imghost, | ||
recaptchacompat: props.config?.recaptchacompat === false ? "off" : null, | ||
reportapi: props.config?.reportapi, | ||
sentry: props.config?.sentry, | ||
custom: props.config?.custom | ||
}, HCAPTCHA_ONLOAD_FUNCTION_NAME, props.config?.apihost); | ||
/** Whether the hCaptcha API (in `window`) is ready. */ | ||
@@ -32,3 +31,2 @@ const isApiReady = () => typeof window.hcaptcha !== "undefined"; | ||
isRemoved: false, | ||
elementId: props.id, | ||
captchaId: null | ||
@@ -63,46 +61,39 @@ }); | ||
const resetCaptcha = () => { | ||
const { captchaId } = state; | ||
if (!isReady() || !captchaId) | ||
if (!isReady() || !state.captchaId) | ||
return; | ||
// Reset captcha state, removes stored token and unticks checkbox. | ||
hcaptcha.reset(captchaId); | ||
hcaptcha.reset(state.captchaId); | ||
}; | ||
const removeCaptcha = (callback) => { | ||
const { captchaId } = state; | ||
if (!isReady() || !captchaId) | ||
if (!isReady() || !state.captchaId) | ||
return; | ||
setState({ isRemoved: true }); | ||
hcaptcha.remove(captchaId); | ||
hcaptcha.remove(state.captchaId); | ||
callback && callback(); | ||
}; | ||
const executeSync = () => { | ||
const { captchaId } = state; | ||
if (!isReady() || !captchaId) | ||
if (!isReady() || !state.captchaId) | ||
return; | ||
return hcaptcha.execute(captchaId, { async: false }); | ||
return hcaptcha.execute(state.captchaId, { async: false }); | ||
}; | ||
const execute = async () => { | ||
const { captchaId } = state; | ||
if (!isReady() || !captchaId) | ||
if (!isReady() || !state.captchaId) | ||
return; | ||
const response = await hcaptcha.execute(captchaId, { async: true }); | ||
const response = await hcaptcha.execute(state.captchaId, { async: true }); | ||
return response; | ||
}; | ||
const setData = (data) => { | ||
const { captchaId } = state; | ||
if (!isReady() || !captchaId) | ||
if (!isReady() || !state.captchaId) | ||
return; | ||
return hcaptcha.setData(captchaId, data); | ||
return hcaptcha.setData(state.captchaId, data); | ||
}; | ||
const getResponse = () => { | ||
const { captchaId } = state; | ||
if (!captchaId) | ||
if (!state.captchaId) | ||
return null; | ||
return hcaptcha.getResponse(captchaId); | ||
return hcaptcha.getResponse(state.captchaId); | ||
}; | ||
const getRespKey = () => { | ||
const { captchaId } = state; | ||
if (!captchaId) | ||
if (!state.captchaId) | ||
return null; | ||
return hcaptcha.getRespKey(captchaId); | ||
return hcaptcha.getRespKey(state.captchaId); | ||
}; | ||
@@ -127,7 +118,4 @@ /** | ||
window[HCAPTCHA_ONLOAD_FUNCTION_NAME] = () => undefined; | ||
renderCaptcha(() => { | ||
const { onLoad } = props; | ||
if (onLoad) | ||
onLoad(hcaptcha_functions); | ||
}); | ||
const onReady = () => props.onLoad?.(hcaptcha_functions); | ||
renderCaptcha(onReady); | ||
}; | ||
@@ -139,54 +127,46 @@ /** | ||
const handleSubmit = () => { | ||
const { isRemoved, captchaId } = state; | ||
if (typeof hcaptcha === "undefined" || isRemoved || !captchaId) | ||
if (typeof hcaptcha === "undefined" || state.isRemoved || !state.captchaId) | ||
return; | ||
const { onVerify } = props; | ||
if (!onVerify) | ||
if (!props.onVerify) | ||
return; | ||
// Get response token from hCaptcha widget. | ||
const token = hcaptcha.getResponse(captchaId); | ||
const token = hcaptcha.getResponse(state.captchaId); | ||
// Get current challenge session ID from hCaptcha widget. | ||
const ekey = hcaptcha.getRespKey(captchaId); | ||
const ekey = hcaptcha.getRespKey(state.captchaId); | ||
// Dispatch event to verify user response. | ||
onVerify(token, ekey); | ||
props.onVerify(token, ekey); | ||
}; | ||
/** Handle expire with the `onExpire` prop. */ | ||
const handleExpire = () => { | ||
const { onExpire } = props; | ||
const { captchaId } = state; | ||
if (!isReady() || !captchaId) | ||
if (!isReady() || !state.captchaId) | ||
return; | ||
// Reset captcha when running into error. | ||
hcaptcha.reset(captchaId); | ||
if (onExpire) | ||
onExpire(); | ||
hcaptcha.reset(state.captchaId); | ||
props.onExpire?.(); | ||
}; | ||
/** Handle error with the `onError` prop. */ | ||
const handleError = (event) => { | ||
const { onError } = props; | ||
const { captchaId } = state; | ||
if (!isReady() || !captchaId) | ||
if (!isReady() || !state.captchaId) | ||
return; | ||
// Reset captcha when running into error. | ||
hcaptcha.reset(captchaId); | ||
if (onError) | ||
onError(event); | ||
hcaptcha.reset(state.captchaId); | ||
props.onError?.(event); | ||
}; | ||
/** Handle open with the `onOpen` prop. */ | ||
const handleOpen = () => { | ||
if (!isReady() || !props.onOpen) | ||
if (!isReady()) | ||
return; | ||
props.onOpen(); | ||
props.onOpen?.(); | ||
}; | ||
/** Handle close with the `onClose` prop. */ | ||
const handleClose = () => { | ||
if (!isReady() || !props.onClose) | ||
if (!isReady()) | ||
return; | ||
props.onClose(); | ||
props.onClose?.(); | ||
}; | ||
/** Handle the expired challenge with the `onChallengeExpired` prop. */ | ||
const handleChallengeExpired = () => { | ||
if (!isReady() || !props.onChallengeExpired) | ||
if (!isReady()) | ||
return; | ||
props.onChallengeExpired(); | ||
props.onChallengeExpired?.(); | ||
}; | ||
@@ -197,7 +177,5 @@ /** On mount, initialize and load the hCaptcha script. */ | ||
/** Create the hCaptcha main load function. */ | ||
window[HCAPTCHA_ONLOAD_FUNCTION_NAME] = () => handleOnLoad(); | ||
window[HCAPTCHA_ONLOAD_FUNCTION_NAME] = handleOnLoad; | ||
/** Insert the script in the `head` element. */ | ||
createScriptLoader({ | ||
src: script_url | ||
}); | ||
createScriptLoader({ src: script_url() }); | ||
} | ||
@@ -213,8 +191,7 @@ /** | ||
onCleanup(() => { | ||
const { captchaId } = state; | ||
if (!isReady() || !captchaId) | ||
if (!isReady() || !state.captchaId) | ||
return; | ||
// Reset any stored variables / timers when unmounting. | ||
hcaptcha.reset(captchaId); | ||
hcaptcha.remove(captchaId); | ||
hcaptcha.reset(state.captchaId); | ||
hcaptcha.remove(state.captchaId); | ||
/** | ||
@@ -229,4 +206,4 @@ * We need to remove also the hCaptcha API on cleanup | ||
}); | ||
return (<div ref={captcha_ref} id={state.elementId}/>); | ||
return (<div ref={captcha_ref} id={props.id}/>); | ||
}; | ||
export default HCaptcha; |
@@ -1,2 +0,2 @@ | ||
import type { Component } from "solid-js"; | ||
import { type Component } from "solid-js"; | ||
import type { HCaptchaProps } from "./types"; | ||
@@ -3,0 +3,0 @@ /** The name of the function that will be triggered when hCaptcha is loaded. */ |
@@ -5,4 +5,2 @@ /// <reference types="@hcaptcha/types" /> | ||
isRemoved: boolean; | ||
/** ID of the `div` element that contains the hCaptcha widget. */ | ||
elementId?: string; | ||
/** Captcha identifier given by hCaptcha. */ | ||
@@ -9,0 +7,0 @@ captchaId: string | null; |
{ | ||
"name": "solid-hcaptcha", | ||
"description": "hCaptcha Component Library for Solid.", | ||
"version": "0.2.6", | ||
"version": "0.3.0", | ||
"license": "MIT", | ||
@@ -41,3 +41,4 @@ "type": "module", | ||
"type": "git", | ||
"url": "git+https://github.com/Vexcited/solid-hcaptcha.git" | ||
"url": "https://github.com/Vexcited/solid-hcaptcha.git", | ||
"directory": "package" | ||
}, | ||
@@ -47,21 +48,22 @@ "bugs": { | ||
}, | ||
"homepage": "https://github.com/Vexcited/solid-hcaptcha", | ||
"homepage": "https://vexcited.github.io/solid-hcaptcha/", | ||
"devDependencies": { | ||
"@typescript-eslint/eslint-plugin": "^5.46.1", | ||
"@typescript-eslint/parser": "^5.46.1", | ||
"eslint": "^8.29.0", | ||
"release-it": "^15.5.1", | ||
"rimraf": "^3.0.2", | ||
"rollup": "^3.7.4", | ||
"@typescript-eslint/eslint-plugin": "^6.5.0", | ||
"@typescript-eslint/parser": "^6.5.0", | ||
"eslint": "^8.48.0", | ||
"eslint-plugin-solid": "^0.13.0", | ||
"release-it": "^16.1.5", | ||
"rimraf": "^5.0.1", | ||
"rollup": "^3.28.1", | ||
"rollup-preset-solid": "^2.0.1", | ||
"solid-js": "^1.6.5", | ||
"typescript": "^4.9.4" | ||
"solid-js": "^1.7.11", | ||
"typescript": "^5.2.2" | ||
}, | ||
"peerDependencies": { | ||
"solid-js": "^1.6.5" | ||
"solid-js": "^1.6.15 || ^1.7.11" | ||
}, | ||
"dependencies": { | ||
"@hcaptcha/types": "^1.0.3", | ||
"@solid-primitives/script-loader": "^1.1.2" | ||
"@solid-primitives/script-loader": "^2.0.2" | ||
} | ||
} |
@@ -53,3 +53,3 @@ # Solid hCaptcha Component Library | ||
export default App; | ||
``` | ||
``` | ||
@@ -97,3 +97,3 @@ ### Programmatic Usage | ||
export default App; | ||
``` | ||
``` | ||
@@ -137,3 +137,3 @@ ## References | ||
| `onExpire` | `-` | When the current token expires. | | ||
| `onLoad` | `hcaptcha: HCaptchaFunctions` | When the hCaptcha API loads. The hCaptcha instance is passed along. You can store them to use, later, [its methods](#methods-from-hcaptcha-instance-type-hcaptchafunctions). | | ||
| `onLoad` | `hcaptcha: HCaptchaFunctions` | When the hCaptcha API loads. The hCaptcha instance is passed along. You can store them to use, later, [its methods](#methods-from-hcaptcha-instance-hcaptchafunctions). | | ||
| `onOpen` | `-` | When the user display of a challenge starts. | | ||
@@ -163,6 +163,8 @@ | `onClose` | `-` | When the user dismisses a challenge. | | ||
1. #### Make sure you don't double-import the api.js script | ||
Importing the JS SDK twice can cause unpredictable behavior, so don't do a direct import separately if you are using solid-hcaptcha. | ||
### Make sure you don't double-import the `api.js` script | ||
2. #### Make sure you are using `recaptchacompat: false` if you have the reCAPTCHA JS loaded on the same page. | ||
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 (they recommend only running hCaptcha) then please disable their compatibility mode. | ||
Importing the JS SDK twice can cause unpredictable behavior, so don't do a direct import separately if you are using solid-hcaptcha. | ||
### Make sure you are using `recaptchacompat: false` if you have the reCAPTCHA JS loaded on the same page | ||
parallel (they recommend only running hCaptcha) then please disable their compatibility mode. |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
167
45610
10
571
+ Added@solid-primitives/script-loader@2.2.0(transitive)
- Removed@solid-primitives/script-loader@1.1.3(transitive)