@gahojin-inc/react-google-recaptcha 2026.1.0 → 2026.4.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.
@@ -0,0 +1,68 @@
1
+ import { JSX, PropsWithChildren } from "react";
2
+
3
+ //#region \0rolldown/runtime.js
4
+ //#endregion
5
+ //#region src/types.d.ts
6
+ type Theme = "light" | "dark";
7
+ type Size = "normal" | "compact" | "invisible";
8
+ type Badge = "bottomright" | "bottomleft" | "inline";
9
+ type Parameters = {
10
+ sitekey: string;
11
+ badge?: Badge;
12
+ size?: Size;
13
+ theme?: Theme;
14
+ callback?: (token: string) => void;
15
+ "error-callback"?: (error?: Error) => void;
16
+ };
17
+ type GoogleReCaptchaProviderProps = PropsWithChildren<{
18
+ readonly siteKey: string;
19
+ readonly language?: string | null;
20
+ readonly useRecaptchaNet?: boolean;
21
+ readonly useEnterprise?: boolean;
22
+ readonly container?: string | HTMLElement | null;
23
+ readonly badge?: Badge;
24
+ readonly theme?: Theme;
25
+ }>;
26
+ type Action = {
27
+ action: string;
28
+ };
29
+ type Grecaptcha = {
30
+ ready: (onReady: () => void) => void;
31
+ render: (container: string | HTMLElement, params: Parameters) => string;
32
+ execute: (widgetId: string, params?: Action) => PromiseLike<string | null>;
33
+ reset: (widgetId: string) => void;
34
+ };
35
+ type GoogleReCaptchaContextType = {
36
+ readonly isLoading: boolean;
37
+ readonly error: Error | null;
38
+ execute: (action?: string) => Promise<string>;
39
+ reset: () => void;
40
+ };
41
+ declare global {
42
+ var grecaptcha: Grecaptcha & {
43
+ enterprise: Grecaptcha;
44
+ };
45
+ }
46
+ declare namespace provider_d_exports {
47
+ export { GoogleReCaptchaProvider$1 as GoogleReCaptchaProvider };
48
+ }
49
+ declare const GoogleReCaptchaProvider$1: ({
50
+ siteKey,
51
+ language,
52
+ useRecaptchaNet,
53
+ useEnterprise,
54
+ container,
55
+ badge,
56
+ theme,
57
+ children
58
+ }: GoogleReCaptchaProviderProps) => JSX.Element;
59
+ //#endregion
60
+ //#region src/hooks.d.ts
61
+ declare const useGoogleRecaptcha: () => GoogleReCaptchaContextType;
62
+ //#endregion
63
+ //#region src/index.d.ts
64
+ declare const MOCK_TOKEN: string;
65
+ declare const GoogleReCaptchaProvider: (typeof provider_d_exports)["GoogleReCaptchaProvider"];
66
+ //#endregion
67
+ export { GoogleReCaptchaProvider, type GoogleReCaptchaProviderProps, MOCK_TOKEN, useGoogleRecaptcha };
68
+ //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,5 @@
1
1
  import { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
-
4
3
  //#region src/context.tsx
5
4
  const GoogleReCaptchaContext = createContext({
6
5
  isLoading: true,
@@ -8,7 +7,6 @@ const GoogleReCaptchaContext = createContext({
8
7
  execute: () => Promise.reject("useGoogleRecaptcha must be used within an GoogleReCaptchaProvider"),
9
8
  reset: () => []
10
9
  });
11
-
12
10
  //#endregion
13
11
  //#region src/mock_provider.tsx
14
12
  const MOCK_TOKEN$1 = "mock-JspVRfSqeamw4CKN3kc7nL_p_MTzWSeE";
@@ -24,7 +22,6 @@ const MockGoogleReCaptchaProvider = ({ container, children }) => {
24
22
  children: [children, container ? null : /* @__PURE__ */ jsx("div", { id: `${id}-container` })]
25
23
  });
26
24
  };
27
-
28
25
  //#endregion
29
26
  //#region src/utils.ts
30
27
  const getRecaptchaScriptSrc = (render, language, useRecaptchaNet, useEnterprise) => {
@@ -52,7 +49,6 @@ const removeRecaptchBadge = () => {
52
49
  const nodeBadge = document.querySelector(".grecaptcha-badge");
53
50
  if (nodeBadge?.parentNode) document.body.removeChild(nodeBadge.parentNode);
54
51
  };
55
-
56
52
  //#endregion
57
53
  //#region src/provider.tsx
58
54
  const GoogleReCaptchaProvider$1 = ({ siteKey, language, useRecaptchaNet, useEnterprise, container, badge, theme, children }) => {
@@ -159,18 +155,16 @@ const GoogleReCaptchaProvider$1 = ({ siteKey, language, useRecaptchaNet, useEnte
159
155
  children: [children, container ? null : /* @__PURE__ */ jsx("div", { id: `${id}-container` })]
160
156
  });
161
157
  };
162
-
163
158
  //#endregion
164
159
  //#region src/hooks.ts
165
160
  const useGoogleRecaptcha = () => {
166
161
  return useContext(GoogleReCaptchaContext);
167
162
  };
168
-
169
163
  //#endregion
170
164
  //#region src/index.ts
171
165
  const MOCK_TOKEN = MOCK_TOKEN$1;
172
166
  const GoogleReCaptchaProvider = import.meta.env?.MODE === "test" ? MockGoogleReCaptchaProvider : GoogleReCaptchaProvider$1;
173
-
174
167
  //#endregion
175
168
  export { GoogleReCaptchaProvider, MOCK_TOKEN, useGoogleRecaptcha };
176
- //# sourceMappingURL=index.mjs.map
169
+
170
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["MOCK_TOKEN","GoogleReCaptchaProvider","mockProvider.MOCK_TOKEN","mockProvider.MockGoogleReCaptchaProvider","provider.GoogleReCaptchaProvider"],"sources":["../src/context.tsx","../src/mock_provider.tsx","../src/utils.ts","../src/provider.tsx","../src/hooks.ts","../src/index.ts"],"sourcesContent":["import { type Context, createContext } from 'react'\nimport type { GoogleReCaptchaContextType } from './types'\n\nconst GoogleReCaptchaContext: Context<GoogleReCaptchaContextType> = createContext<GoogleReCaptchaContextType>({\n isLoading: true,\n error: null,\n execute: () => Promise.reject('useGoogleRecaptcha must be used within an GoogleReCaptchaProvider'),\n reset: () => [],\n})\n\nexport { GoogleReCaptchaContext }\n","import { type JSX, useId } from 'react'\nimport { GoogleReCaptchaContext } from './context.tsx'\nimport type { GoogleReCaptchaProviderProps } from './types.ts'\n\nconst MOCK_TOKEN: string = 'mock-JspVRfSqeamw4CKN3kc7nL_p_MTzWSeE'\n\nconst MockGoogleReCaptchaProvider = ({ container, children }: GoogleReCaptchaProviderProps): JSX.Element => {\n const id = useId()\n return (\n <GoogleReCaptchaContext.Provider value={{ isLoading: false, error: null, execute: () => Promise.resolve(MOCK_TOKEN), reset: () => {} }}>\n {children}\n {container ? null : <div id={`${id}-container`} />}\n </GoogleReCaptchaContext.Provider>\n )\n}\n\nexport { MOCK_TOKEN, MockGoogleReCaptchaProvider }\n","export const getRecaptchaScriptSrc = (\n render: string,\n language: string | null | undefined,\n useRecaptchaNet: boolean | undefined,\n useEnterprise: boolean | undefined,\n): string => {\n const hostName = useRecaptchaNet ? 'recaptcha.net' : 'google.com'\n const script = useEnterprise ? 'enterprise.js' : 'api.js'\n\n return `https://${hostName}/recaptcha/${script}?render=${render}${language ? `&hl=${language}` : ''}`\n}\n\nexport const injectScriptTag = (\n scriptId: string,\n language: string | null | undefined,\n useRecaptchaNet: boolean | undefined,\n useEnterprise: boolean | undefined,\n onLoad: () => void,\n): (() => void) => {\n const script = document.createElement('script')\n script.type = 'text/javascript'\n script.id = scriptId\n script.src = getRecaptchaScriptSrc('explicit', language, useRecaptchaNet, useEnterprise)\n script.async = true\n script.defer = true\n script.onload = onLoad\n\n document.head.appendChild(script)\n return () => {\n document.head.removeChild(script)\n }\n}\n\nexport const removeScriptTag = (): void => {\n removeRecaptchBadge()\n\n const script = document.querySelector('script[src^=\"https://www.gstatic.com/recaptcha/releases\"]')\n if (script) {\n script.remove()\n }\n}\n\nexport const removeRecaptchBadge = (): void => {\n const nodeBadge = document.querySelector('.grecaptcha-badge')\n if (nodeBadge?.parentNode) {\n document.body.removeChild(nodeBadge.parentNode)\n }\n}\n","import { type JSX, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'\nimport { GoogleReCaptchaContext } from './context.tsx'\nimport type { GoogleReCaptchaContextType, GoogleReCaptchaProviderProps, Grecaptcha } from './types.ts'\nimport { injectScriptTag, removeScriptTag } from './utils.ts'\n\ntype State = {\n isLoading: boolean\n error?: Error | null\n}\n\nconst GoogleReCaptchaProvider = ({\n siteKey,\n language,\n useRecaptchaNet,\n useEnterprise,\n container,\n badge,\n theme,\n children,\n}: GoogleReCaptchaProviderProps): JSX.Element => {\n const id = useId()\n const containerId = useMemo(() => (container ? container : `${id}-container`), [id, container])\n const [state, setState] = useState<State>({ isLoading: true })\n\n const widgetId = useRef<string>(siteKey)\n const grecaptcha = useRef<Grecaptcha>(null)\n const scriptLoaded = useRef(false)\n const successHandler = useRef<(token: string) => void>(null)\n const errorHandler = useRef<(error: Error | undefined) => void>(null)\n\n const handleSuccess = useCallback((token: string) => {\n if (successHandler.current) {\n successHandler.current?.(token)\n // トークンを再度取得できるよう、リセットする\n grecaptcha.current?.reset(widgetId.current)\n successHandler.current = null\n errorHandler.current = null\n }\n }, [])\n\n const handleError = useCallback((error: Error | undefined) => {\n if (errorHandler.current) {\n errorHandler.current?.(error)\n successHandler.current = null\n errorHandler.current = null\n }\n }, [])\n\n // ReCaptcha初期化\n const onLoad = useCallback(() => {\n const instance = window.grecaptcha?.enterprise ?? window.grecaptcha\n if (!instance) {\n setState({\n isLoading: false,\n error: new Error('reCaptcha is not available'),\n })\n return\n }\n\n // 二重にrender実行されることを抑止\n if (scriptLoaded.current) {\n return\n }\n scriptLoaded.current = true\n\n instance.ready(() => {\n widgetId.current = instance.render(containerId, {\n sitekey: siteKey,\n badge,\n theme,\n size: 'invisible',\n callback: handleSuccess,\n 'error-callback': handleError,\n })\n grecaptcha.current = instance\n setState({\n error: null,\n isLoading: false,\n })\n })\n }, [siteKey, containerId, badge, theme, handleSuccess, handleError])\n\n const reset = useCallback(() => {\n grecaptcha.current?.reset(widgetId.current)\n }, [])\n\n const execute = useCallback(\n (action?: string) => {\n const instance = grecaptcha.current\n if (instance?.execute) {\n const promise = new Promise<string>((resolve, reject) => {\n successHandler.current = resolve\n errorHandler.current = reject\n })\n return Promise.resolve(instance.execute(widgetId.current, action ? { action } : undefined)).then((token) => {\n if (token) {\n handleSuccess(token)\n }\n // token = nullの場合、v2動作\n return promise\n })\n }\n return Promise.reject('ReCaptcha is not available')\n },\n [handleSuccess],\n )\n\n // scriptタグを追加/削除する\n useEffect(() => {\n const removeScript = injectScriptTag(id, language, useRecaptchaNet, useEnterprise, onLoad)\n return () => {\n removeScript()\n removeScriptTag()\n scriptLoaded.current = false\n }\n }, [id, language, useRecaptchaNet, useEnterprise, onLoad])\n\n const value: GoogleReCaptchaContextType = useMemo(\n () => ({\n isLoading: state.isLoading,\n error: state.error ?? null,\n execute,\n reset,\n }),\n [state, execute, reset],\n )\n\n return (\n <GoogleReCaptchaContext.Provider value={value}>\n {children}\n {container ? null : <div id={`${id}-container`} />}\n </GoogleReCaptchaContext.Provider>\n )\n}\n\nexport { GoogleReCaptchaProvider }\n","import { useContext } from 'react'\nimport { GoogleReCaptchaContext } from './context'\nimport type { GoogleReCaptchaContextType } from './types'\n\nconst useGoogleRecaptcha = (): GoogleReCaptchaContextType => {\n return useContext(GoogleReCaptchaContext)\n}\n\nexport { useGoogleRecaptcha }\n","import * as mockProvider from './mock_provider'\nimport * as provider from './provider'\n\nexport const MOCK_TOKEN: string = mockProvider.MOCK_TOKEN\n\nexport const GoogleReCaptchaProvider: (typeof provider)['GoogleReCaptchaProvider'] =\n process.env?.NODE_ENV === 'test' || import.meta.env?.MODE === 'test' ? mockProvider.MockGoogleReCaptchaProvider : provider.GoogleReCaptchaProvider\n\nexport { useGoogleRecaptcha } from './hooks'\nexport type { GoogleReCaptchaProviderProps } from './types'\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gahojin-inc/react-google-recaptcha",
3
- "version": "2026.1.0",
3
+ "version": "2026.4.0",
4
4
  "description": "Hooks for Google ReCaptcha V3",
5
5
  "author": "GAHOJIN, Inc.",
6
6
  "license": "Apache-2.0",
@@ -25,18 +25,19 @@
25
25
  "access": "public",
26
26
  "provenance": true
27
27
  },
28
- "module": "./dist/index.mjs",
29
- "types": "./dist/index.d.mts",
28
+ "main": "./dist/index.js",
29
+ "module": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
30
31
  "exports": {
31
32
  "./package.json": "./package.json",
32
33
  ".": {
33
- "types": "./dist/index.d.mts",
34
- "import": "./dist/index.mjs"
34
+ "types": "./dist/index.d.ts",
35
+ "import": "./dist/index.js"
35
36
  }
36
37
  },
37
38
  "dependencies": {},
38
39
  "devDependencies": {
39
- "react": "19.2.3"
40
+ "react": "19.2.4"
40
41
  },
41
42
  "peerDependencies": {
42
43
  "react": "^18 || ^19"
@@ -1,4 +0,0 @@
1
- import { type Context } from "react";
2
- import type { GoogleReCaptchaContextType } from "./types.mjs";
3
- declare const GoogleReCaptchaContext: Context<GoogleReCaptchaContextType>;
4
- export { GoogleReCaptchaContext };
package/dist/hooks.d.mts DELETED
@@ -1,3 +0,0 @@
1
- import type { GoogleReCaptchaContextType } from "./types.mjs";
2
- declare const useGoogleRecaptcha: () => GoogleReCaptchaContextType;
3
- export { useGoogleRecaptcha };
package/dist/index.d.mts DELETED
@@ -1,5 +0,0 @@
1
- import * as provider from "./provider.mjs";
2
- export declare const MOCK_TOKEN: string;
3
- export declare const GoogleReCaptchaProvider: (typeof provider)["GoogleReCaptchaProvider"];
4
- export { useGoogleRecaptcha } from "./hooks.mjs";
5
- export type { GoogleReCaptchaProviderProps } from "./types.mjs";
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":["GoogleReCaptchaContext: Context<GoogleReCaptchaContextType>","MOCK_TOKEN: string","MOCK_TOKEN","GoogleReCaptchaProvider","value: GoogleReCaptchaContextType","MOCK_TOKEN: string","mockProvider.MOCK_TOKEN","GoogleReCaptchaProvider: (typeof provider)['GoogleReCaptchaProvider']","mockProvider.MockGoogleReCaptchaProvider","provider.GoogleReCaptchaProvider"],"sources":["../src/context.tsx","../src/mock_provider.tsx","../src/utils.ts","../src/provider.tsx","../src/hooks.ts","../src/index.ts"],"sourcesContent":["import { type Context, createContext } from 'react'\nimport type { GoogleReCaptchaContextType } from './types'\n\nconst GoogleReCaptchaContext: Context<GoogleReCaptchaContextType> = createContext<GoogleReCaptchaContextType>({\n isLoading: true,\n error: null,\n execute: () => Promise.reject('useGoogleRecaptcha must be used within an GoogleReCaptchaProvider'),\n reset: () => [],\n})\n\nexport { GoogleReCaptchaContext }\n","import { type JSX, useId } from 'react'\nimport { GoogleReCaptchaContext } from './context.tsx'\nimport type { GoogleReCaptchaProviderProps } from './types.ts'\n\nconst MOCK_TOKEN: string = 'mock-JspVRfSqeamw4CKN3kc7nL_p_MTzWSeE'\n\nconst MockGoogleReCaptchaProvider = ({ container, children }: GoogleReCaptchaProviderProps): JSX.Element => {\n const id = useId()\n return (\n <GoogleReCaptchaContext.Provider value={{ isLoading: false, error: null, execute: () => Promise.resolve(MOCK_TOKEN), reset: () => {} }}>\n {children}\n {container ? null : <div id={`${id}-container`} />}\n </GoogleReCaptchaContext.Provider>\n )\n}\n\nexport { MOCK_TOKEN, MockGoogleReCaptchaProvider }\n","export const getRecaptchaScriptSrc = (\n render: string,\n language: string | null | undefined,\n useRecaptchaNet: boolean | undefined,\n useEnterprise: boolean | undefined,\n): string => {\n const hostName = useRecaptchaNet ? 'recaptcha.net' : 'google.com'\n const script = useEnterprise ? 'enterprise.js' : 'api.js'\n\n return `https://${hostName}/recaptcha/${script}?render=${render}${language ? `&hl=${language}` : ''}`\n}\n\nexport const injectScriptTag = (\n scriptId: string,\n language: string | null | undefined,\n useRecaptchaNet: boolean | undefined,\n useEnterprise: boolean | undefined,\n onLoad: () => void,\n): (() => void) => {\n const script = document.createElement('script')\n script.type = 'text/javascript'\n script.id = scriptId\n script.src = getRecaptchaScriptSrc('explicit', language, useRecaptchaNet, useEnterprise)\n script.async = true\n script.defer = true\n script.onload = onLoad\n\n document.head.appendChild(script)\n return () => {\n document.head.removeChild(script)\n }\n}\n\nexport const removeScriptTag = (): void => {\n removeRecaptchBadge()\n\n const script = document.querySelector('script[src^=\"https://www.gstatic.com/recaptcha/releases\"]')\n if (script) {\n script.remove()\n }\n}\n\nexport const removeRecaptchBadge = (): void => {\n const nodeBadge = document.querySelector('.grecaptcha-badge')\n if (nodeBadge?.parentNode) {\n document.body.removeChild(nodeBadge.parentNode)\n }\n}\n","import { type JSX, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'\nimport { GoogleReCaptchaContext } from './context.tsx'\nimport type { GoogleReCaptchaContextType, GoogleReCaptchaProviderProps, Grecaptcha } from './types.ts'\nimport { injectScriptTag, removeScriptTag } from './utils.ts'\n\ntype State = {\n isLoading: boolean\n error?: Error | null\n}\n\nconst GoogleReCaptchaProvider = ({\n siteKey,\n language,\n useRecaptchaNet,\n useEnterprise,\n container,\n badge,\n theme,\n children,\n}: GoogleReCaptchaProviderProps): JSX.Element => {\n const id = useId()\n const containerId = useMemo(() => (container ? container : `${id}-container`), [id, container])\n const [state, setState] = useState<State>({ isLoading: true })\n\n const widgetId = useRef<string>(siteKey)\n const grecaptcha = useRef<Grecaptcha>(null)\n const scriptLoaded = useRef(false)\n const successHandler = useRef<(token: string) => void>(null)\n const errorHandler = useRef<(error: Error | undefined) => void>(null)\n\n const handleSuccess = useCallback((token: string) => {\n if (successHandler.current) {\n successHandler.current?.(token)\n // トークンを再度取得できるよう、リセットする\n grecaptcha.current?.reset(widgetId.current)\n successHandler.current = null\n errorHandler.current = null\n }\n }, [])\n\n const handleError = useCallback((error: Error | undefined) => {\n if (errorHandler.current) {\n errorHandler.current?.(error)\n successHandler.current = null\n errorHandler.current = null\n }\n }, [])\n\n // ReCaptcha初期化\n const onLoad = useCallback(() => {\n const instance = window.grecaptcha?.enterprise ?? window.grecaptcha\n if (!instance) {\n setState({\n isLoading: false,\n error: new Error('reCaptcha is not available'),\n })\n return\n }\n\n // 二重にrender実行されることを抑止\n if (scriptLoaded.current) {\n return\n }\n scriptLoaded.current = true\n\n instance.ready(() => {\n widgetId.current = instance.render(containerId, {\n sitekey: siteKey,\n badge,\n theme,\n size: 'invisible',\n callback: handleSuccess,\n 'error-callback': handleError,\n })\n grecaptcha.current = instance\n setState({\n error: null,\n isLoading: false,\n })\n })\n }, [siteKey, containerId, badge, theme, handleSuccess, handleError])\n\n const reset = useCallback(() => {\n grecaptcha.current?.reset(widgetId.current)\n }, [])\n\n const execute = useCallback(\n (action?: string) => {\n const instance = grecaptcha.current\n if (instance?.execute) {\n const promise = new Promise<string>((resolve, reject) => {\n successHandler.current = resolve\n errorHandler.current = reject\n })\n return Promise.resolve(instance.execute(widgetId.current, action ? { action } : undefined)).then((token) => {\n if (token) {\n handleSuccess(token)\n }\n // token = nullの場合、v2動作\n return promise\n })\n }\n return Promise.reject('ReCaptcha is not available')\n },\n [handleSuccess],\n )\n\n // scriptタグを追加/削除する\n useEffect(() => {\n const removeScript = injectScriptTag(id, language, useRecaptchaNet, useEnterprise, onLoad)\n return () => {\n removeScript()\n removeScriptTag()\n scriptLoaded.current = false\n }\n }, [id, language, useRecaptchaNet, useEnterprise, onLoad])\n\n const value: GoogleReCaptchaContextType = useMemo(\n () => ({\n isLoading: state.isLoading,\n error: state.error ?? null,\n execute,\n reset,\n }),\n [state, execute, reset],\n )\n\n return (\n <GoogleReCaptchaContext.Provider value={value}>\n {children}\n {container ? null : <div id={`${id}-container`} />}\n </GoogleReCaptchaContext.Provider>\n )\n}\n\nexport { GoogleReCaptchaProvider }\n","import { useContext } from 'react'\nimport { GoogleReCaptchaContext } from './context'\nimport type { GoogleReCaptchaContextType } from './types'\n\nconst useGoogleRecaptcha = (): GoogleReCaptchaContextType => {\n return useContext(GoogleReCaptchaContext)\n}\n\nexport { useGoogleRecaptcha }\n","import * as mockProvider from './mock_provider'\nimport * as provider from './provider'\n\nexport const MOCK_TOKEN: string = mockProvider.MOCK_TOKEN\n\nexport const GoogleReCaptchaProvider: (typeof provider)['GoogleReCaptchaProvider'] =\n process.env?.NODE_ENV === 'test' || import.meta.env?.MODE === 'test' ? mockProvider.MockGoogleReCaptchaProvider : provider.GoogleReCaptchaProvider\n\nexport { useGoogleRecaptcha } from './hooks'\nexport type { GoogleReCaptchaProviderProps } from './types'\n"],"mappings":"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"}
@@ -1,5 +0,0 @@
1
- import { type JSX } from "react";
2
- import type { GoogleReCaptchaProviderProps } from "./types.mjs";
3
- declare const MOCK_TOKEN: string;
4
- declare const MockGoogleReCaptchaProvider: ({ container, children }: GoogleReCaptchaProviderProps) => JSX.Element;
5
- export { MOCK_TOKEN, MockGoogleReCaptchaProvider };
@@ -1,4 +0,0 @@
1
- import { type JSX } from "react";
2
- import type { GoogleReCaptchaProviderProps } from "./types.mjs";
3
- declare const GoogleReCaptchaProvider: ({ siteKey, language, useRecaptchaNet, useEnterprise, container, badge, theme, children }: GoogleReCaptchaProviderProps) => JSX.Element;
4
- export { GoogleReCaptchaProvider };
package/dist/types.d.mts DELETED
@@ -1,42 +0,0 @@
1
- import type { PropsWithChildren } from "react";
2
- export type Theme = "light" | "dark";
3
- export type Type = "image" | "audio";
4
- export type Size = "normal" | "compact" | "invisible";
5
- export type Badge = "bottomright" | "bottomleft" | "inline";
6
- export type Parameters = {
7
- sitekey: string;
8
- badge?: Badge;
9
- size?: Size;
10
- theme?: Theme;
11
- callback?: (token: string) => void;
12
- "error-callback"?: (error?: Error) => void;
13
- };
14
- export type GoogleReCaptchaProviderProps = PropsWithChildren<{
15
- readonly siteKey: string;
16
- readonly language?: string | null;
17
- readonly useRecaptchaNet?: boolean;
18
- readonly useEnterprise?: boolean;
19
- readonly container?: string | HTMLElement | null;
20
- readonly badge?: Badge;
21
- readonly theme?: Theme;
22
- }>;
23
- export type Action = {
24
- action: string;
25
- };
26
- export type Grecaptcha = {
27
- ready: (onReady: () => void) => void;
28
- render: (container: string | HTMLElement, params: Parameters) => string;
29
- execute: (widgetId: string, params?: Action) => PromiseLike<string | null>;
30
- reset: (widgetId: string) => void;
31
- };
32
- export type GoogleReCaptchaContextType = {
33
- readonly isLoading: boolean;
34
- readonly error: Error | null;
35
- execute: (action?: string) => Promise<string>;
36
- reset: () => void;
37
- };
38
- declare global {
39
- var grecaptcha: Grecaptcha & {
40
- enterprise: Grecaptcha;
41
- };
42
- }
package/dist/utils.d.mts DELETED
@@ -1,4 +0,0 @@
1
- export declare const getRecaptchaScriptSrc: (render: string, language: string | null | undefined, useRecaptchaNet: boolean | undefined, useEnterprise: boolean | undefined) => string;
2
- export declare const injectScriptTag: (scriptId: string, language: string | null | undefined, useRecaptchaNet: boolean | undefined, useEnterprise: boolean | undefined, onLoad: () => void) => (() => void);
3
- export declare const removeScriptTag: () => void;
4
- export declare const removeRecaptchBadge: () => void;