@@ -6,7 +6,9 @@ import React, {
66 type InputHTMLAttributes ,
77 memo ,
88 type ReactNode ,
9- useId
9+ useId ,
10+ useState ,
11+ useEffect
1012} from "react" ;
1113import { assert , type Equals } from "tsafe/assert" ;
1214import { symToStr } from "tsafe/symToStr" ;
@@ -84,6 +86,39 @@ export const PasswordInput = memo(
8486 messages . length !== 0 &&
8587 messages . find ( ( { severity } ) => severity !== "valid" ) === undefined ;
8688
89+ const [ inputWrapperElement , setInputWrapperElement ] = useState < HTMLDivElement | null > ( null ) ;
90+
91+ const [ isPasswordReveled , setIsPasswordReveled ] = useState ( false ) ;
92+
93+ useEffect ( ( ) => {
94+ if ( inputWrapperElement === null ) {
95+ return ;
96+ }
97+
98+ const inputElement = inputWrapperElement . querySelector < HTMLInputElement > ( "input" ) ;
99+
100+ assert ( inputElement !== null ) ;
101+
102+ const observer = new MutationObserver ( mutations => {
103+ mutations . forEach ( mutation => {
104+ if ( mutation . type === "attributes" && mutation . attributeName === "type" ) {
105+ const input = mutation . target as HTMLInputElement ;
106+ const type = input . getAttribute ( "type" ) ;
107+ if ( type === "password" ) {
108+ setIsPasswordReveled ( false ) ;
109+ } else {
110+ setIsPasswordReveled ( true ) ;
111+ }
112+ }
113+ } ) ;
114+ } ) ;
115+
116+ observer . observe ( inputElement , {
117+ attributes : true ,
118+ attributeFilter : [ "type" ]
119+ } ) ;
120+ } , [ inputWrapperElement ] ) ;
121+
87122 return (
88123 < div
89124 className = { cx (
@@ -110,12 +145,12 @@ export const PasswordInput = memo(
110145 { hintText !== undefined && < span className = "fr-hint-text" > { hintText } </ span > }
111146 </ label >
112147 ) }
113- < div className = { fr . cx ( "fr-input-wrap" ) } >
148+ < div className = { fr . cx ( "fr-input-wrap" ) } ref = { setInputWrapperElement } >
114149 < input
115150 { ...nativeInputProps }
116151 className = { cx ( fr . cx ( "fr-password__input" , "fr-input" ) , classes . input ) }
117152 id = { inputId }
118- type = " password"
153+ type = { isPasswordReveled ? "text" : " password"}
119154 disabled = { disabled }
120155 { ...( messages . length !== 0 && { "aria-describedby" : messagesGroupId } ) }
121156 />
0 commit comments