@prosopo/procaptcha-pow 2.12.7 → 2.13.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/.turbo/turbo-build$colon$cjs.log +5 -5
- package/.turbo/turbo-build$colon$tsc.log +19 -19
- package/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +43 -0
- package/dist/cjs/components/procaptchaPoW.cjs +22 -0
- package/dist/cjs/components/procaptchaWidget.cjs +143 -0
- package/dist/cjs/index.cjs +5 -2
- package/dist/components/procaptchaPoW.d.ts +7 -0
- package/dist/components/procaptchaPoW.d.ts.map +1 -0
- package/dist/components/procaptchaPoW.js +21 -0
- package/dist/components/procaptchaPoW.js.map +1 -0
- package/dist/components/procaptchaWidget.d.ts +7 -0
- package/dist/components/procaptchaWidget.d.ts.map +1 -0
- package/dist/components/procaptchaWidget.js +143 -0
- package/dist/components/procaptchaWidget.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -2
- package/dist/tests/domHarness.d.ts +20 -0
- package/dist/tests/domHarness.d.ts.map +1 -0
- package/dist/tests/domHarness.js +56 -0
- package/dist/tests/domHarness.js.map +1 -0
- package/dist/tests/procaptchaPoW.unit.test.js +46 -30
- package/dist/tests/procaptchaPoW.unit.test.js.map +1 -1
- package/dist/tests/procaptchaPow.test-d.js +5 -5
- package/dist/tests/procaptchaPow.test-d.js.map +1 -1
- package/dist/tests/procaptchaWidget.unit.test.js +79 -137
- package/dist/tests/procaptchaWidget.unit.test.js.map +1 -1
- package/package.json +9 -13
- package/src/components/procaptchaPoW.ts +53 -0
- package/src/components/procaptchaWidget.ts +281 -0
- package/src/index.ts +2 -2
- package/src/tests/domHarness.ts +122 -0
- package/src/tests/procaptchaPoW.unit.test.ts +59 -36
- package/src/tests/procaptchaPow.test-d.ts +15 -9
- package/src/tests/procaptchaWidget.unit.test.ts +105 -171
- package/tsconfig.cjs.json +1 -2
- package/tsconfig.json +1 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/components/ProcaptchaPoW.cjs +0 -7
- package/dist/cjs/components/ProcaptchaWidget.cjs +0 -130
- package/dist/components/ProcaptchaPoW.d.ts +0 -3
- package/dist/components/ProcaptchaPoW.d.ts.map +0 -1
- package/dist/components/ProcaptchaPoW.js +0 -7
- package/dist/components/ProcaptchaPoW.js.map +0 -1
- package/dist/components/ProcaptchaWidget.d.ts +0 -4
- package/dist/components/ProcaptchaWidget.d.ts.map +0 -1
- package/dist/components/ProcaptchaWidget.js +0 -131
- package/dist/components/ProcaptchaWidget.js.map +0 -1
- package/src/components/ProcaptchaPoW.tsx +0 -39
- package/src/components/ProcaptchaWidget.tsx +0 -231
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
let react = require("react");
|
|
2
|
-
let _emotion_react_jsx_runtime = require("@emotion/react/jsx-runtime");
|
|
3
|
-
//#region src/components/ProcaptchaPoW.tsx
|
|
4
|
-
var ProcaptchaWidget = (0, react.lazy)(async () => Promise.resolve().then(() => require("./ProcaptchaWidget.cjs")));
|
|
5
|
-
var ProcaptchaPow = (props) => /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(react.Suspense, { children: /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(ProcaptchaWidget, { ...props }) });
|
|
6
|
-
//#endregion
|
|
7
|
-
exports.ProcaptchaPow = ProcaptchaPow;
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
const require_Manager = require("../services/Manager.cjs");
|
|
2
|
-
let _prosopo_locale = require("@prosopo/locale");
|
|
3
|
-
let _prosopo_procaptcha_common = require("@prosopo/procaptcha-common");
|
|
4
|
-
let _prosopo_types = require("@prosopo/types");
|
|
5
|
-
let _prosopo_widget_skeleton = require("@prosopo/widget-skeleton");
|
|
6
|
-
let react = require("react");
|
|
7
|
-
let _emotion_react_jsx_runtime = require("@emotion/react/jsx-runtime");
|
|
8
|
-
//#region src/components/ProcaptchaWidget.tsx
|
|
9
|
-
var PROCAPTCHA_EXECUTE_EVENT = "procaptcha:execute";
|
|
10
|
-
var Procaptcha = (props) => {
|
|
11
|
-
const { t, ready: isTranslationReady } = (0, _prosopo_locale.useTranslation)();
|
|
12
|
-
const config = props.config;
|
|
13
|
-
const i18n = props.i18n;
|
|
14
|
-
const theme = "light" === config.theme ? _prosopo_widget_skeleton.lightTheme : _prosopo_widget_skeleton.darkTheme;
|
|
15
|
-
const frictionlessState = props.frictionlessState;
|
|
16
|
-
const callbacks = props.callbacks || {};
|
|
17
|
-
const [state, _updateState] = (0, _prosopo_procaptcha_common.useProcaptcha)(react.useState, react.useRef);
|
|
18
|
-
const [loading, setLoading] = (0, react.useState)(false);
|
|
19
|
-
const updateState = (0, _prosopo_procaptcha_common.buildUpdateState)(state, _updateState);
|
|
20
|
-
const hpRef = (0, react.useRef)(null);
|
|
21
|
-
const executeRunning = (0, react.useRef)(false);
|
|
22
|
-
const manager = (0, react.useRef)(require_Manager.Manager(config, state, updateState, callbacks, frictionlessState, props.onEscalate, () => hpRef.current?.value || void 0));
|
|
23
|
-
const lastCoordsRef = (0, react.useRef)(null);
|
|
24
|
-
const sessionInvalidatedFiredRef = (0, react.useRef)(false);
|
|
25
|
-
(0, react.useEffect)(() => {
|
|
26
|
-
if (!config.language) return;
|
|
27
|
-
if (i18n) {
|
|
28
|
-
if (i18n.language !== config.language) i18n.changeLanguage(config.language);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
(0, _prosopo_locale.loadI18next)(false, config.language);
|
|
32
|
-
}, [i18n, config.language]);
|
|
33
|
-
(0, react.useEffect)(() => {
|
|
34
|
-
if (!props.autoStart) return;
|
|
35
|
-
setLoading(true);
|
|
36
|
-
const coords = props.startCoords;
|
|
37
|
-
lastCoordsRef.current = coords ?? null;
|
|
38
|
-
manager.current.start(coords?.x ?? 0, coords?.y ?? 0).catch((error) => {
|
|
39
|
-
console.error("Error starting PoW verification:", error);
|
|
40
|
-
}).finally(() => {
|
|
41
|
-
setLoading(false);
|
|
42
|
-
});
|
|
43
|
-
}, [props.autoStart, props.startCoords]);
|
|
44
|
-
(0, react.useEffect)(() => {
|
|
45
|
-
if (!state.error) return;
|
|
46
|
-
setLoading(false);
|
|
47
|
-
if (state.error.key !== "CAPTCHA.NO_SESSION_FOUND") return;
|
|
48
|
-
if (props.onSessionInvalidated && !sessionInvalidatedFiredRef.current) {
|
|
49
|
-
sessionInvalidatedFiredRef.current = true;
|
|
50
|
-
const coords = lastCoordsRef.current;
|
|
51
|
-
props.onSessionInvalidated(coords?.x, coords?.y);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
if (frictionlessState) setTimeout(() => {
|
|
55
|
-
frictionlessState.restart();
|
|
56
|
-
}, 100);
|
|
57
|
-
}, [
|
|
58
|
-
state.error,
|
|
59
|
-
frictionlessState,
|
|
60
|
-
props.onSessionInvalidated
|
|
61
|
-
]);
|
|
62
|
-
(0, react.useEffect)(() => {
|
|
63
|
-
const invisible = config.mode === _prosopo_types.ModeEnum.invisible;
|
|
64
|
-
const logError = (error) => {
|
|
65
|
-
console.error("Error starting PoW verification:", error);
|
|
66
|
-
};
|
|
67
|
-
const handleExecuteEvent = () => {
|
|
68
|
-
if (executeRunning.current) return;
|
|
69
|
-
executeRunning.current = true;
|
|
70
|
-
if (!invisible) setLoading(true);
|
|
71
|
-
const done = () => {
|
|
72
|
-
executeRunning.current = false;
|
|
73
|
-
if (!invisible) setLoading(false);
|
|
74
|
-
};
|
|
75
|
-
try {
|
|
76
|
-
manager.current.start().catch(logError).finally(done);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
logError(error);
|
|
79
|
-
done();
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
const container = props.container;
|
|
83
|
-
container?.addEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
|
|
84
|
-
if (invisible) document.addEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
|
|
85
|
-
return () => {
|
|
86
|
-
container?.removeEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
|
|
87
|
-
if (invisible) document.removeEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
|
|
88
|
-
};
|
|
89
|
-
}, [config.mode, props.container]);
|
|
90
|
-
const honeypot = frictionlessState?.hp ? /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(_prosopo_procaptcha_common.Honeypot, {
|
|
91
|
-
ref: hpRef,
|
|
92
|
-
encodedQuestion: frictionlessState.hp
|
|
93
|
-
}) : null;
|
|
94
|
-
if (config.mode === _prosopo_types.ModeEnum.invisible) return honeypot;
|
|
95
|
-
return /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsxs)(_emotion_react_jsx_runtime.Fragment, { children: [honeypot, /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(_prosopo_procaptcha_common.Checkbox, {
|
|
96
|
-
checked: state.isHuman,
|
|
97
|
-
theme,
|
|
98
|
-
onChange: async (event) => {
|
|
99
|
-
if (loading) return;
|
|
100
|
-
setLoading(true);
|
|
101
|
-
let x = 0;
|
|
102
|
-
let y = 0;
|
|
103
|
-
const mouseOrTouchEvent = event.nativeEvent;
|
|
104
|
-
if (!(0, _prosopo_procaptcha_common.isEventTrusted)(mouseOrTouchEvent)) {} else if ("touches" in mouseOrTouchEvent && mouseOrTouchEvent.touches.length > 0 && mouseOrTouchEvent.touches[0]) {
|
|
105
|
-
x = mouseOrTouchEvent.touches[0].clientX;
|
|
106
|
-
y = mouseOrTouchEvent.touches[0].clientY;
|
|
107
|
-
} else if ("clientX" in mouseOrTouchEvent && "clientY" in mouseOrTouchEvent) {
|
|
108
|
-
x = mouseOrTouchEvent.clientX;
|
|
109
|
-
y = mouseOrTouchEvent.clientY;
|
|
110
|
-
}
|
|
111
|
-
lastCoordsRef.current = {
|
|
112
|
-
x,
|
|
113
|
-
y
|
|
114
|
-
};
|
|
115
|
-
try {
|
|
116
|
-
await manager.current.start(x, y);
|
|
117
|
-
} catch (error) {
|
|
118
|
-
console.error("Error starting PoW verification:", error);
|
|
119
|
-
}
|
|
120
|
-
setLoading(false);
|
|
121
|
-
},
|
|
122
|
-
labelText: isTranslationReady ? t("WIDGET.I_AM_HUMAN") : "",
|
|
123
|
-
error: state.error?.message,
|
|
124
|
-
"aria-label": "human checkbox",
|
|
125
|
-
loadingText: t("WIDGET.CHECKING", { defaultValue: "Checking that you are human" }),
|
|
126
|
-
loading
|
|
127
|
-
})] });
|
|
128
|
-
};
|
|
129
|
-
//#endregion
|
|
130
|
-
exports.default = Procaptcha;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ProcaptchaPoW.d.ts","sourceRoot":"","sources":["../../src/components/ProcaptchaPoW.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAoBtD,eAAO,MAAM,aAAa,UAAW,eAAe,qDAInD,CAAC"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Suspense, lazy } from "react";
|
|
2
|
-
import { jsx } from "@emotion/react/jsx-runtime";
|
|
3
|
-
//#region src/components/ProcaptchaPoW.tsx
|
|
4
|
-
var ProcaptchaWidget = lazy(async () => import("./ProcaptchaWidget.js"));
|
|
5
|
-
var ProcaptchaPow = (props) => /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(ProcaptchaWidget, { ...props }) });
|
|
6
|
-
//#endregion
|
|
7
|
-
export { ProcaptchaPow };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ProcaptchaPoW.js","sourceRoot":"","sources":["../../src/components/ProcaptchaPoW.tsx"],"names":[],"mappings":";AAeA,OAAO,EAA4B,QAAQ,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AASjE,MAAM,gBAAgB,GAAmD,IAAI,CAC5E,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAC3C,CAAC;AAQF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAsB,EAAE,EAAE,CAAC,CACxD,KAAC,QAAQ,cACR,KAAC,gBAAgB,OAAK,KAAK,GAAI,GACrB,CACX,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ProcaptchaWidget.d.ts","sourceRoot":"","sources":["../../src/components/ProcaptchaWidget.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAY,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAQhE,QAAA,MAAM,UAAU,UAAW,eAAe,4DA2MzC,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import "../_virtual/_rolldown/runtime.js";
|
|
2
|
-
import { Manager } from "../services/Manager.js";
|
|
3
|
-
import { loadI18next, useTranslation } from "@prosopo/locale";
|
|
4
|
-
import { Checkbox, Honeypot, buildUpdateState, isEventTrusted, useProcaptcha } from "@prosopo/procaptcha-common";
|
|
5
|
-
import { ModeEnum } from "@prosopo/types";
|
|
6
|
-
import { darkTheme, lightTheme } from "@prosopo/widget-skeleton";
|
|
7
|
-
import { useEffect, useRef, useState } from "react";
|
|
8
|
-
import { Fragment, jsx, jsxs } from "@emotion/react/jsx-runtime";
|
|
9
|
-
//#region src/components/ProcaptchaWidget.tsx
|
|
10
|
-
var PROCAPTCHA_EXECUTE_EVENT = "procaptcha:execute";
|
|
11
|
-
var Procaptcha = (props) => {
|
|
12
|
-
const { t, ready: isTranslationReady } = useTranslation();
|
|
13
|
-
const config = props.config;
|
|
14
|
-
const i18n = props.i18n;
|
|
15
|
-
const theme = "light" === config.theme ? lightTheme : darkTheme;
|
|
16
|
-
const frictionlessState = props.frictionlessState;
|
|
17
|
-
const callbacks = props.callbacks || {};
|
|
18
|
-
const [state, _updateState] = useProcaptcha(useState, useRef);
|
|
19
|
-
const [loading, setLoading] = useState(false);
|
|
20
|
-
const updateState = buildUpdateState(state, _updateState);
|
|
21
|
-
const hpRef = useRef(null);
|
|
22
|
-
const executeRunning = useRef(false);
|
|
23
|
-
const manager = useRef(Manager(config, state, updateState, callbacks, frictionlessState, props.onEscalate, () => hpRef.current?.value || void 0));
|
|
24
|
-
const lastCoordsRef = useRef(null);
|
|
25
|
-
const sessionInvalidatedFiredRef = useRef(false);
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
if (!config.language) return;
|
|
28
|
-
if (i18n) {
|
|
29
|
-
if (i18n.language !== config.language) i18n.changeLanguage(config.language);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
loadI18next(false, config.language);
|
|
33
|
-
}, [i18n, config.language]);
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
if (!props.autoStart) return;
|
|
36
|
-
setLoading(true);
|
|
37
|
-
const coords = props.startCoords;
|
|
38
|
-
lastCoordsRef.current = coords ?? null;
|
|
39
|
-
manager.current.start(coords?.x ?? 0, coords?.y ?? 0).catch((error) => {
|
|
40
|
-
console.error("Error starting PoW verification:", error);
|
|
41
|
-
}).finally(() => {
|
|
42
|
-
setLoading(false);
|
|
43
|
-
});
|
|
44
|
-
}, [props.autoStart, props.startCoords]);
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
if (!state.error) return;
|
|
47
|
-
setLoading(false);
|
|
48
|
-
if (state.error.key !== "CAPTCHA.NO_SESSION_FOUND") return;
|
|
49
|
-
if (props.onSessionInvalidated && !sessionInvalidatedFiredRef.current) {
|
|
50
|
-
sessionInvalidatedFiredRef.current = true;
|
|
51
|
-
const coords = lastCoordsRef.current;
|
|
52
|
-
props.onSessionInvalidated(coords?.x, coords?.y);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
if (frictionlessState) setTimeout(() => {
|
|
56
|
-
frictionlessState.restart();
|
|
57
|
-
}, 100);
|
|
58
|
-
}, [
|
|
59
|
-
state.error,
|
|
60
|
-
frictionlessState,
|
|
61
|
-
props.onSessionInvalidated
|
|
62
|
-
]);
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
const invisible = config.mode === ModeEnum.invisible;
|
|
65
|
-
const logError = (error) => {
|
|
66
|
-
console.error("Error starting PoW verification:", error);
|
|
67
|
-
};
|
|
68
|
-
const handleExecuteEvent = () => {
|
|
69
|
-
if (executeRunning.current) return;
|
|
70
|
-
executeRunning.current = true;
|
|
71
|
-
if (!invisible) setLoading(true);
|
|
72
|
-
const done = () => {
|
|
73
|
-
executeRunning.current = false;
|
|
74
|
-
if (!invisible) setLoading(false);
|
|
75
|
-
};
|
|
76
|
-
try {
|
|
77
|
-
manager.current.start().catch(logError).finally(done);
|
|
78
|
-
} catch (error) {
|
|
79
|
-
logError(error);
|
|
80
|
-
done();
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
const container = props.container;
|
|
84
|
-
container?.addEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
|
|
85
|
-
if (invisible) document.addEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
|
|
86
|
-
return () => {
|
|
87
|
-
container?.removeEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
|
|
88
|
-
if (invisible) document.removeEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
|
|
89
|
-
};
|
|
90
|
-
}, [config.mode, props.container]);
|
|
91
|
-
const honeypot = frictionlessState?.hp ? /* @__PURE__ */ jsx(Honeypot, {
|
|
92
|
-
ref: hpRef,
|
|
93
|
-
encodedQuestion: frictionlessState.hp
|
|
94
|
-
}) : null;
|
|
95
|
-
if (config.mode === ModeEnum.invisible) return honeypot;
|
|
96
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [honeypot, /* @__PURE__ */ jsx(Checkbox, {
|
|
97
|
-
checked: state.isHuman,
|
|
98
|
-
theme,
|
|
99
|
-
onChange: async (event) => {
|
|
100
|
-
if (loading) return;
|
|
101
|
-
setLoading(true);
|
|
102
|
-
let x = 0;
|
|
103
|
-
let y = 0;
|
|
104
|
-
const mouseOrTouchEvent = event.nativeEvent;
|
|
105
|
-
if (!isEventTrusted(mouseOrTouchEvent)) {} else if ("touches" in mouseOrTouchEvent && mouseOrTouchEvent.touches.length > 0 && mouseOrTouchEvent.touches[0]) {
|
|
106
|
-
x = mouseOrTouchEvent.touches[0].clientX;
|
|
107
|
-
y = mouseOrTouchEvent.touches[0].clientY;
|
|
108
|
-
} else if ("clientX" in mouseOrTouchEvent && "clientY" in mouseOrTouchEvent) {
|
|
109
|
-
x = mouseOrTouchEvent.clientX;
|
|
110
|
-
y = mouseOrTouchEvent.clientY;
|
|
111
|
-
}
|
|
112
|
-
lastCoordsRef.current = {
|
|
113
|
-
x,
|
|
114
|
-
y
|
|
115
|
-
};
|
|
116
|
-
try {
|
|
117
|
-
await manager.current.start(x, y);
|
|
118
|
-
} catch (error) {
|
|
119
|
-
console.error("Error starting PoW verification:", error);
|
|
120
|
-
}
|
|
121
|
-
setLoading(false);
|
|
122
|
-
},
|
|
123
|
-
labelText: isTranslationReady ? t("WIDGET.I_AM_HUMAN") : "",
|
|
124
|
-
error: state.error?.message,
|
|
125
|
-
"aria-label": "human checkbox",
|
|
126
|
-
loadingText: t("WIDGET.CHECKING", { defaultValue: "Checking that you are human" }),
|
|
127
|
-
loading
|
|
128
|
-
})] });
|
|
129
|
-
};
|
|
130
|
-
//#endregion
|
|
131
|
-
export { Procaptcha as default };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ProcaptchaWidget.js","sourceRoot":"","sources":["../../src/components/ProcaptchaWidget.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAwB,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGjD,MAAM,wBAAwB,GAAG,oBAAoB,CAAC;AAEtD,MAAM,UAAU,GAAG,CAAC,KAAsB,EAAE,EAAE;IAC7C,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,GAAG,cAAc,EAAE,CAAC;IAC1D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,MAAM,KAAK,GAAG,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IAChE,MAAM,iBAAiB,GAAG,KAAK,CAAC,iBAAiB,CAAC;IAClD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;IACxC,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9C,MAAM,WAAW,GAAG,gBAAgB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAG7C,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,MAAM,CACrB,OAAO,CACN,MAAM,EACN,KAAK,EACL,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,KAAK,CAAC,UAAU,EAChB,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,IAAI,SAAS,CACvC,CACD,CAAC;IAKF,MAAM,aAAa,GAAG,MAAM,CAAkC,IAAI,CAAC,CAAC;IAIpE,MAAM,0BAA0B,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEjD,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,MAAM,CAAC,QAAQ;YAAE,OAAO;QAC7B,IAAI,IAAI,EAAE,CAAC;YACV,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACvC,KAAK,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC3C,CAAC;YACD,OAAO;QACR,CAAC;QAKD,KAAK,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE5B,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,KAAK,CAAC,SAAS;YAAE,OAAO;QAC7B,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC;QACjC,aAAa,CAAC,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC;QACvC,OAAO,CAAC,OAAO;aACb,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;aAIrC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACzB,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACb,UAAU,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAEzC,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,KAAK,CAAC,KAAK;YAAE,OAAO;QACzB,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,0BAA0B;YAAE,OAAO;QAC3D,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,0BAA0B,CAAC,OAAO,EAAE,CAAC;YAKvE,0BAA0B,CAAC,OAAO,GAAG,IAAI,CAAC;YAC1C,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC;YACrC,KAAK,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YACjD,OAAO;QACR,CAAC;QACD,IAAI,iBAAiB,EAAE,CAAC;YAGvB,UAAU,CAAC,GAAG,EAAE;gBACf,iBAAiB,CAAC,OAAO,EAAE,CAAC;YAC7B,CAAC,EAAE,GAAG,CAAC,CAAC;QACT,CAAC;IACF,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAKjE,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,SAAS,CAAC;QACrD,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAE,EAAE;YACnC,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC,CAAC;QACF,MAAM,kBAAkB,GAAG,GAAG,EAAE;YAC/B,IAAI,cAAc,CAAC,OAAO;gBAAE,OAAO;YACnC,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;YAC9B,IAAI,CAAC,SAAS;gBAAE,UAAU,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,IAAI,GAAG,GAAG,EAAE;gBACjB,cAAc,CAAC,OAAO,GAAG,KAAK,CAAC;gBAC/B,IAAI,CAAC,SAAS;oBAAE,UAAU,CAAC,KAAK,CAAC,CAAC;YACnC,CAAC,CAAC;YACF,IAAI,CAAC;gBACJ,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC5D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAChB,IAAI,EAAE,CAAC;YACR,CAAC;QACF,CAAC,CAAC;QAEF,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;QAClC,SAAS,EAAE,gBAAgB,CAAC,wBAAwB,EAAE,kBAAkB,CAAC,CAAC;QAC1E,IAAI,SAAS,EAAE,CAAC;YACf,QAAQ,CAAC,gBAAgB,CAAC,wBAAwB,EAAE,kBAAkB,CAAC,CAAC;QACzE,CAAC;QAED,OAAO,GAAG,EAAE;YACX,SAAS,EAAE,mBAAmB,CAC7B,wBAAwB,EACxB,kBAAkB,CAClB,CAAC;YACF,IAAI,SAAS,EAAE,CAAC;gBACf,QAAQ,CAAC,mBAAmB,CAC3B,wBAAwB,EACxB,kBAAkB,CAClB,CAAC;YACH,CAAC;QACF,CAAC,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAEnC,MAAM,QAAQ,GAAG,iBAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,CACxC,KAAC,QAAQ,IAAC,GAAG,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,CAAC,EAAE,GAAI,CAC/D,CAAC,CAAC,CAAC,IAAI,CAAC;IAET,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,SAAS,EAAE,CAAC;QAGxC,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,OAAO,CACN,8BACE,QAAQ,EACT,KAAC,QAAQ,IACR,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,KAAK,EAAE,KAA0C,EAAE,EAAE;oBAC9D,IAAI,OAAO,EAAE,CAAC;wBACb,OAAO;oBACR,CAAC;oBACD,UAAU,CAAC,IAAI,CAAC,CAAC;oBAGjB,IAAI,CAAC,GAAG,CAAC,CAAC;oBACV,IAAI,CAAC,GAAG,CAAC,CAAC;oBAIV,MAAM,iBAAiB,GAAG,KAAK,CAAC,WAAW,CAAC;oBAC5C,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,EAAE,CAAC;oBAEzC,CAAC;yBAAM,IACN,SAAS,IAAI,iBAAiB;wBAC9B,iBAAiB,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;wBACpC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAC3B,CAAC;wBACF,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;wBACzC,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;oBAC1C,CAAC;yBAAM,IACN,SAAS,IAAI,iBAAiB;wBAC9B,SAAS,IAAI,iBAAiB,EAC7B,CAAC;wBACF,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC;wBAC9B,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC;oBAC/B,CAAC;oBAED,aAAa,CAAC,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;oBACjC,IAAI,CAAC;wBACJ,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;oBACnC,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBAIhB,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;oBAC1D,CAAC;oBACD,UAAU,CAAC,KAAK,CAAC,CAAC;gBACnB,CAAC,EACD,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,EAAE,EAC3D,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,gBAChB,gBAAgB,EAC3B,WAAW,EAAE,CAAC,CAAC,iBAAiB,EAAE;oBACjC,YAAY,EAAE,6BAA6B;iBAC3C,CAAC,EACF,OAAO,EAAE,OAAO,GACf,IACA,CACH,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
|
|
15
|
-
import type { ProcaptchaProps } from "@prosopo/types";
|
|
16
|
-
import { type LazyExoticComponent, Suspense, lazy } from "react";
|
|
17
|
-
import type { ReactElement } from "react";
|
|
18
|
-
|
|
19
|
-
// Define the function signature more precisely
|
|
20
|
-
type ProcaptchaWidgetComponent = (
|
|
21
|
-
props: ProcaptchaProps,
|
|
22
|
-
) => ReactElement | null;
|
|
23
|
-
|
|
24
|
-
// Lazy load the widget with the correct type signature
|
|
25
|
-
const ProcaptchaWidget: LazyExoticComponent<ProcaptchaWidgetComponent> = lazy(
|
|
26
|
-
async () => import("./ProcaptchaWidget.js"),
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
// Spread props rather than enumerating: the inner ProcaptchaWidget consumes
|
|
30
|
-
// `onEscalate` (passed by ProcaptchaFrictionless so a route()-escalated PoW
|
|
31
|
-
// solve can mount the image widget) and `autoStart`. Listing props by name
|
|
32
|
-
// silently dropped both, so the Manager closure captured
|
|
33
|
-
// `onEscalate=undefined` and the post-PoW escalation envelope no-op'd in the
|
|
34
|
-
// browser — the user just saw the PoW checkbox spin forever.
|
|
35
|
-
export const ProcaptchaPow = (props: ProcaptchaProps) => (
|
|
36
|
-
<Suspense>
|
|
37
|
-
<ProcaptchaWidget {...props} />
|
|
38
|
-
</Suspense>
|
|
39
|
-
);
|
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
|
|
15
|
-
import { loadI18next, useTranslation } from "@prosopo/locale";
|
|
16
|
-
import { buildUpdateState, useProcaptcha } from "@prosopo/procaptcha-common";
|
|
17
|
-
import { Checkbox, Honeypot, isEventTrusted } from "@prosopo/procaptcha-common";
|
|
18
|
-
import { ModeEnum, type ProcaptchaProps } from "@prosopo/types";
|
|
19
|
-
import { darkTheme, lightTheme } from "@prosopo/widget-skeleton";
|
|
20
|
-
import { useEffect, useRef, useState } from "react";
|
|
21
|
-
import { Manager } from "../services/Manager.js";
|
|
22
|
-
|
|
23
|
-
// Define the same event name as in the bundle for consistency
|
|
24
|
-
const PROCAPTCHA_EXECUTE_EVENT = "procaptcha:execute";
|
|
25
|
-
|
|
26
|
-
const Procaptcha = (props: ProcaptchaProps) => {
|
|
27
|
-
const { t, ready: isTranslationReady } = useTranslation();
|
|
28
|
-
const config = props.config;
|
|
29
|
-
const i18n = props.i18n;
|
|
30
|
-
const theme = "light" === config.theme ? lightTheme : darkTheme;
|
|
31
|
-
const frictionlessState = props.frictionlessState; // Set up Session ID and Provider if they exist
|
|
32
|
-
const callbacks = props.callbacks || {};
|
|
33
|
-
const [state, _updateState] = useProcaptcha(useState, useRef);
|
|
34
|
-
const [loading, setLoading] = useState(false);
|
|
35
|
-
// get the state update mechanism
|
|
36
|
-
const updateState = buildUpdateState(state, _updateState);
|
|
37
|
-
const hpRef = useRef<HTMLInputElement>(null);
|
|
38
|
-
// A bound button can be clicked again while the first run is still going;
|
|
39
|
-
// `loading` is not in the execute effect's deps, so the guard is a ref.
|
|
40
|
-
const executeRunning = useRef(false);
|
|
41
|
-
const manager = useRef(
|
|
42
|
-
Manager(
|
|
43
|
-
config,
|
|
44
|
-
state,
|
|
45
|
-
updateState,
|
|
46
|
-
callbacks,
|
|
47
|
-
frictionlessState,
|
|
48
|
-
props.onEscalate,
|
|
49
|
-
() => hpRef.current?.value || undefined,
|
|
50
|
-
),
|
|
51
|
-
);
|
|
52
|
-
// Coordinates of the last `manager.start(x, y)` invocation from this widget
|
|
53
|
-
// instance — either the checkbox click, or a `startCoords` handoff from a
|
|
54
|
-
// prior `onSessionInvalidated` cycle. Held in a ref so the current values
|
|
55
|
-
// survive re-renders and are readable from the `state.error` effect.
|
|
56
|
-
const lastCoordsRef = useRef<{ x: number; y: number } | null>(null);
|
|
57
|
-
// One-shot guard: a widget instance only escalates a single NO_SESSION_FOUND
|
|
58
|
-
// to `onSessionInvalidated`. If the retry also fails, we fall through to
|
|
59
|
-
// the pre-existing `frictionlessState.restart()` path instead of looping.
|
|
60
|
-
const sessionInvalidatedFiredRef = useRef(false);
|
|
61
|
-
|
|
62
|
-
useEffect(() => {
|
|
63
|
-
if (!config.language) return;
|
|
64
|
-
if (i18n) {
|
|
65
|
-
if (i18n.language !== config.language) {
|
|
66
|
-
void i18n.changeLanguage(config.language);
|
|
67
|
-
}
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
// Direct-React consumers don't go through WidgetFactory, so pass the
|
|
71
|
-
// language into loadI18next — first init boots with the right language
|
|
72
|
-
// (skipping browser detection), and subsequent calls reconcile via
|
|
73
|
-
// changeLanguage inside loadI18next.
|
|
74
|
-
void loadI18next(false, config.language);
|
|
75
|
-
}, [i18n, config.language]);
|
|
76
|
-
|
|
77
|
-
useEffect(() => {
|
|
78
|
-
if (!props.autoStart) return;
|
|
79
|
-
setLoading(true);
|
|
80
|
-
const coords = props.startCoords;
|
|
81
|
-
lastCoordsRef.current = coords ?? null;
|
|
82
|
-
manager.current
|
|
83
|
-
.start(coords?.x ?? 0, coords?.y ?? 0)
|
|
84
|
-
// The manager handles its own failures, but anything it doesn't (a
|
|
85
|
-
// reset that throws, say) would otherwise escape as an unhandled
|
|
86
|
-
// rejection and leave the widget stuck showing a spinner.
|
|
87
|
-
.catch((error: unknown) => {
|
|
88
|
-
console.error("Error starting PoW verification:", error);
|
|
89
|
-
})
|
|
90
|
-
.finally(() => {
|
|
91
|
-
setLoading(false);
|
|
92
|
-
});
|
|
93
|
-
}, [props.autoStart, props.startCoords]);
|
|
94
|
-
|
|
95
|
-
useEffect(() => {
|
|
96
|
-
if (!state.error) return;
|
|
97
|
-
setLoading(false);
|
|
98
|
-
if (state.error.key !== "CAPTCHA.NO_SESSION_FOUND") return;
|
|
99
|
-
if (props.onSessionInvalidated && !sessionInvalidatedFiredRef.current) {
|
|
100
|
-
// Preserve the checkbox coords across the retry so the resumed
|
|
101
|
-
// submit still carries the real entry-point telemetry. The
|
|
102
|
-
// frictionless wrapper mints a fresh session and re-mounts this
|
|
103
|
-
// widget with matching `autoStart` + `startCoords`.
|
|
104
|
-
sessionInvalidatedFiredRef.current = true;
|
|
105
|
-
const coords = lastCoordsRef.current;
|
|
106
|
-
props.onSessionInvalidated(coords?.x, coords?.y);
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
if (frictionlessState) {
|
|
110
|
-
// Fallback for widgets not mounted under a recovery-aware parent,
|
|
111
|
-
// or a second NO_SESSION_FOUND after we've already retried once.
|
|
112
|
-
setTimeout(() => {
|
|
113
|
-
frictionlessState.restart();
|
|
114
|
-
}, 100);
|
|
115
|
-
}
|
|
116
|
-
}, [state.error, frictionlessState, props.onSessionInvalidated]);
|
|
117
|
-
|
|
118
|
-
// A bare execute() reaches every invisible widget via document. A targeted
|
|
119
|
-
// execute() is dispatched on this widget's container and works in either
|
|
120
|
-
// mode, which is what lets a bound button drive a visible widget.
|
|
121
|
-
useEffect(() => {
|
|
122
|
-
const invisible = config.mode === ModeEnum.invisible;
|
|
123
|
-
const logError = (error: unknown) => {
|
|
124
|
-
console.error("Error starting PoW verification:", error);
|
|
125
|
-
};
|
|
126
|
-
const handleExecuteEvent = () => {
|
|
127
|
-
if (executeRunning.current) return;
|
|
128
|
-
executeRunning.current = true;
|
|
129
|
-
if (!invisible) setLoading(true);
|
|
130
|
-
const done = () => {
|
|
131
|
-
executeRunning.current = false;
|
|
132
|
-
if (!invisible) setLoading(false);
|
|
133
|
-
};
|
|
134
|
-
try {
|
|
135
|
-
void manager.current.start().catch(logError).finally(done);
|
|
136
|
-
} catch (error) {
|
|
137
|
-
logError(error);
|
|
138
|
-
done();
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
const container = props.container;
|
|
143
|
-
container?.addEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
|
|
144
|
-
if (invisible) {
|
|
145
|
-
document.addEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return () => {
|
|
149
|
-
container?.removeEventListener(
|
|
150
|
-
PROCAPTCHA_EXECUTE_EVENT,
|
|
151
|
-
handleExecuteEvent,
|
|
152
|
-
);
|
|
153
|
-
if (invisible) {
|
|
154
|
-
document.removeEventListener(
|
|
155
|
-
PROCAPTCHA_EXECUTE_EVENT,
|
|
156
|
-
handleExecuteEvent,
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
}, [config.mode, props.container]);
|
|
161
|
-
|
|
162
|
-
const honeypot = frictionlessState?.hp ? (
|
|
163
|
-
<Honeypot ref={hpRef} encodedQuestion={frictionlessState.hp} />
|
|
164
|
-
) : null;
|
|
165
|
-
|
|
166
|
-
if (config.mode === ModeEnum.invisible) {
|
|
167
|
-
// Invisible mode renders no checkbox, but we still render the honeypot
|
|
168
|
-
// so bots that scan the DOM for inputs find a tempting target.
|
|
169
|
-
return honeypot;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return (
|
|
173
|
-
<>
|
|
174
|
-
{honeypot}
|
|
175
|
-
<Checkbox
|
|
176
|
-
checked={state.isHuman}
|
|
177
|
-
theme={theme}
|
|
178
|
-
onChange={async (event: React.MouseEvent | React.TouchEvent) => {
|
|
179
|
-
if (loading) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
setLoading(true);
|
|
183
|
-
|
|
184
|
-
// Capture click coordinates
|
|
185
|
-
let x = 0;
|
|
186
|
-
let y = 0;
|
|
187
|
-
|
|
188
|
-
// Try to get coordinates from the change event's underlying mouse event
|
|
189
|
-
// The original mouse event might be available in the event chain
|
|
190
|
-
const mouseOrTouchEvent = event.nativeEvent;
|
|
191
|
-
if (!isEventTrusted(mouseOrTouchEvent)) {
|
|
192
|
-
// Don't capture coordinates for non-trusted events
|
|
193
|
-
} else if (
|
|
194
|
-
"touches" in mouseOrTouchEvent &&
|
|
195
|
-
mouseOrTouchEvent.touches.length > 0 &&
|
|
196
|
-
mouseOrTouchEvent.touches[0]
|
|
197
|
-
) {
|
|
198
|
-
x = mouseOrTouchEvent.touches[0].clientX;
|
|
199
|
-
y = mouseOrTouchEvent.touches[0].clientY;
|
|
200
|
-
} else if (
|
|
201
|
-
"clientX" in mouseOrTouchEvent &&
|
|
202
|
-
"clientY" in mouseOrTouchEvent
|
|
203
|
-
) {
|
|
204
|
-
x = mouseOrTouchEvent.clientX;
|
|
205
|
-
y = mouseOrTouchEvent.clientY;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
lastCoordsRef.current = { x, y };
|
|
209
|
-
try {
|
|
210
|
-
await manager.current.start(x, y);
|
|
211
|
-
} catch (error) {
|
|
212
|
-
// React ignores the promise this handler returns, so a
|
|
213
|
-
// rejection here would surface as an unhandled rejection and
|
|
214
|
-
// the spinner would never clear.
|
|
215
|
-
console.error("Error starting PoW verification:", error);
|
|
216
|
-
}
|
|
217
|
-
setLoading(false);
|
|
218
|
-
}}
|
|
219
|
-
labelText={isTranslationReady ? t("WIDGET.I_AM_HUMAN") : ""}
|
|
220
|
-
error={state.error?.message}
|
|
221
|
-
aria-label="human checkbox"
|
|
222
|
-
loadingText={t("WIDGET.CHECKING", {
|
|
223
|
-
defaultValue: "Checking that you are human",
|
|
224
|
-
})}
|
|
225
|
-
loading={loading}
|
|
226
|
-
/>
|
|
227
|
-
</>
|
|
228
|
-
);
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
export default Procaptcha;
|