UNPKG

@elsikora/x-captcha-react

Version:

React components for X-Captcha service

64 lines (61 loc) 3.97 kB
import { jsxs, jsx, Fragment } from 'react/jsx-runtime'; import { useState, useMemo, useCallback } from 'react'; import { detectLanguage, createTranslator } from '../i18n/i18n.js'; import '../i18n/translations/index.js'; import { GenerateThemeVariables } from '../utility/generate-theme-variables.utility.js'; import { CaptchaWidget } from './CaptchaWidget.js'; import styles from '../styles/captcha-form.module.css.js'; /** * Form component with integrated captcha and modern styling * @param {ICaptchaFormProperties} props - The properties * @returns {React.ReactElement} The captcha form */ const CaptchaForm = ({ apiUrl, buttonColor, children, className = "", language, onSubmit, publicKey, submitButtonText, themeColor = "#4285F4", ...captchaProperties }) => { const [token, setToken] = useState(null); const [error, setError] = useState(null); const [isHovering, setIsHovering] = useState(false); const [isFocused, setIsFocused] = useState(false); // eslint-disable-next-line @elsikora/react/1/naming-convention/use-state const [translate] = useState(() => { const detectedLanguage = language ?? detectLanguage(); return createTranslator(detectedLanguage); }); // Generate CSS variables from theme props const themeVariables = useMemo(() => GenerateThemeVariables({ buttonColor, themeColor, }), [buttonColor, themeColor]); const defaultSubmitText = submitButtonText ?? "Submit"; const handleVerify = useCallback((newToken) => { setToken(newToken); setError(null); }, []); const handleError = useCallback((errorMessage) => { setToken(null); setError(errorMessage); }, []); const handleSubmit = useCallback((event) => { event.preventDefault(); if (!token) { setError(translate("pleaseCompleteCaptcha")); return; } onSubmit(token, event); }, [token, onSubmit, translate]); const buttonClasses = [styles["x-captcha-submit-button"], token ? styles["x-captcha-submit-button-active"] : styles["x-captcha-submit-button-disabled"], token && isHovering ? styles["x-captcha-submit-button-hover"] : "", token && isFocused ? styles["x-captcha-submit-button-focus"] : ""].filter(Boolean).join(" "); return (jsxs("form", { className: `${styles["x-captcha-form"]} ${className}`, onSubmit: handleSubmit, style: themeVariables, children: [children ? jsx("div", { className: styles["x-captcha-children-container"], children: children }) : jsx(Fragment, {}), jsx("div", { className: styles["x-captcha-captcha-container"], children: jsx(CaptchaWidget, { apiUrl: apiUrl, language: language, onError: handleError, onVerify: handleVerify, publicKey: publicKey, themeColor: themeColor, ...captchaProperties }) }), error && (jsxs("div", { className: styles["x-captcha-error"], children: [jsx("span", { className: styles["x-captcha-error-icon"], children: jsxs("svg", { fill: "none", height: "16", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", viewBox: "0 0 24 24", width: "16", xmlns: "http://www.w3.org/2000/svg", children: [jsx("circle", { cx: "12", cy: "12", r: "10" }), jsx("line", { x1: "12", x2: "12", y1: "8", y2: "12" }), jsx("line", { x1: "12", x2: "12.01", y1: "16", y2: "16" })] }) }), error] })), jsx("button", { className: buttonClasses, disabled: !token, onBlur: () => { if (token) setIsFocused(false); }, onFocus: () => { if (token) setIsFocused(true); }, onMouseEnter: () => { if (token) setIsHovering(true); }, onMouseLeave: () => { if (token) setIsHovering(false); }, type: "submit", children: defaultSubmitText })] })); }; export { CaptchaForm }; //# sourceMappingURL=CaptchaForm.js.map