diff --git a/src/login/UserProfileFormFields.tsx b/src/login/UserProfileFormFields.tsx index 4d883b76..5c816351 100644 --- a/src/login/UserProfileFormFields.tsx +++ b/src/login/UserProfileFormFields.tsx @@ -1,4 +1,4 @@ -import { useEffect, Fragment } from "react"; +import { useEffect, useReducer, Fragment } from "react"; import type { ClassKey } from "keycloakify/login/TemplateProps"; import { useUserProfileForm, type KcContextLike, type FormAction, type FormFieldError } from "keycloakify/login/lib/useUserProfileForm"; import type { Attribute } from "keycloakify/login/kcContext/KcContext"; @@ -239,7 +239,7 @@ function InputFiledByType(props: InputFiledByTypeProps) { case "select-radiobuttons": case "multiselect-checkboxes": return ; - default: + default: { if (valueOrValues instanceof Array) { return ( <> @@ -250,10 +250,60 @@ function InputFiledByType(props: InputFiledByTypeProps) { ); } - return ; + const inputNode = ; + + if (attribute.name === "password" || attribute.name === "password-confirm") { + return ( + + {inputNode} + + ); + } + + return inputNode; + } } } +function PasswordWrapper(props: { + getClassName: UserProfileFormFieldsProps["getClassName"]; + i18n: I18n; + attributeName: "password" | "password-confirm"; + children: JSX.Element; +}) { + const { getClassName, i18n, attributeName, children } = props; + + const { msgStr } = i18n; + + const [isPasswordRevealed, toggleIsPasswordRevealed] = useReducer((isPasswordRevealed: boolean) => !isPasswordRevealed, false); + + useEffect(() => { + const passwordInputElement = document.getElementById(attributeName); + + assert(passwordInputElement instanceof HTMLInputElement); + + passwordInputElement.type = isPasswordRevealed ? "text" : "password"; + }, [isPasswordRevealed]); + + return ( +
+ {children} + +
+ ); +} + function InputTag(props: InputFiledByTypeProps & { fieldIndex: number | undefined }) { const { attribute, fieldIndex, getClassName, formValidationDispatch, valueOrValues, i18n, displayableErrors } = props;