widget: add proper types (0.1.29)

This commit is contained in:
tiago
2025-09-23 17:18:31 +01:00
parent d6c9d40fbf
commit 8932eb927b
4 changed files with 187 additions and 5 deletions
+2
View File
@@ -65,6 +65,8 @@ widget.addEventListener("solve", function (e) {
Alternatively, you can use `onsolve=""` directly within the widget or wrap the widget in a `<form></form>` (where Cap will automatically submit the token alongside other form data. for this, it'll create a hidden field with name set to its `data-cap-hidden-field-name` attribute or `cap-token`).
You can learn how to use the widget in more detail (such as the invisible mode) in the [widget guide](./widget.md).
## Server-side
Cap is fully self-hosted, so you'll need to start a server exposing an API for Cap's methods running at the same URL as specified in the `data-cap-api-endpoint` attribute.
+26 -2
View File
@@ -4,7 +4,7 @@
>
> **Requirements:** All modern browsers should be supported, but the build script specifically targets the last 10 versions of Chrome, Firefox, Safari and Edge.
`@cap.js/widget` is Cap's client-side library. It includes the `cap-widget` web component, the invisible mode and the Captcha solver. First, add it to your client-side code:
`@cap.js/widget` is Cap's client-side library. It includes the `cap-widget` web component, the invisible mode and the CAPTCHA solver. First, add it to your client-side code:
::: code-group
@@ -24,6 +24,12 @@
:::
You can also import it if you're using a bundler:
```js
import Cap from '@cap.js/widget';
```
::: warning
We're using the latest version of the library here for simplicity, but you should optimally pin a specific version to avoid breaking changes in the future.
@@ -59,6 +65,19 @@ widget.addEventListener("solve", function (e) {
Alternatively, you can use `onsolve=""` directly within the widget or wrap the widget in a `<form></form>` (where Cap will automatically submit the token alongside other form data. for this, it'll create a hidden field with name set to its `data-cap-hidden-field-name` attribute or `cap-token`).
## Invisible mode
You can use `new Cap({ ... })` in your client-side JavaScript to create a new Cap instance and use the `solve()` method to solve the challenge. This is helpful for situations where you don't want the Cap widget to be visible but still want security, e.g. on a social media app when posting something.
```js
import Cap from '@cap.js/widget';
const cap = new Cap({
apiEndpoint: '/api/cap'
});
const token = await cap.solve();
```
## Supported events
The following custom events are supported:
@@ -94,7 +113,8 @@ You can override the default browser fetch implementation by setting `window.CAP
```js
window.CAP_CUSTOM_FETCH = function (url, options) {
// Custom fetch implementation
// … add your custom fetch implementation
return fetch(url, options);
};
```
@@ -133,3 +153,7 @@ cap-widget {
--cap-opacity-hover: 0.8;
}
```
## Types
Cap's widget is fully typed. You can find the type definitions in the `cap.d.ts` file.
+155
View File
@@ -0,0 +1,155 @@
declare global {
interface Window {
CAP_CUSTOM_FETCH?: typeof fetch;
CAP_CUSTOM_WASM_URL?: string;
CAP_CSS_NONCE?: string;
CAP_DONT_SKIP_REDEFINE?: boolean;
Cap: typeof Cap;
}
}
interface CapProgressEventDetail {
progress: number;
}
interface CapSolveEventDetail {
token: string;
}
interface CapErrorEventDetail {
isCap: boolean;
message: string;
}
interface CapProgressEvent extends CustomEvent {
detail: CapProgressEventDetail;
}
interface CapSolveEvent extends CustomEvent {
detail: CapSolveEventDetail;
}
interface CapErrorEvent extends CustomEvent {
detail: CapErrorEventDetail;
}
interface CapResetEvent extends CustomEvent {
detail: Record<string, never>;
}
interface SolveResult {
success: boolean;
token: string;
}
interface CapConfig {
apiEndpoint?: string;
"data-cap-api-endpoint"?: string;
"data-cap-worker-count"?: string;
"data-cap-hidden-field-name"?: string;
"data-cap-i18n-initial-state"?: string;
"data-cap-i18n-verifying-label"?: string;
"data-cap-i18n-solved-label"?: string;
"data-cap-i18n-error-label"?: string;
"data-cap-i18n-verify-aria-label"?: string;
"data-cap-i18n-verifying-aria-label"?: string;
"data-cap-i18n-verified-aria-label"?: string;
"data-cap-i18n-error-aria-label"?: string;
"data-cap-i18n-wasm-disabled"?: string;
onsolve?: string;
onprogress?: string;
onreset?: string;
onerror?: string;
}
interface CapWidget extends HTMLElement {
readonly token: string | null;
readonly tokenValue: string | null;
solve(): Promise<SolveResult>;
reset(): void;
setWorkersCount(workers: number): void;
addEventListener(
type: "progress",
listener: (event: CapProgressEvent) => void
): void;
addEventListener(
type: "solve",
listener: (event: CapSolveEvent) => void
): void;
addEventListener(
type: "error",
listener: (event: CapErrorEvent) => void
): void;
addEventListener(
type: "reset",
listener: (event: CapResetEvent) => void
): void;
addEventListener(type: string, listener: EventListener): void;
removeEventListener(
type: "progress",
listener: (event: CapProgressEvent) => void
): void;
removeEventListener(
type: "solve",
listener: (event: CapSolveEvent) => void
): void;
removeEventListener(
type: "error",
listener: (event: CapErrorEvent) => void
): void;
removeEventListener(
type: "reset",
listener: (event: CapResetEvent) => void
): void;
removeEventListener(type: string, listener: EventListener): void;
}
declare class Cap {
readonly widget: CapWidget;
readonly token: string | null;
constructor(config?: CapConfig, el?: CapWidget);
solve(): Promise<SolveResult>;
reset(): void;
addEventListener(
type: "progress",
listener: (event: CapProgressEvent) => void
): void;
addEventListener(
type: "solve",
listener: (event: CapSolveEvent) => void
): void;
addEventListener(
type: "error",
listener: (event: CapErrorEvent) => void
): void;
addEventListener(
type: "reset",
listener: (event: CapResetEvent) => void
): void;
addEventListener(type: string, listener: EventListener): void;
}
declare global {
interface HTMLElementTagNameMap {
"cap-widget": CapWidget;
}
}
export {
Cap,
type CapWidget,
type CapConfig,
type CapProgressEvent,
type CapSolveEvent,
type CapErrorEvent,
type CapResetEvent,
type SolveResult,
};
export default Cap;
+4 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@cap.js/widget",
"version": "0.1.28",
"version": "0.1.29",
"description": "Client-side widget for Cap, a lightweight, modern open-source CAPTCHA alternative designed using SHA-256 PoW.",
"keywords": [
"security",
@@ -49,7 +49,8 @@
"url": "git+https://github.com/tiagozip/cap.git"
},
"license": "Apache-2.0",
"author": "Tiago Rangel",
"author": "Tiago",
"type": "commonjs",
"main": "cap.min.js"
"main": "cap.min.js",
"types": "cap.d.ts"
}