@gahojin-inc/react-google-recaptcha 2026.3.0 → 2026.5.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.
- package/dist/{context.d.mts → context.d.ts} +2 -2
- package/dist/context.js +12 -0
- package/dist/context.js.map +1 -0
- package/dist/{hooks.d.mts → hooks.d.ts} +1 -1
- package/dist/hooks.js +10 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/{mock_provider.d.mts → mock_provider.d.ts} +2 -2
- package/dist/mock_provider.js +19 -0
- package/dist/mock_provider.js.map +1 -0
- package/dist/provider.d.ts +4 -0
- package/dist/provider.js +113 -0
- package/dist/provider.js.map +1 -0
- package/dist/types.d.ts +42 -0
- package/dist/utils.js +30 -0
- package/dist/utils.js.map +1 -0
- package/package.json +11 -8
- package/dist/index.d.mts +0 -5
- package/dist/index.mjs +0 -170
- package/dist/index.mjs.map +0 -1
- package/dist/provider.d.mts +0 -4
- package/dist/types.d.mts +0 -42
- /package/dist/{utils.d.mts → utils.d.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { Context } from 'react';
|
|
2
|
+
import { GoogleReCaptchaContextType } from './types.js';
|
|
3
3
|
declare const GoogleReCaptchaContext: Context<GoogleReCaptchaContextType>;
|
|
4
4
|
export { GoogleReCaptchaContext };
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
//#region src/context.tsx
|
|
3
|
+
var GoogleReCaptchaContext = createContext({
|
|
4
|
+
isLoading: true,
|
|
5
|
+
error: null,
|
|
6
|
+
execute: () => Promise.reject("useGoogleRecaptcha must be used within an GoogleReCaptchaProvider"),
|
|
7
|
+
reset: () => []
|
|
8
|
+
});
|
|
9
|
+
//#endregion
|
|
10
|
+
export { GoogleReCaptchaContext };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","names":[],"sources":["../src/context.tsx"],"sourcesContent":["import { type Context, createContext } from 'react'\nimport type { GoogleReCaptchaContextType } from './types.js'\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"],"mappings":";;AAGA,IAAM,yBAA8D,cAA0C;CAC5G,WAAW;CACX,OAAO;CACP,eAAe,QAAQ,OAAO,oEAAoE;CAClG,aAAa,EAAE;CAChB,CAAC"}
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { GoogleReCaptchaContext } from "./context.js";
|
|
2
|
+
import { useContext } from "react";
|
|
3
|
+
//#region src/hooks.ts
|
|
4
|
+
var useGoogleRecaptcha = () => {
|
|
5
|
+
return useContext(GoogleReCaptchaContext);
|
|
6
|
+
};
|
|
7
|
+
//#endregion
|
|
8
|
+
export { useGoogleRecaptcha };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","names":[],"sources":["../src/hooks.ts"],"sourcesContent":["import { useContext } from 'react'\nimport { GoogleReCaptchaContext } from './context.js'\nimport type { GoogleReCaptchaContextType } from './types.js'\n\nconst useGoogleRecaptcha = (): GoogleReCaptchaContextType => {\n return useContext(GoogleReCaptchaContext)\n}\n\nexport { useGoogleRecaptcha }\n"],"mappings":";;;AAIA,IAAM,2BAAuD;AAC3D,QAAO,WAAW,uBAAuB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as provider from './provider.js';
|
|
2
|
+
export declare const MOCK_TOKEN: string;
|
|
3
|
+
export declare const GoogleReCaptchaProvider: (typeof provider)['GoogleReCaptchaProvider'];
|
|
4
|
+
export { useGoogleRecaptcha } from './hooks.js';
|
|
5
|
+
export type { GoogleReCaptchaProviderProps } from './types.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { MockGoogleReCaptchaProvider } from "./mock_provider.js";
|
|
2
|
+
import { GoogleReCaptchaProvider as GoogleReCaptchaProvider$1 } from "./provider.js";
|
|
3
|
+
import { useGoogleRecaptcha } from "./hooks.js";
|
|
4
|
+
//#region src/index.ts
|
|
5
|
+
var MOCK_TOKEN = "mock-JspVRfSqeamw4CKN3kc7nL_p_MTzWSeE";
|
|
6
|
+
var GoogleReCaptchaProvider = process.env.NODE_ENV === "test" || false ? MockGoogleReCaptchaProvider : GoogleReCaptchaProvider$1;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { GoogleReCaptchaProvider, MOCK_TOKEN, useGoogleRecaptcha };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import * as mockProvider from './mock_provider.js'\nimport * as provider from './provider.js'\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.js'\nexport type { GoogleReCaptchaProviderProps } from './types.js'\n"],"mappings":";;;;AAGA,IAAa,aAAqB;AAElC,IAAa,0BAAA,QAAA,IAAA,aACe,UAAU,QAAmC,8BAA2C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { JSX } from 'react';
|
|
2
|
+
import { GoogleReCaptchaProviderProps } from './types.js';
|
|
3
3
|
declare const MOCK_TOKEN: string;
|
|
4
4
|
declare const MockGoogleReCaptchaProvider: ({ container, children }: GoogleReCaptchaProviderProps) => JSX.Element;
|
|
5
5
|
export { MOCK_TOKEN, MockGoogleReCaptchaProvider };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { GoogleReCaptchaContext } from "./context.js";
|
|
2
|
+
import { useId } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var MockGoogleReCaptchaProvider = ({ container, children }) => {
|
|
5
|
+
const id = useId();
|
|
6
|
+
return jsxs(GoogleReCaptchaContext.Provider, {
|
|
7
|
+
value: {
|
|
8
|
+
isLoading: false,
|
|
9
|
+
error: null,
|
|
10
|
+
execute: () => Promise.resolve("mock-JspVRfSqeamw4CKN3kc7nL_p_MTzWSeE"),
|
|
11
|
+
reset: () => {}
|
|
12
|
+
},
|
|
13
|
+
children: [children, container ? null : jsx("div", { id: `${id}-container` })]
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
export { MockGoogleReCaptchaProvider };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=mock_provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock_provider.js","names":[],"sources":["../src/mock_provider.tsx"],"sourcesContent":["import { type JSX, useId } from 'react'\nimport { GoogleReCaptchaContext } from './context.js'\nimport type { GoogleReCaptchaProviderProps } from './types.js'\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"],"mappings":";;;AAMA,IAAM,+BAA+B,EAAE,WAAW,eAA0D;CAC1G,MAAM,KAAK,OAAO;AAClB,QACE,KAAC,uBAAuB,UAAxB;EAAiC,OAAO;GAAE,WAAW;GAAO,OAAO;GAAM,eAAe,QAAQ,QAAA,wCAAmB;GAAE,aAAa;GAAI;YAAtI,CACG,UACA,YAAY,OAAO,IAAC,OAAD,EAAK,IAAI,GAAG,GAAG,aAAe,CAAA,CAClB"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { JSX } from 'react';
|
|
2
|
+
import { GoogleReCaptchaProviderProps } from './types.js';
|
|
3
|
+
declare const GoogleReCaptchaProvider: ({ siteKey, language, useRecaptchaNet, useEnterprise, container, badge, theme, children, }: GoogleReCaptchaProviderProps) => JSX.Element;
|
|
4
|
+
export { GoogleReCaptchaProvider };
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { GoogleReCaptchaContext } from "./context.js";
|
|
2
|
+
import { injectScriptTag, removeScriptTag } from "./utils.js";
|
|
3
|
+
import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/provider.tsx
|
|
6
|
+
var GoogleReCaptchaProvider = ({ siteKey, language, useRecaptchaNet, useEnterprise, container, badge, theme, children }) => {
|
|
7
|
+
const id = useId();
|
|
8
|
+
const containerId = useMemo(() => container ? container : `${id}-container`, [id, container]);
|
|
9
|
+
const [state, setState] = useState({ isLoading: true });
|
|
10
|
+
const widgetId = useRef(siteKey);
|
|
11
|
+
const grecaptcha = useRef(null);
|
|
12
|
+
const scriptLoaded = useRef(false);
|
|
13
|
+
const successHandler = useRef(null);
|
|
14
|
+
const errorHandler = useRef(null);
|
|
15
|
+
const handleSuccess = useCallback((token) => {
|
|
16
|
+
if (successHandler.current) {
|
|
17
|
+
successHandler.current?.(token);
|
|
18
|
+
grecaptcha.current?.reset(widgetId.current);
|
|
19
|
+
successHandler.current = null;
|
|
20
|
+
errorHandler.current = null;
|
|
21
|
+
}
|
|
22
|
+
}, []);
|
|
23
|
+
const handleError = useCallback((error) => {
|
|
24
|
+
if (errorHandler.current) {
|
|
25
|
+
errorHandler.current?.(error);
|
|
26
|
+
successHandler.current = null;
|
|
27
|
+
errorHandler.current = null;
|
|
28
|
+
}
|
|
29
|
+
}, []);
|
|
30
|
+
const onLoad = useCallback(() => {
|
|
31
|
+
const instance = window.grecaptcha?.enterprise ?? window.grecaptcha;
|
|
32
|
+
if (!instance) {
|
|
33
|
+
setState({
|
|
34
|
+
isLoading: false,
|
|
35
|
+
error: new Error("reCaptcha is not available")
|
|
36
|
+
});
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (scriptLoaded.current) return;
|
|
40
|
+
scriptLoaded.current = true;
|
|
41
|
+
instance.ready(() => {
|
|
42
|
+
widgetId.current = instance.render(containerId, {
|
|
43
|
+
sitekey: siteKey,
|
|
44
|
+
badge,
|
|
45
|
+
theme,
|
|
46
|
+
size: "invisible",
|
|
47
|
+
callback: handleSuccess,
|
|
48
|
+
"error-callback": handleError
|
|
49
|
+
});
|
|
50
|
+
grecaptcha.current = instance;
|
|
51
|
+
setState({
|
|
52
|
+
error: null,
|
|
53
|
+
isLoading: false
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}, [
|
|
57
|
+
siteKey,
|
|
58
|
+
containerId,
|
|
59
|
+
badge,
|
|
60
|
+
theme,
|
|
61
|
+
handleSuccess,
|
|
62
|
+
handleError
|
|
63
|
+
]);
|
|
64
|
+
const reset = useCallback(() => {
|
|
65
|
+
grecaptcha.current?.reset(widgetId.current);
|
|
66
|
+
}, []);
|
|
67
|
+
const execute = useCallback((action) => {
|
|
68
|
+
const instance = grecaptcha.current;
|
|
69
|
+
if (instance?.execute) {
|
|
70
|
+
const promise = new Promise((resolve, reject) => {
|
|
71
|
+
successHandler.current = resolve;
|
|
72
|
+
errorHandler.current = reject;
|
|
73
|
+
});
|
|
74
|
+
return Promise.resolve(instance.execute(widgetId.current, action ? { action } : void 0)).then((token) => {
|
|
75
|
+
if (token) handleSuccess(token);
|
|
76
|
+
return promise;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return Promise.reject("ReCaptcha is not available");
|
|
80
|
+
}, [handleSuccess]);
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
const removeScript = injectScriptTag(id, language, useRecaptchaNet, useEnterprise, onLoad);
|
|
83
|
+
return () => {
|
|
84
|
+
removeScript();
|
|
85
|
+
removeScriptTag();
|
|
86
|
+
scriptLoaded.current = false;
|
|
87
|
+
};
|
|
88
|
+
}, [
|
|
89
|
+
id,
|
|
90
|
+
language,
|
|
91
|
+
useRecaptchaNet,
|
|
92
|
+
useEnterprise,
|
|
93
|
+
onLoad
|
|
94
|
+
]);
|
|
95
|
+
const value = useMemo(() => ({
|
|
96
|
+
isLoading: state.isLoading,
|
|
97
|
+
error: state.error ?? null,
|
|
98
|
+
execute,
|
|
99
|
+
reset
|
|
100
|
+
}), [
|
|
101
|
+
state,
|
|
102
|
+
execute,
|
|
103
|
+
reset
|
|
104
|
+
]);
|
|
105
|
+
return jsxs(GoogleReCaptchaContext.Provider, {
|
|
106
|
+
value,
|
|
107
|
+
children: [children, container ? null : jsx("div", { id: `${id}-container` })]
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
//#endregion
|
|
111
|
+
export { GoogleReCaptchaProvider };
|
|
112
|
+
|
|
113
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","names":[],"sources":["../src/provider.tsx"],"sourcesContent":["import { type JSX, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'\nimport { GoogleReCaptchaContext } from './context.js'\nimport type { GoogleReCaptchaContextType, GoogleReCaptchaProviderProps, Grecaptcha } from './types.js'\nimport { injectScriptTag, removeScriptTag } from './utils.js'\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"],"mappings":";;;;;AAUA,IAAM,2BAA2B,EAC/B,SACA,UACA,iBACA,eACA,WACA,OACA,OACA,eAC+C;CAC/C,MAAM,KAAK,OAAO;CAClB,MAAM,cAAc,cAAe,YAAY,YAAY,GAAG,GAAG,aAAc,CAAC,IAAI,UAAU,CAAC;CAC/F,MAAM,CAAC,OAAO,YAAY,SAAgB,EAAE,WAAW,MAAM,CAAC;CAE9D,MAAM,WAAW,OAAe,QAAQ;CACxC,MAAM,aAAa,OAAmB,KAAK;CAC3C,MAAM,eAAe,OAAO,MAAM;CAClC,MAAM,iBAAiB,OAAgC,KAAK;CAC5D,MAAM,eAAe,OAA2C,KAAK;CAErE,MAAM,gBAAgB,aAAa,UAAkB;AACnD,MAAI,eAAe,SAAS;AAC1B,kBAAe,UAAU,MAAM;AAE/B,cAAW,SAAS,MAAM,SAAS,QAAQ;AAC3C,kBAAe,UAAU;AACzB,gBAAa,UAAU;;IAExB,EAAE,CAAC;CAEN,MAAM,cAAc,aAAa,UAA6B;AAC5D,MAAI,aAAa,SAAS;AACxB,gBAAa,UAAU,MAAM;AAC7B,kBAAe,UAAU;AACzB,gBAAa,UAAU;;IAExB,EAAE,CAAC;CAGN,MAAM,SAAS,kBAAkB;EAC/B,MAAM,WAAW,OAAO,YAAY,cAAc,OAAO;AACzD,MAAI,CAAC,UAAU;AACb,YAAS;IACP,WAAW;IACX,OAAO,IAAI,MAAM,6BAA6B;IAC/C,CAAC;AACF;;AAIF,MAAI,aAAa,QACf;AAEF,eAAa,UAAU;AAEvB,WAAS,YAAY;AACnB,YAAS,UAAU,SAAS,OAAO,aAAa;IAC9C,SAAS;IACT;IACA;IACA,MAAM;IACN,UAAU;IACV,kBAAkB;IACnB,CAAC;AACF,cAAW,UAAU;AACrB,YAAS;IACP,OAAO;IACP,WAAW;IACZ,CAAC;IACF;IACD;EAAC;EAAS;EAAa;EAAO;EAAO;EAAe;EAAY,CAAC;CAEpE,MAAM,QAAQ,kBAAkB;AAC9B,aAAW,SAAS,MAAM,SAAS,QAAQ;IAC1C,EAAE,CAAC;CAEN,MAAM,UAAU,aACb,WAAoB;EACnB,MAAM,WAAW,WAAW;AAC5B,MAAI,UAAU,SAAS;GACrB,MAAM,UAAU,IAAI,SAAiB,SAAS,WAAW;AACvD,mBAAe,UAAU;AACzB,iBAAa,UAAU;KACvB;AACF,UAAO,QAAQ,QAAQ,SAAS,QAAQ,SAAS,SAAS,SAAS,EAAE,QAAQ,GAAG,KAAA,EAAU,CAAC,CAAC,MAAM,UAAU;AAC1G,QAAI,MACF,eAAc,MAAM;AAGtB,WAAO;KACP;;AAEJ,SAAO,QAAQ,OAAO,6BAA6B;IAErD,CAAC,cAAc,CAChB;AAGD,iBAAgB;EACd,MAAM,eAAe,gBAAgB,IAAI,UAAU,iBAAiB,eAAe,OAAO;AAC1F,eAAa;AACX,iBAAc;AACd,oBAAiB;AACjB,gBAAa,UAAU;;IAExB;EAAC;EAAI;EAAU;EAAiB;EAAe;EAAO,CAAC;CAE1D,MAAM,QAAoC,eACjC;EACL,WAAW,MAAM;EACjB,OAAO,MAAM,SAAS;EACtB;EACA;EACD,GACD;EAAC;EAAO;EAAS;EAAM,CACxB;AAED,QACE,KAAC,uBAAuB,UAAxB;EAAwC;YAAxC,CACG,UACA,YAAY,OAAO,IAAC,OAAD,EAAK,IAAI,GAAG,GAAG,aAAe,CAAA,CAClB"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { 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.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/utils.ts
|
|
2
|
+
var getRecaptchaScriptSrc = (render, language, useRecaptchaNet, useEnterprise) => {
|
|
3
|
+
return `https://${useRecaptchaNet ? "recaptcha.net" : "google.com"}/recaptcha/${useEnterprise ? "enterprise.js" : "api.js"}?render=${render}${language ? `&hl=${language}` : ""}`;
|
|
4
|
+
};
|
|
5
|
+
var injectScriptTag = (scriptId, language, useRecaptchaNet, useEnterprise, onLoad) => {
|
|
6
|
+
const script = document.createElement("script");
|
|
7
|
+
script.type = "text/javascript";
|
|
8
|
+
script.id = scriptId;
|
|
9
|
+
script.src = getRecaptchaScriptSrc("explicit", language, useRecaptchaNet, useEnterprise);
|
|
10
|
+
script.async = true;
|
|
11
|
+
script.defer = true;
|
|
12
|
+
script.onload = onLoad;
|
|
13
|
+
document.head.appendChild(script);
|
|
14
|
+
return () => {
|
|
15
|
+
document.head.removeChild(script);
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
var removeScriptTag = () => {
|
|
19
|
+
removeRecaptchBadge();
|
|
20
|
+
const script = document.querySelector("script[src^=\"https://www.gstatic.com/recaptcha/releases\"]");
|
|
21
|
+
if (script) script.remove();
|
|
22
|
+
};
|
|
23
|
+
var removeRecaptchBadge = () => {
|
|
24
|
+
const nodeBadge = document.querySelector(".grecaptcha-badge");
|
|
25
|
+
if (nodeBadge?.parentNode) document.body.removeChild(nodeBadge.parentNode);
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
export { injectScriptTag, removeScriptTag };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../src/utils.ts"],"sourcesContent":["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"],"mappings":";AAAA,IAAa,yBACX,QACA,UACA,iBACA,kBACW;AAIX,QAAO,WAHU,kBAAkB,kBAAkB,aAG1B,aAFZ,gBAAgB,kBAAkB,SAEF,UAAU,SAAS,WAAW,OAAO,aAAa;;AAGnG,IAAa,mBACX,UACA,UACA,iBACA,eACA,WACiB;CACjB,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,QAAO,OAAO;AACd,QAAO,KAAK;AACZ,QAAO,MAAM,sBAAsB,YAAY,UAAU,iBAAiB,cAAc;AACxF,QAAO,QAAQ;AACf,QAAO,QAAQ;AACf,QAAO,SAAS;AAEhB,UAAS,KAAK,YAAY,OAAO;AACjC,cAAa;AACX,WAAS,KAAK,YAAY,OAAO;;;AAIrC,IAAa,wBAA8B;AACzC,sBAAqB;CAErB,MAAM,SAAS,SAAS,cAAc,8DAA4D;AAClG,KAAI,OACF,QAAO,QAAQ;;AAInB,IAAa,4BAAkC;CAC7C,MAAM,YAAY,SAAS,cAAc,oBAAoB;AAC7D,KAAI,WAAW,WACb,UAAS,KAAK,YAAY,UAAU,WAAW"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gahojin-inc/react-google-recaptcha",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.5.0",
|
|
4
4
|
"description": "Hooks for Google ReCaptcha V3",
|
|
5
5
|
"author": "GAHOJIN, Inc.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -25,24 +25,27 @@
|
|
|
25
25
|
"access": "public",
|
|
26
26
|
"provenance": true
|
|
27
27
|
},
|
|
28
|
-
"
|
|
29
|
-
"
|
|
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.
|
|
34
|
-
"import": "./dist/index.
|
|
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.
|
|
40
|
+
"react": "19.2.5",
|
|
41
|
+
"react-dom": "19.2.5"
|
|
40
42
|
},
|
|
41
43
|
"peerDependencies": {
|
|
42
|
-
"react": "^18 || ^19"
|
|
44
|
+
"react": "^18 || ^19",
|
|
45
|
+
"react-dom": "^18 || ^19"
|
|
43
46
|
},
|
|
44
47
|
"scripts": {
|
|
45
|
-
"build": "
|
|
48
|
+
"build": "vite build",
|
|
46
49
|
"lint": "biome check --write .",
|
|
47
50
|
"lint:ci": "biome ci .",
|
|
48
51
|
"check": "tsc --noEmit",
|
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";
|
package/dist/index.mjs
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
//#region src/context.tsx
|
|
4
|
-
const GoogleReCaptchaContext = createContext({
|
|
5
|
-
isLoading: true,
|
|
6
|
-
error: null,
|
|
7
|
-
execute: () => Promise.reject("useGoogleRecaptcha must be used within an GoogleReCaptchaProvider"),
|
|
8
|
-
reset: () => []
|
|
9
|
-
});
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/mock_provider.tsx
|
|
12
|
-
const MOCK_TOKEN$1 = "mock-JspVRfSqeamw4CKN3kc7nL_p_MTzWSeE";
|
|
13
|
-
const MockGoogleReCaptchaProvider = ({ container, children }) => {
|
|
14
|
-
const id = useId();
|
|
15
|
-
return /* @__PURE__ */ jsxs(GoogleReCaptchaContext.Provider, {
|
|
16
|
-
value: {
|
|
17
|
-
isLoading: false,
|
|
18
|
-
error: null,
|
|
19
|
-
execute: () => Promise.resolve(MOCK_TOKEN$1),
|
|
20
|
-
reset: () => {}
|
|
21
|
-
},
|
|
22
|
-
children: [children, container ? null : /* @__PURE__ */ jsx("div", { id: `${id}-container` })]
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
//#endregion
|
|
26
|
-
//#region src/utils.ts
|
|
27
|
-
const getRecaptchaScriptSrc = (render, language, useRecaptchaNet, useEnterprise) => {
|
|
28
|
-
return `https://${useRecaptchaNet ? "recaptcha.net" : "google.com"}/recaptcha/${useEnterprise ? "enterprise.js" : "api.js"}?render=${render}${language ? `&hl=${language}` : ""}`;
|
|
29
|
-
};
|
|
30
|
-
const injectScriptTag = (scriptId, language, useRecaptchaNet, useEnterprise, onLoad) => {
|
|
31
|
-
const script = document.createElement("script");
|
|
32
|
-
script.type = "text/javascript";
|
|
33
|
-
script.id = scriptId;
|
|
34
|
-
script.src = getRecaptchaScriptSrc("explicit", language, useRecaptchaNet, useEnterprise);
|
|
35
|
-
script.async = true;
|
|
36
|
-
script.defer = true;
|
|
37
|
-
script.onload = onLoad;
|
|
38
|
-
document.head.appendChild(script);
|
|
39
|
-
return () => {
|
|
40
|
-
document.head.removeChild(script);
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
const removeScriptTag = () => {
|
|
44
|
-
removeRecaptchBadge();
|
|
45
|
-
const script = document.querySelector("script[src^=\"https://www.gstatic.com/recaptcha/releases\"]");
|
|
46
|
-
if (script) script.remove();
|
|
47
|
-
};
|
|
48
|
-
const removeRecaptchBadge = () => {
|
|
49
|
-
const nodeBadge = document.querySelector(".grecaptcha-badge");
|
|
50
|
-
if (nodeBadge?.parentNode) document.body.removeChild(nodeBadge.parentNode);
|
|
51
|
-
};
|
|
52
|
-
//#endregion
|
|
53
|
-
//#region src/provider.tsx
|
|
54
|
-
const GoogleReCaptchaProvider$1 = ({ siteKey, language, useRecaptchaNet, useEnterprise, container, badge, theme, children }) => {
|
|
55
|
-
const id = useId();
|
|
56
|
-
const containerId = useMemo(() => container ? container : `${id}-container`, [id, container]);
|
|
57
|
-
const [state, setState] = useState({ isLoading: true });
|
|
58
|
-
const widgetId = useRef(siteKey);
|
|
59
|
-
const grecaptcha = useRef(null);
|
|
60
|
-
const scriptLoaded = useRef(false);
|
|
61
|
-
const successHandler = useRef(null);
|
|
62
|
-
const errorHandler = useRef(null);
|
|
63
|
-
const handleSuccess = useCallback((token) => {
|
|
64
|
-
if (successHandler.current) {
|
|
65
|
-
successHandler.current?.(token);
|
|
66
|
-
grecaptcha.current?.reset(widgetId.current);
|
|
67
|
-
successHandler.current = null;
|
|
68
|
-
errorHandler.current = null;
|
|
69
|
-
}
|
|
70
|
-
}, []);
|
|
71
|
-
const handleError = useCallback((error) => {
|
|
72
|
-
if (errorHandler.current) {
|
|
73
|
-
errorHandler.current?.(error);
|
|
74
|
-
successHandler.current = null;
|
|
75
|
-
errorHandler.current = null;
|
|
76
|
-
}
|
|
77
|
-
}, []);
|
|
78
|
-
const onLoad = useCallback(() => {
|
|
79
|
-
const instance = window.grecaptcha?.enterprise ?? window.grecaptcha;
|
|
80
|
-
if (!instance) {
|
|
81
|
-
setState({
|
|
82
|
-
isLoading: false,
|
|
83
|
-
error: /* @__PURE__ */ new Error("reCaptcha is not available")
|
|
84
|
-
});
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
if (scriptLoaded.current) return;
|
|
88
|
-
scriptLoaded.current = true;
|
|
89
|
-
instance.ready(() => {
|
|
90
|
-
widgetId.current = instance.render(containerId, {
|
|
91
|
-
sitekey: siteKey,
|
|
92
|
-
badge,
|
|
93
|
-
theme,
|
|
94
|
-
size: "invisible",
|
|
95
|
-
callback: handleSuccess,
|
|
96
|
-
"error-callback": handleError
|
|
97
|
-
});
|
|
98
|
-
grecaptcha.current = instance;
|
|
99
|
-
setState({
|
|
100
|
-
error: null,
|
|
101
|
-
isLoading: false
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
}, [
|
|
105
|
-
siteKey,
|
|
106
|
-
containerId,
|
|
107
|
-
badge,
|
|
108
|
-
theme,
|
|
109
|
-
handleSuccess,
|
|
110
|
-
handleError
|
|
111
|
-
]);
|
|
112
|
-
const reset = useCallback(() => {
|
|
113
|
-
grecaptcha.current?.reset(widgetId.current);
|
|
114
|
-
}, []);
|
|
115
|
-
const execute = useCallback((action) => {
|
|
116
|
-
const instance = grecaptcha.current;
|
|
117
|
-
if (instance?.execute) {
|
|
118
|
-
const promise = new Promise((resolve, reject) => {
|
|
119
|
-
successHandler.current = resolve;
|
|
120
|
-
errorHandler.current = reject;
|
|
121
|
-
});
|
|
122
|
-
return Promise.resolve(instance.execute(widgetId.current, action ? { action } : void 0)).then((token) => {
|
|
123
|
-
if (token) handleSuccess(token);
|
|
124
|
-
return promise;
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
return Promise.reject("ReCaptcha is not available");
|
|
128
|
-
}, [handleSuccess]);
|
|
129
|
-
useEffect(() => {
|
|
130
|
-
const removeScript = injectScriptTag(id, language, useRecaptchaNet, useEnterprise, onLoad);
|
|
131
|
-
return () => {
|
|
132
|
-
removeScript();
|
|
133
|
-
removeScriptTag();
|
|
134
|
-
scriptLoaded.current = false;
|
|
135
|
-
};
|
|
136
|
-
}, [
|
|
137
|
-
id,
|
|
138
|
-
language,
|
|
139
|
-
useRecaptchaNet,
|
|
140
|
-
useEnterprise,
|
|
141
|
-
onLoad
|
|
142
|
-
]);
|
|
143
|
-
const value = useMemo(() => ({
|
|
144
|
-
isLoading: state.isLoading,
|
|
145
|
-
error: state.error ?? null,
|
|
146
|
-
execute,
|
|
147
|
-
reset
|
|
148
|
-
}), [
|
|
149
|
-
state,
|
|
150
|
-
execute,
|
|
151
|
-
reset
|
|
152
|
-
]);
|
|
153
|
-
return /* @__PURE__ */ jsxs(GoogleReCaptchaContext.Provider, {
|
|
154
|
-
value,
|
|
155
|
-
children: [children, container ? null : /* @__PURE__ */ jsx("div", { id: `${id}-container` })]
|
|
156
|
-
});
|
|
157
|
-
};
|
|
158
|
-
//#endregion
|
|
159
|
-
//#region src/hooks.ts
|
|
160
|
-
const useGoogleRecaptcha = () => {
|
|
161
|
-
return useContext(GoogleReCaptchaContext);
|
|
162
|
-
};
|
|
163
|
-
//#endregion
|
|
164
|
-
//#region src/index.ts
|
|
165
|
-
const MOCK_TOKEN = MOCK_TOKEN$1;
|
|
166
|
-
const GoogleReCaptchaProvider = import.meta.env?.MODE === "test" ? MockGoogleReCaptchaProvider : GoogleReCaptchaProvider$1;
|
|
167
|
-
//#endregion
|
|
168
|
-
export { GoogleReCaptchaProvider, MOCK_TOKEN, useGoogleRecaptcha };
|
|
169
|
-
|
|
170
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","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/dist/provider.d.mts
DELETED
|
@@ -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
|
-
}
|
|
File without changes
|