@@ -6,7 +6,9 @@ import React, {
6
6
type InputHTMLAttributes ,
7
7
memo ,
8
8
type ReactNode ,
9
- useId
9
+ useId ,
10
+ useState ,
11
+ useEffect
10
12
} from "react" ;
11
13
import { assert , type Equals } from "tsafe/assert" ;
12
14
import { symToStr } from "tsafe/symToStr" ;
@@ -84,6 +86,39 @@ export const PasswordInput = memo(
84
86
messages . length !== 0 &&
85
87
messages . find ( ( { severity } ) => severity !== "valid" ) === undefined ;
86
88
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
+
87
122
return (
88
123
< div
89
124
className = { cx (
@@ -110,12 +145,12 @@ export const PasswordInput = memo(
110
145
{ hintText !== undefined && < span className = "fr-hint-text" > { hintText } </ span > }
111
146
</ label >
112
147
) }
113
- < div className = { fr . cx ( "fr-input-wrap" ) } >
148
+ < div className = { fr . cx ( "fr-input-wrap" ) } ref = { setInputWrapperElement } >
114
149
< input
115
150
{ ...nativeInputProps }
116
151
className = { cx ( fr . cx ( "fr-password__input" , "fr-input" ) , classes . input ) }
117
152
id = { inputId }
118
- type = " password"
153
+ type = { isPasswordReveled ? "text" : " password"}
119
154
disabled = { disabled }
120
155
{ ...( messages . length !== 0 && { "aria-describedby" : messagesGroupId } ) }
121
156
/>
0 commit comments