@rozie-ui/captcha-react 0.1.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dan Krieger and Rozie.js contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # @rozie-ui/captcha-react
2
+
3
+ Idiomatic **react** `Captcha` — Cross-framework CAPTCHA / bot-protection widget wrapping Google reCAPTCHA v2, hCaptcha, and Cloudflare Turnstile. Compiled from one [Rozie](https://github.com/One-Learning-Community/rozie.js) source. This package is generated; do not edit `src/` by hand.
4
+
5
+ This package ships `Captcha` (the default export) alongside `RecaptchaV3` (named export).
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm i @rozie-ui/captcha-react
11
+ ```
12
+
13
+ Peer dependencies: `react + react-dom`.
14
+
15
+ ## Captcha
16
+
17
+ ### Usage
18
+
19
+ ```tsx
20
+ import { useState } from 'react';
21
+ import { Captcha } from '@rozie-ui/captcha-react';
22
+
23
+ export function Demo() {
24
+ const [token, setToken] = useState('');
25
+ return (
26
+ <Captcha
27
+ provider="recaptcha"
28
+ sitekey="your-site-key"
29
+ token={token}
30
+ onTokenChange={setToken}
31
+ onVerify={(e) => console.log('verified', e.token)}
32
+ />
33
+ );
34
+ }
35
+ ```
36
+
37
+ ### Props
38
+
39
+ | Name | Type | Default | Two-way (model) | Required |
40
+ | --- | --- | --- | :---: | :---: |
41
+ | `provider` | `String` | `"recaptcha"` | | |
42
+ | `sitekey` | `String` | `—` | | ✓ |
43
+ | `token` | `String` | `""` | ✓ | |
44
+ | `theme` | `String` | `"light"` | | |
45
+ | `size` | `String` | `"normal"` | | |
46
+ | `tabindex` | `Number` | `null` | | |
47
+ | `options` | `Object` | `{}` | | |
48
+
49
+ ### Events
50
+
51
+ | Event | Description |
52
+ | --- | --- |
53
+ | `verify` | Fired when the user completes the challenge. Payload `{ token, provider }`. |
54
+ | `expire` | Fired when the verified token expires. Payload `{ provider }`. |
55
+ | `error` | Fired on a challenge or script-load failure. Payload `{ provider, error? }`. |
56
+
57
+ ### Imperative handle
58
+
59
+ This component exposes imperative methods (declared once in the Rozie source via `$expose`). Grab a handle with the native ref mechanism and call them directly:
60
+
61
+ ```tsx
62
+ import { useRef } from 'react';
63
+ import { Captcha, type CaptchaHandle } from '@rozie-ui/captcha-react';
64
+
65
+ const handle = useRef<CaptchaHandle>(null);
66
+ // <Captcha ref={handle} provider="recaptcha" sitekey="your-site-key" />
67
+ // handle.current?.reset(); // clear + reset the widget
68
+ // handle.current?.execute(); // invisible / programmatic challenge
69
+ // handle.current?.getResponse(); // read the current token
70
+ ```
71
+
72
+ | Method | Description |
73
+ | --- | --- |
74
+ | `reset` | Reset the widget to its un-challenged state and clear the two-way `token`. |
75
+ | `execute` | Programmatically run the challenge — drives invisible widgets (`size="invisible"`). |
76
+ | `getResponse` | Return the current response token on demand (e.g. just before form submit). |
77
+
78
+ ## RecaptchaV3
79
+
80
+ ### Usage
81
+
82
+ ```tsx
83
+ import { useRef } from 'react';
84
+ import { RecaptchaV3, type RecaptchaV3Handle } from '@rozie-ui/captcha-react';
85
+
86
+ export function SignupForm() {
87
+ const captcha = useRef<RecaptchaV3Handle>(null);
88
+ const onSubmit = async (e: React.FormEvent) => {
89
+ e.preventDefault();
90
+ const token = await captcha.current?.execute('signup'); // fresh token for THIS action
91
+ await fetch('/signup', { method: 'POST', body: JSON.stringify({ token }) });
92
+ };
93
+ return (
94
+ <form onSubmit={onSubmit}>
95
+ {/* … fields … */}
96
+ <RecaptchaV3 ref={captcha} sitekey="your-site-key" action="signup" />
97
+ <button type="submit">Sign up</button>
98
+ </form>
99
+ );
100
+ }
101
+ ```
102
+
103
+ ### Props
104
+
105
+ | Name | Type | Default | Two-way (model) | Required |
106
+ | --- | --- | --- | :---: | :---: |
107
+ | `sitekey` | `String` | `—` | | ✓ |
108
+ | `action` | `String` | `"submit"` | | |
109
+ | `token` | `String` | `""` | ✓ | |
110
+ | `executeOnMount` | `Boolean` | `false` | | |
111
+
112
+ ### Events
113
+
114
+ | Event | Description |
115
+ | --- | --- |
116
+ | `error` | Fired on a load timeout, script error, or a rejected `execute()`. Payload `{ error? }`. |
117
+ | `verify` | Fired on a successful `execute()`. Payload `{ token, action }`. |
118
+
119
+ ### Imperative handle
120
+
121
+ This component exposes imperative methods (declared once in the Rozie source via `$expose`). Grab a handle with the native ref mechanism and call them directly:
122
+
123
+ ```tsx
124
+ import { useRef } from 'react';
125
+ import { RecaptchaV3, type RecaptchaV3Handle } from '@rozie-ui/captcha-react';
126
+
127
+ const handle = useRef<RecaptchaV3Handle>(null);
128
+ // <RecaptchaV3 ref={handle} sitekey="your-site-key" action="submit" />
129
+ // const token = await handle.current?.execute(); // uses the action prop
130
+ // const token = await handle.current?.execute('login'); // override for this call
131
+ ```
132
+
133
+ | Method | Description |
134
+ | --- | --- |
135
+ | `execute` | Run a v3 challenge for the optional `action` (defaults to the `action` prop) and resolve with a fresh token; also writes the two-way `token` and emits `@verify`. |
package/dist/index.cjs ADDED
@@ -0,0 +1,359 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ let react = require("react");
6
+ let _rozie_runtime_react = require("@rozie/runtime-react");
7
+ let react_jsx_runtime = require("react/jsx-runtime");
8
+ //#region src/internal/loadCaptchaApi.ts
9
+ /**
10
+ * Bridge Friendly Captcha's `createWidget` SDK (the `@friendlycaptcha/sdk`
11
+ * compat build, loaded from the CDN — NO npm peer dependency) onto `CaptchaApi`.
12
+ *
13
+ * FC has no explicit-`render`/widget-id model: `createWidget({ element, ... })`
14
+ * returns an event-emitter handle (`frc:widget.complete|expire|error`) with
15
+ * `reset()` / `start()` / `getResponse()` / `destroy()`. We treat that handle AS
16
+ * the opaque widget id the rest of the family already threads around. FC also
17
+ * has no `size` concept — `startMode` is the closest analog and rides through
18
+ * the `options` escape hatch (or a `startMode` config key if a consumer passes
19
+ * one directly).
20
+ */
21
+ const adaptFriendly = (g) => {
22
+ const fc = g;
23
+ return {
24
+ render(el, cfg) {
25
+ const h = fc.createWidget({
26
+ element: el,
27
+ sitekey: cfg.sitekey,
28
+ theme: cfg.theme,
29
+ startMode: cfg.startMode
30
+ });
31
+ h.addEventListener("frc:widget.complete", (e) => {
32
+ const cb = cfg.callback;
33
+ if (typeof cb === "function") cb(e.detail?.response ?? "");
34
+ });
35
+ h.addEventListener("frc:widget.expire", () => {
36
+ const cb = cfg["expired-callback"];
37
+ if (typeof cb === "function") cb();
38
+ });
39
+ h.addEventListener("frc:widget.error", () => {
40
+ const cb = cfg["error-callback"];
41
+ if (typeof cb === "function") cb();
42
+ });
43
+ return h;
44
+ },
45
+ reset: (id) => id.reset(),
46
+ execute: (id) => id.start(),
47
+ getResponse: (id) => id.getResponse(),
48
+ remove: (id) => id.destroy()
49
+ };
50
+ };
51
+ const CAPTCHA_PROVIDERS = {
52
+ recaptcha: {
53
+ src: "https://www.google.com/recaptcha/api.js?render=explicit",
54
+ global: "grecaptcha"
55
+ },
56
+ hcaptcha: {
57
+ src: "https://js.hcaptcha.com/1/api.js?render=explicit",
58
+ global: "hcaptcha"
59
+ },
60
+ turnstile: {
61
+ src: "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit",
62
+ global: "turnstile"
63
+ },
64
+ friendly: {
65
+ src: "https://cdn.jsdelivr.net/npm/@friendlycaptcha/sdk@1/site.compat.min.js",
66
+ global: "frcaptcha",
67
+ adapt: adaptFriendly
68
+ }
69
+ };
70
+ /**
71
+ * Load a provider's api.js ONCE across the whole document, shared by every
72
+ * `<Captcha>` instance via a `globalThis` singleton (a per-instance cache would
73
+ * re-inject per component). Resolves with the provider global once its
74
+ * `render()` is callable; rejects on an unknown provider, a script load error,
75
+ * or a `LOAD_TIMEOUT_MS` timeout. `providers` is injectable for tests.
76
+ */
77
+ function loadCaptchaApi(provider, providers = CAPTCHA_PROVIDERS) {
78
+ const cfg = providers[provider];
79
+ if (!cfg) return Promise.reject(/* @__PURE__ */ new Error("Unknown captcha provider: " + provider));
80
+ const root = globalThis;
81
+ const cache = root.__rozieCaptchaLoaders ||= {};
82
+ if (cache[provider]) return cache[provider];
83
+ const win = globalThis;
84
+ const ready = (g) => {
85
+ if (!g) return false;
86
+ const o = g;
87
+ return typeof o.render === "function" || typeof o.createWidget === "function";
88
+ };
89
+ const resolveApi = (g) => cfg.adapt ? cfg.adapt(g) : g;
90
+ const p = new Promise((resolve, reject) => {
91
+ if (ready(win[cfg.global])) {
92
+ resolve(resolveApi(win[cfg.global]));
93
+ return;
94
+ }
95
+ if (!document.querySelector("script[data-rozie-captcha=\"" + provider + "\"]")) {
96
+ const el = document.createElement("script");
97
+ el.src = cfg.src;
98
+ el.async = true;
99
+ el.defer = true;
100
+ el.setAttribute("data-rozie-captcha", provider);
101
+ el.addEventListener("error", () => reject(/* @__PURE__ */ new Error("Failed to load " + provider + " script")));
102
+ document.head.appendChild(el);
103
+ }
104
+ const started = Date.now();
105
+ const poll = setInterval(() => {
106
+ if (ready(win[cfg.global])) {
107
+ clearInterval(poll);
108
+ resolve(resolveApi(win[cfg.global]));
109
+ } else if (Date.now() - started > 2e4) {
110
+ clearInterval(poll);
111
+ reject(/* @__PURE__ */ new Error(provider + " script load timeout"));
112
+ }
113
+ }, 50);
114
+ });
115
+ cache[provider] = p;
116
+ return p;
117
+ }
118
+ //#endregion
119
+ //#region src/Captcha.tsx
120
+ const Captcha = (0, react.forwardRef)(function Captcha(_props, ref) {
121
+ const __defaultOptions = (0, react.useState)(() => ({}))[0];
122
+ const props = {
123
+ ..._props,
124
+ provider: _props.provider ?? "recaptcha",
125
+ theme: _props.theme ?? "light",
126
+ size: _props.size ?? "normal",
127
+ tabindex: _props.tabindex ?? null,
128
+ options: _props.options ?? __defaultOptions
129
+ };
130
+ const attrs = (() => {
131
+ const { provider, sitekey, token, theme, size, tabindex, options, defaultValue, onTokenChange, defaultToken, ...rest } = _props;
132
+ return rest;
133
+ })();
134
+ const disposed = (0, react.useRef)(false);
135
+ const api = (0, react.useRef)(null);
136
+ const widgetId = (0, react.useRef)(null);
137
+ const [token, setToken] = (0, _rozie_runtime_react.useControllableState)({
138
+ value: props.token,
139
+ defaultValue: props.defaultToken ?? "",
140
+ onValueChange: props.onTokenChange
141
+ });
142
+ const widgetEl = (0, react.useRef)(null);
143
+ const { onError: _rozieProp_onError, onExpire: _rozieProp_onExpire, onVerify: _rozieProp_onVerify } = props;
144
+ const buildConfig = (0, react.useCallback)(() => ({
145
+ sitekey: props.sitekey,
146
+ theme: props.theme,
147
+ size: props.size,
148
+ ...props.tabindex != null ? { tabindex: props.tabindex } : {},
149
+ callback: (response) => {
150
+ setToken(response);
151
+ _rozieProp_onVerify && _rozieProp_onVerify({
152
+ token: response,
153
+ provider: props.provider
154
+ });
155
+ },
156
+ "expired-callback": () => {
157
+ setToken("");
158
+ _rozieProp_onExpire && _rozieProp_onExpire({ provider: props.provider });
159
+ },
160
+ "error-callback": () => {
161
+ setToken("");
162
+ _rozieProp_onError && _rozieProp_onError({ provider: props.provider });
163
+ },
164
+ ...props.options
165
+ }), [
166
+ _rozieProp_onError,
167
+ _rozieProp_onExpire,
168
+ _rozieProp_onVerify,
169
+ props.options,
170
+ props.provider,
171
+ props.sitekey,
172
+ props.size,
173
+ props.tabindex,
174
+ props.theme,
175
+ setToken
176
+ ]);
177
+ function reset() {
178
+ if (widgetId.current != null && api.current && typeof api.current.reset === "function") api.current.reset(widgetId.current);
179
+ setToken("");
180
+ }
181
+ function execute() {
182
+ if (widgetId.current != null && api.current && typeof api.current.execute === "function") api.current.execute(widgetId.current);
183
+ }
184
+ function getResponse() {
185
+ return widgetId.current != null && api.current && typeof api.current.getResponse === "function" ? api.current.getResponse(widgetId.current) : "";
186
+ }
187
+ (0, react.useEffect)(() => {
188
+ disposed.current = false;
189
+ loadCaptchaApi(props.provider).then((a) => {
190
+ if (disposed.current) return;
191
+ api.current = a;
192
+ widgetId.current = api.current.render(widgetEl.current, buildConfig());
193
+ }).catch((err) => {
194
+ props.onError && props.onError({
195
+ provider: props.provider,
196
+ error: err
197
+ });
198
+ });
199
+ return () => {
200
+ disposed.current = true;
201
+ if (widgetId.current == null || !api.current) return;
202
+ if (typeof api.current.remove === "function") api.current.remove(widgetId.current);
203
+ else if (typeof api.current.reset === "function") api.current.reset(widgetId.current);
204
+ };
205
+ }, []);
206
+ const _rozieExposeRef = (0, react.useRef)({
207
+ reset,
208
+ execute,
209
+ getResponse
210
+ });
211
+ _rozieExposeRef.current = {
212
+ reset,
213
+ execute,
214
+ getResponse
215
+ };
216
+ (0, react.useImperativeHandle)(ref, () => ({
217
+ reset: (...args) => _rozieExposeRef.current.reset(...args),
218
+ execute: (...args) => _rozieExposeRef.current.execute(...args),
219
+ getResponse: (...args) => _rozieExposeRef.current.getResponse(...args)
220
+ }), []);
221
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
222
+ ref: widgetEl,
223
+ ...attrs,
224
+ className: (0, _rozie_runtime_react.clsx)("rozie-captcha", attrs.className),
225
+ "data-rozie-s-9c7749d4": ""
226
+ }) });
227
+ });
228
+ //#endregion
229
+ //#region src/internal/loadRecaptchaV3.ts
230
+ /** The v3 api.js base URL. The sitekey is appended (`render=SITEKEY`) per call. */
231
+ const RECAPTCHA_V3_SRC = "https://www.google.com/recaptcha/api.js?render=";
232
+ const getGrecaptcha = () => globalThis.grecaptcha;
233
+ /**
234
+ * Load reCAPTCHA v3's api.js ONCE per sitekey across the whole document, shared
235
+ * by every `<RecaptchaV3>` instance via a `globalThis` singleton keyed on the
236
+ * sitekey. Resolves with the `grecaptcha` global once `grecaptcha.ready(cb)` has
237
+ * fired; rejects on a script load error or a `LOAD_TIMEOUT_MS` timeout.
238
+ *
239
+ * `srcBase` is injectable for tests (pass `''` so happy-dom does not attempt a
240
+ * real network fetch — mirrors loadCaptchaApi's injectable `providers` seam).
241
+ */
242
+ function loadRecaptchaV3(sitekey, srcBase = RECAPTCHA_V3_SRC) {
243
+ const root = globalThis;
244
+ const cache = root.__rozieRecaptchaV3Loaders ||= {};
245
+ if (cache[sitekey]) return cache[sitekey];
246
+ const p = new Promise((resolve, reject) => {
247
+ let settled = false;
248
+ const ready = (g) => {
249
+ g.ready(() => {
250
+ if (settled) return;
251
+ settled = true;
252
+ resolve(g);
253
+ });
254
+ };
255
+ const present = getGrecaptcha();
256
+ if (present && typeof present.ready === "function") {
257
+ ready(present);
258
+ return;
259
+ }
260
+ if (!document.querySelector("script[data-rozie-recaptcha-v3=\"" + sitekey + "\"]")) {
261
+ const el = document.createElement("script");
262
+ el.src = srcBase + encodeURIComponent(sitekey);
263
+ el.async = true;
264
+ el.defer = true;
265
+ el.setAttribute("data-rozie-recaptcha-v3", sitekey);
266
+ el.addEventListener("error", () => {
267
+ if (settled) return;
268
+ settled = true;
269
+ reject(/* @__PURE__ */ new Error("Failed to load reCAPTCHA v3 script for sitekey: " + sitekey));
270
+ });
271
+ document.head.appendChild(el);
272
+ }
273
+ const started = Date.now();
274
+ const poll = setInterval(() => {
275
+ const g = getGrecaptcha();
276
+ if (g && typeof g.ready === "function") {
277
+ clearInterval(poll);
278
+ ready(g);
279
+ } else if (Date.now() - started > 2e4) {
280
+ clearInterval(poll);
281
+ if (settled) return;
282
+ settled = true;
283
+ reject(/* @__PURE__ */ new Error("reCAPTCHA v3 script load timeout for sitekey: " + sitekey));
284
+ }
285
+ }, 50);
286
+ });
287
+ cache[sitekey] = p;
288
+ return p;
289
+ }
290
+ /**
291
+ * Run a v3 challenge for `sitekey` + `action`, returning a fresh token.
292
+ * Delegates to `grecaptcha.execute(sitekey, { action })`. Call AFTER
293
+ * `loadRecaptchaV3(sitekey)` has resolved (the component threads that order).
294
+ */
295
+ function execute(sitekey, opts) {
296
+ const g = getGrecaptcha();
297
+ if (!g || typeof g.execute !== "function") return Promise.reject(/* @__PURE__ */ new Error("reCAPTCHA v3 not loaded for sitekey: " + sitekey));
298
+ return g.execute(sitekey, opts);
299
+ }
300
+ //#endregion
301
+ //#region src/RecaptchaV3.tsx
302
+ const RecaptchaV3 = (0, react.forwardRef)(function RecaptchaV3(_props, ref) {
303
+ const props = {
304
+ ..._props,
305
+ action: _props.action ?? "submit",
306
+ executeOnMount: _props.executeOnMount ?? false
307
+ };
308
+ const attrs = (() => {
309
+ const { sitekey, action, token, executeOnMount, defaultValue, onTokenChange, defaultToken, ...rest } = _props;
310
+ return rest;
311
+ })();
312
+ const disposed = (0, react.useRef)(false);
313
+ const [token, setToken] = (0, _rozie_runtime_react.useControllableState)({
314
+ value: props.token,
315
+ defaultValue: props.defaultToken ?? "",
316
+ onValueChange: props.onTokenChange
317
+ });
318
+ function execute$1(action = null) {
319
+ const a = action != null ? action : props.action;
320
+ return loadRecaptchaV3(props.sitekey).then(() => execute(props.sitekey, { action: a })).then((tok) => {
321
+ if (disposed.current) return tok;
322
+ setToken(tok);
323
+ props.onVerify && props.onVerify({
324
+ token: tok,
325
+ action: a
326
+ });
327
+ return tok;
328
+ }).catch((err) => {
329
+ if (!disposed.current) props.onError && props.onError({ error: err });
330
+ throw err;
331
+ });
332
+ }
333
+ (0, react.useEffect)(() => {
334
+ disposed.current = false;
335
+ loadRecaptchaV3(props.sitekey).then(() => {
336
+ if (disposed.current || !props.executeOnMount) return;
337
+ execute$1();
338
+ }).catch((err) => {
339
+ if (disposed.current) return;
340
+ props.onError && props.onError({ error: err });
341
+ });
342
+ return () => {
343
+ disposed.current = true;
344
+ };
345
+ }, []);
346
+ const _rozieExposeRef = (0, react.useRef)({ execute: execute$1 });
347
+ _rozieExposeRef.current = { execute: execute$1 };
348
+ (0, react.useImperativeHandle)(ref, () => ({ execute: (...args) => _rozieExposeRef.current.execute(...args) }), []);
349
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
350
+ style: { display: "none" },
351
+ ...attrs,
352
+ className: (0, _rozie_runtime_react.clsx)("rozie-recaptcha-v3", attrs.className),
353
+ "data-rozie-s-9148a0b0": ""
354
+ }) });
355
+ });
356
+ //#endregion
357
+ exports.Captcha = Captcha;
358
+ exports.RecaptchaV3 = RecaptchaV3;
359
+ exports.default = Captcha;
@@ -0,0 +1,41 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/Captcha.d.ts
4
+ interface CaptchaProps {
5
+ provider?: string;
6
+ sitekey: string;
7
+ token?: string;
8
+ defaultToken?: string;
9
+ onTokenChange?: (next: string) => void;
10
+ theme?: string;
11
+ size?: string;
12
+ tabindex?: (number) | null;
13
+ options?: Record<string, unknown>;
14
+ onVerify?: (...args: unknown[]) => void;
15
+ onExpire?: (...args: unknown[]) => void;
16
+ onError?: (...args: unknown[]) => void;
17
+ }
18
+ interface CaptchaHandle {
19
+ reset: (...args: any[]) => any;
20
+ execute: (...args: any[]) => any;
21
+ getResponse: (...args: any[]) => any;
22
+ }
23
+ declare const Captcha: React.ForwardRefExoticComponent<CaptchaProps & React.RefAttributes<CaptchaHandle>>;
24
+ //#endregion
25
+ //#region src/RecaptchaV3.d.ts
26
+ interface RecaptchaV3Props {
27
+ sitekey: string;
28
+ action?: string;
29
+ token?: string;
30
+ defaultToken?: string;
31
+ onTokenChange?: (next: string) => void;
32
+ executeOnMount?: boolean;
33
+ onError?: (...args: unknown[]) => void;
34
+ onVerify?: (...args: unknown[]) => void;
35
+ }
36
+ interface RecaptchaV3Handle {
37
+ execute: (...args: any[]) => any;
38
+ }
39
+ declare const RecaptchaV3: React.ForwardRefExoticComponent<RecaptchaV3Props & React.RefAttributes<RecaptchaV3Handle>>;
40
+ //#endregion
41
+ export { Captcha, Captcha as default, type CaptchaHandle, RecaptchaV3, type RecaptchaV3Handle };
@@ -0,0 +1,41 @@
1
+ import * as _$react from "react";
2
+
3
+ //#region src/Captcha.d.ts
4
+ interface CaptchaProps {
5
+ provider?: string;
6
+ sitekey: string;
7
+ token?: string;
8
+ defaultToken?: string;
9
+ onTokenChange?: (token: string) => void;
10
+ theme?: string;
11
+ size?: string;
12
+ tabindex?: (number) | null;
13
+ options?: Record<string, any>;
14
+ onVerify?: (...args: any[]) => void;
15
+ onExpire?: (...args: any[]) => void;
16
+ onError?: (...args: any[]) => void;
17
+ }
18
+ interface CaptchaHandle {
19
+ reset: (...args: any[]) => any;
20
+ execute: (...args: any[]) => any;
21
+ getResponse: (...args: any[]) => any;
22
+ }
23
+ declare const Captcha: _$react.ForwardRefExoticComponent<CaptchaProps & _$react.RefAttributes<CaptchaHandle>>;
24
+ //#endregion
25
+ //#region src/RecaptchaV3.d.ts
26
+ interface RecaptchaV3Props {
27
+ sitekey: string;
28
+ action?: string;
29
+ token?: string;
30
+ defaultToken?: string;
31
+ onTokenChange?: (token: string) => void;
32
+ executeOnMount?: boolean;
33
+ onError?: (...args: any[]) => void;
34
+ onVerify?: (...args: any[]) => void;
35
+ }
36
+ interface RecaptchaV3Handle {
37
+ execute: (...args: any[]) => any;
38
+ }
39
+ declare const RecaptchaV3: _$react.ForwardRefExoticComponent<RecaptchaV3Props & _$react.RefAttributes<RecaptchaV3Handle>>;
40
+ //#endregion
41
+ export { Captcha, Captcha as default, type CaptchaHandle, RecaptchaV3, type RecaptchaV3Handle };