@@ -7,39 +7,46 @@ import { fr } from "./fr";
77import { cx } from "./tools/cx" ;
88import type { FrIconClassName , RiIconClassName } from "./fr/generatedFromCss/classNames" ;
99
10- export type InputProps = InputProps . Input | InputProps . TextArea ;
10+ export type InputProps = {
11+ className ?: string ;
12+ label : ReactNode ;
13+ hintText ?: ReactNode ;
14+ /** default: false */
15+ disabled ?: boolean ;
16+ iconId ?: FrIconClassName | RiIconClassName ;
17+ classes ?: Partial <
18+ Record < "root" | "label" | "description" | "nativeInputOrTextArea" | "message" , string >
19+ > ;
20+ } & ( InputProps . WithSpecialState | InputProps . WithoutSpecialState ) &
21+ ( InputProps . WithoutTextArea | InputProps . WithTextArea ) ;
1122
1223export namespace InputProps {
13- export type Common = {
14- className ?: string ;
15- label : ReactNode ;
16- hintText ?: ReactNode ;
17- /** default: false */
18- disabled ?: boolean ;
19- message ?: {
20- type : "success" | "error" ;
21- text : ReactNode ;
22- } ;
23- iconId ?: FrIconClassName | RiIconClassName ;
24- classes ?: Partial <
25- Record < "root" | "label" | "description" | "nativeInputOrTextArea" | "message" , string >
26- > ;
24+ export type WithSpecialState = {
25+ state : "success" | "error" ;
26+ stateRelatedMessage : ReactNode ;
2727 } ;
2828
29- export type Input = Common & {
29+ export type WithoutSpecialState = {
30+ state ?: never ;
31+ stateRelatedMessage ?: never ;
32+ } ;
33+
34+ export type WithoutTextArea = {
3035 /** Default: false */
3136 isTextArea ?: false ;
3237 /** Props forwarded to the underlying <input /> element */
3338 nativeInputProps ?: InputHTMLAttributes < HTMLInputElement > ;
39+
3440 nativeTextAreaProps ?: never ;
3541 } ;
3642
37- export type TextArea = Common & {
43+ export type WithTextArea = {
3844 /** Default: false */
3945 isTextArea : true ;
40- nativeInputProps ?: never ;
4146 /** Props forwarded to the underlying <textarea /> element */
4247 nativeTextAreaProps ?: TextareaHTMLAttributes < HTMLTextAreaElement > ;
48+
49+ nativeInputProps ?: never ;
4350 } ;
4451}
4552
@@ -53,16 +60,18 @@ export const Input = memo(
5360 label,
5461 hintText,
5562 disabled = false ,
56- message,
5763 iconId : iconId_props ,
58- isTextArea = false ,
59- nativeInputProps = { } ,
60- nativeTextAreaProps = { } ,
6164 classes = { } ,
65+ state,
66+ stateRelatedMessage,
67+ isTextArea = false ,
68+ nativeTextAreaProps,
69+ nativeInputProps,
6270 ...rest
6371 } = props ;
6472
65- const nativeInputOrTextAreaProps = isTextArea ? nativeTextAreaProps : nativeInputProps ;
73+ const nativeInputOrTextAreaProps =
74+ ( isTextArea ? nativeTextAreaProps : nativeInputProps ) ?? { } ;
6675
6776 const NativeInputOrTexArea = isTextArea ? "textarea" : "input" ;
6877
@@ -82,15 +91,15 @@ export const Input = memo(
8291 fr . cx (
8392 "fr-input-group" ,
8493 disabled && "fr-input-group--disabled" ,
85- message !== undefined &&
94+ state !== undefined &&
8695 ( ( ) => {
87- switch ( message . type ) {
96+ switch ( state ) {
8897 case "error" :
8998 return "fr-input-group--error" ;
9099 case "success" :
91100 return "fr-input-group--valid" ;
92101 }
93- assert < Equals < typeof message . type , never > > ( false ) ;
102+ assert < Equals < typeof state , never > > ( false ) ;
94103 } ) ( )
95104 ) ,
96105 classes . root ,
@@ -110,31 +119,29 @@ export const Input = memo(
110119 className = { cx (
111120 fr . cx (
112121 "fr-input" ,
113- message !== undefined &&
122+ state !== undefined &&
114123 ( ( ) => {
115- switch ( message . type ) {
124+ switch ( state ) {
116125 case "error" :
117126 return "fr-input--error" ;
118127 case "success" :
119128 return "fr-input--valid" ;
120129 }
121- assert < Equals < typeof message . type , never > > ( false ) ;
130+ assert < Equals < typeof state , never > > ( false ) ;
122131 } ) ( )
123132 ) ,
124133 classes . nativeInputOrTextArea
125134 ) }
126135 disabled = { disabled || undefined }
127136 aria-describedby = { messageId }
128- type = { isTextArea ? undefined : nativeInputProps . type ?? "text" }
137+ type = { nativeInputProps ? .type ?? "text" }
129138 id = { inputId }
130139 />
131140 ) ;
132141
133142 const iconId =
134143 iconId_props ??
135- ( ! isTextArea && nativeInputProps . type === "date"
136- ? "ri-calendar-line"
137- : undefined ) ;
144+ ( nativeInputProps ?. type === "date" ? "ri-calendar-line" : undefined ) ;
138145
139146 return iconId === undefined ? (
140147 nativeInputOrTextArea
@@ -144,9 +151,25 @@ export const Input = memo(
144151 </ div >
145152 ) ;
146153 } ) ( ) }
147- { message !== undefined && (
148- < p id = { messageId } className = { cx ( fr . cx ( "fr-error-text" ) , classes . message ) } >
149- { message . text }
154+ { stateRelatedMessage !== undefined && (
155+ < p
156+ id = { messageId }
157+ className = { cx (
158+ fr . cx (
159+ ( ( ) => {
160+ switch ( state ) {
161+ case "error" :
162+ return "fr-error-text" ;
163+ case "success" :
164+ return "fr-valid-text" ;
165+ }
166+ assert < Equals < typeof state , never > > ( false ) ;
167+ } ) ( )
168+ ) ,
169+ classes . message
170+ ) }
171+ >
172+ { stateRelatedMessage }
150173 </ p >
151174 ) }
152175 </ div >
0 commit comments