@@ -25,6 +25,7 @@ export type FollowProps = {
2525 | "newsletter-title"
2626 | "newsletter-desc"
2727 | "newsletter-form-wrapper"
28+ | "newsletter-form-hint"
2829 | "social-col"
2930 | "social"
3031 | "social-title"
@@ -33,36 +34,29 @@ export type FollowProps = {
3334 CxArg
3435 >
3536 > ;
36- social ?: FollowProps . Social ;
3737 style ?: CSSProperties ;
3838 newsletter ?: FollowProps . Newsletter ;
39- } ;
39+ social ?: FollowProps . Social ;
40+ } & ( FollowProps . EitherNewsletter | FollowProps . EitherSocial | FollowProps . EitherBoth ) ;
4041
4142//https://main--ds-gouv.netlify.app/example/component/follow/
4243export namespace FollowProps {
43- /**
44- * From DSFR `$follow-icons` + `copy` and `mail`
45- */
46- export type SocialType =
47- | "copy"
48- | "dailymotion"
49- | "facebook"
50- | "github"
51- | "instagram"
52- | "linkedin"
53- | "mail"
54- | "mastodon"
55- | "snapchat"
56- | "telegram"
57- | "threads"
58- | "tiktok"
59- | "twitch"
60- | "twitter"
61- | "twitter-x"
62- | "vimeo"
63- | "youtube" ;
44+ export type EitherNewsletter = {
45+ newsletter : Newsletter ;
46+ social ?: Social ;
47+ } ;
48+
49+ export type EitherSocial = {
50+ newsletter ?: Newsletter ;
51+ social : Social ;
52+ } ;
53+
54+ export type EitherBoth = {
55+ newsletter : Newsletter ;
56+ social : Social ;
57+ } ;
6458
65- type TitleAs = {
59+ export type TitleAs = {
6660 title ?: ReactNode ;
6761 /**
6862 * Display only. The tag will stay `h2`.
@@ -72,15 +66,6 @@ export namespace FollowProps {
7266 titleAs ?: `h${2 | 3 | 4 | 5 | 6 } `;
7367 } ;
7468
75- export type SocialButton = {
76- type : SocialType ;
77- linkProps : RegisteredLinkProps ;
78- } ;
79-
80- export type Social = TitleAs & {
81- buttons : [ SocialButton , ...SocialButton [ ] ] ;
82- } ;
83-
8469 export type NewsletterForm = {
8570 /** Bound props to display success alert */
8671 success : boolean ;
@@ -99,18 +84,62 @@ export namespace FollowProps {
9984 */
10085 formComponent : < TProps extends PropsWithChildren > ( { children } : TProps ) => React . ReactNode ;
10186 consentHint ?: ReactNode ;
102- inputProps : Omit < InputProps . RegularInput , "addon" > ;
87+ inputProps ?: Partial < Omit < InputProps . RegularInput , "addon" > > ;
10388 } ;
10489
105- export type Newsletter = TitleAs & {
106- desc ?: ReactNode ;
90+ export type NewsletterWithForm = {
10791 /** "Subscribe" button */
10892 buttonProps : ButtonProps . Common &
10993 ButtonProps . AsButton &
11094 // optional children
11195 Partial < ButtonProps . WithoutIcon > ;
11296 /** When using a form */
113- form ?: NewsletterForm ;
97+ form : NewsletterForm ;
98+ } ;
99+
100+ export type NewsletterWithoutForm = {
101+ /** "Subscribe" button */
102+ buttonProps : ButtonProps . Common &
103+ ( ButtonProps . AsButton | ButtonProps . AsAnchor ) &
104+ // optional children
105+ Partial < ButtonProps . WithoutIcon > ;
106+ /** When using a form */
107+ form ?: never ;
108+ } ;
109+
110+ export type Newsletter = TitleAs & {
111+ desc ?: ReactNode ;
112+ } & ( NewsletterWithForm | NewsletterWithoutForm ) ;
113+
114+ /**
115+ * From DSFR `$follow-icons` + `copy` and `mail`
116+ */
117+ export type SocialType =
118+ | "copy"
119+ | "dailymotion"
120+ | "facebook"
121+ | "github"
122+ | "instagram"
123+ | "linkedin"
124+ | "mail"
125+ | "mastodon"
126+ | "snapchat"
127+ | "telegram"
128+ | "threads"
129+ | "tiktok"
130+ | "twitch"
131+ | "twitter"
132+ | "twitter-x"
133+ | "vimeo"
134+ | "youtube" ;
135+
136+ export type SocialButton = {
137+ type : SocialType ;
138+ linkProps : RegisteredLinkProps ;
139+ } ;
140+
141+ export type Social = TitleAs & {
142+ buttons : [ SocialButton , ...SocialButton [ ] ] ;
114143 } ;
115144}
116145
@@ -149,100 +178,113 @@ const FollowNewsletter = (
149178 </ p >
150179 ) }
151180 </ div >
152- </ div >
153- { form !== undefined
154- ? ( ( ) => {
155- const {
156- success,
157- consentHint,
158- formComponent,
159- inputProps,
160- successMessage = t ( "your registration has been processed" ) ,
161- ...restForm
162- } = form ;
163- assert < Equals < keyof typeof restForm , never > > ( ) ;
164-
165- if ( success )
166- return (
167- < Alert
168- severity = "success"
169- description = { successMessage }
170- title = {
171- // force default size without title
172- undefined as unknown as string
173- }
174- />
175- ) ;
176-
177- // prepare inputProps with default values
178- const {
179- label : inputLabel = t ( "your email address" ) ,
180- hintText : inputHintText = consentHint ?? t ( "consent hint" ) ,
181- nativeInputProps : {
182- title : inputTitle = t ( "your email address" ) ,
183- placeholder : inputPlaceholder = t ( "your email address" ) ,
184- autoComplete : inputAutoComplete = "email" ,
185- type : inputType = "email" ,
186- ...nativeInputProps
187- } = { } ,
188- ...restInputProps
189- } = inputProps ;
190-
191- // prepare buttonProps with default values
192- const {
193- children : buttonContent = t ( "subscribe" ) ,
194- title : buttonTitle = t ( "subscribe to our newsletter (2)" ) ,
195- type : buttonType = "button" ,
196- ...restButtonProps
197- } = buttonProps ;
198-
199- // use wrapper to add form
200- return formComponent ( {
201- children : (
202- < Input
203- label = { inputLabel }
204- hintText = { inputHintText }
205- nativeInputProps = { {
206- title : inputTitle ,
207- placeholder : inputPlaceholder ,
208- autoComplete : inputAutoComplete ,
209- type : inputType ,
181+ < div >
182+ { form !== undefined
183+ ? ( ( ) => {
184+ const {
185+ success,
186+ consentHint = t ( "consent hint" ) ,
187+ formComponent,
188+ inputProps = { } ,
189+ successMessage = t ( "your registration has been processed" ) ,
190+ ...restForm
191+ } = form ;
192+ assert < Equals < keyof typeof restForm , never > > ( ) ;
193+
194+ if ( success )
195+ return (
196+ < Alert
197+ severity = "success"
198+ description = { successMessage }
199+ title = {
200+ // force default size without title
201+ undefined as unknown as string
202+ }
203+ />
204+ ) ;
205+
206+ // prepare inputProps with default values
207+ const {
208+ label : inputLabel = t ( "your email address" ) ,
209+ hintText : inputHintText = consentHint ,
210+ nativeInputProps : {
211+ title : inputTitle = t ( "your email address" ) ,
212+ placeholder : inputPlaceholder = t ( "your email address" ) ,
213+ autoComplete : inputAutoComplete = "email" ,
214+ type : inputType = "email" ,
210215 ...nativeInputProps
211- } }
212- { ...restInputProps }
213- addon = {
214- < Button
215- { ...restButtonProps }
216- title = { buttonTitle }
217- type = { buttonType }
218- >
219- { buttonContent }
220- </ Button >
221- }
222- />
223- )
224- } ) ;
225- } ) ( )
226- : ( ( ) => {
227- const {
228- children : buttonContent = t ( "subscribe" ) ,
229- title : buttonTitle = t ( "subscribe to our newsletter (2)" ) ,
230- ...restButtonProps
231- } = buttonProps ;
232-
233- return (
234- < ButtonsGroup
235- inlineLayoutWhen = "md and up"
236- buttons = { [
237- {
238- children : buttonContent ,
239- title : buttonTitle ,
240- ...restButtonProps
241- }
242- ] }
243- />
244- ) ;
245- } ) ( ) }
216+ } = { } ,
217+ ...restInputProps
218+ } = inputProps ;
219+
220+ // prepare buttonProps with default values
221+ const {
222+ children : buttonContent = t ( "subscribe" ) ,
223+ title : buttonTitle = t ( "subscribe to our newsletter (2)" ) ,
224+ type : buttonType = "button" ,
225+ ...restButtonProps
226+ } = buttonProps ;
227+
228+ // use wrapper to add form
229+ return formComponent ( {
230+ children : (
231+ < >
232+ < Input
233+ label = { inputLabel }
234+ nativeInputProps = { {
235+ title : inputTitle ,
236+ placeholder : inputPlaceholder ,
237+ autoComplete : inputAutoComplete ,
238+ type : inputType ,
239+ ...nativeInputProps
240+ } }
241+ { ...restInputProps }
242+ addon = {
243+ < Button
244+ { ...restButtonProps }
245+ title = { buttonTitle }
246+ type = { buttonType }
247+ >
248+ { buttonContent }
249+ </ Button >
250+ }
251+ />
252+ { inputHintText !== undefined && (
253+ < p
254+ className = { cx (
255+ fr . cx ( "fr-hint-text" ) ,
256+ classes [ "newsletter-form-hint" ]
257+ ) }
258+ >
259+ { inputHintText }
260+ </ p >
261+ ) }
262+ </ >
263+ )
264+ } ) ;
265+ } ) ( )
266+ : ( ( ) => {
267+ const {
268+ children : buttonContent = t ( "subscribe" ) ,
269+ title : buttonTitle = t ( "subscribe to our newsletter (2)" ) ,
270+ ...restButtonProps
271+ } = buttonProps ;
272+
273+ return (
274+ < ButtonsGroup
275+ inlineLayoutWhen = "md and up"
276+ buttons = { [
277+ {
278+ children : buttonContent ,
279+ title : buttonTitle ,
280+ ...restButtonProps
281+ }
282+ ] }
283+ />
284+ ) ;
285+ } ) ( ) }
286+ </ div >
287+ </ div >
246288 </ div >
247289 ) ;
248290} ;
0 commit comments