1- import React , { memo , ForwardedRef } from "react" ;
1+ import React , { memo , forwardRef } from "react" ;
22import { fr } from "./fr" ;
33import { cx } from "./tools/cx" ;
44import type { ReactNode } from "react" ;
@@ -19,7 +19,6 @@ export type ModalProps = {
1919 /** Default: true */
2020 concealingBackdrop ?: boolean ;
2121 topAnchor ?: boolean ;
22- ref ?: ForwardedRef < HTMLDialogElement > ;
2322 iconId ?: FrIconClassName | RiIconClassName ;
2423 buttons ?:
2524 | [ ModalProps . ActionAreaButtonProps , ...ModalProps . ActionAreaButtonProps [ ] ]
@@ -33,126 +32,134 @@ export namespace ModalProps {
3332 } ;
3433}
3534
36- const Modal = memo ( ( props : ModalProps & { id : string } ) => {
37- const {
38- className,
39- id,
40- title,
41- children,
42- concealingBackdrop = true ,
43- topAnchor = false ,
44- ref,
45- iconId,
46- buttons : buttons_props ,
47- size = "medium" ,
48- ...rest
49- } = props ;
50-
51- assert < Equals < keyof typeof rest , never > > ( ) ;
52-
53- const buttons =
54- buttons_props === undefined
55- ? undefined
56- : buttons_props instanceof Array
57- ? buttons_props
58- : [ buttons_props ] ;
59-
60- const { t } = useTranslation ( ) ;
61-
62- return (
63- < dialog
64- aria-labelledby = "fr-modal-title-modal-1"
65- role = "dialog"
66- id = { id }
67- className = { cx ( fr . cx ( "fr-modal" , topAnchor && "fr-modal--top" ) , className ) }
68- ref = { ref }
69- data-fr-concealing-backdrop = { concealingBackdrop }
70- >
71- < div className = { fr . cx ( "fr-container" , "fr-container--fluid" , "fr-container-md" ) } >
72- < div className = { fr . cx ( "fr-grid-row" , "fr-grid-row--center" ) } >
73- < div
74- className = { ( ( ) => {
75- switch ( size ) {
76- case "large" :
77- return fr . cx ( "fr-col-12" , "fr-col-md-10" , "fr-col-lg-8" ) ;
78- case "small" :
79- return fr . cx ( "fr-col-12" , "fr-col-md-6" , "fr-col-lg-4" ) ;
80- case "medium" :
81- return fr . cx ( "fr-col-12" , "fr-col-md-8" , "fr-col-lg-6" ) ;
82- }
83- } ) ( ) }
84- >
85- < div className = { fr . cx ( "fr-modal__body" ) } >
86- < div className = { fr . cx ( "fr-modal__header" ) } >
87- < button
88- className = { fr . cx ( "fr-link--close" , "fr-link" ) }
89- title = { t ( "close" ) }
90- aria-controls = { id }
91- >
92- { t ( "close" ) }
93- </ button >
94- </ div >
95- < div className = { fr . cx ( "fr-modal__content" ) } >
96- < h1
97- id = "fr-modal-title-modal-1"
98- className = { fr . cx ( "fr-modal__title" ) }
99- >
100- { iconId !== undefined && (
101- < span className = { fr . cx ( iconId , "fr-fi--lg" ) } />
102- ) }
103- { title }
104- </ h1 >
105- { children }
106- </ div >
107- { buttons !== undefined && (
108- < div className = "fr-modal__footer" >
109- < ul
110- className = { fr . cx (
111- "fr-btns-group" ,
112- "fr-btns-group--right" ,
113- "fr-btns-group--inline-reverse" ,
114- "fr-btns-group--inline-lg" ,
115- "fr-btns-group--icon-left"
116- ) }
35+ const Modal = memo (
36+ forwardRef < HTMLDialogElement , ModalProps & { id : string } > ( ( props , ref ) => {
37+ const {
38+ className,
39+ id,
40+ title,
41+ children,
42+ concealingBackdrop = true ,
43+ topAnchor = false ,
44+ iconId,
45+ buttons : buttons_props ,
46+ size = "medium" ,
47+ ...rest
48+ } = props ;
49+
50+ assert < Equals < keyof typeof rest , never > > ( ) ;
51+
52+ const buttons =
53+ buttons_props === undefined
54+ ? undefined
55+ : buttons_props instanceof Array
56+ ? buttons_props
57+ : [ buttons_props ] ;
58+
59+ const { t } = useTranslation ( ) ;
60+
61+ return (
62+ < dialog
63+ aria-labelledby = "fr-modal-title-modal-1"
64+ role = "dialog"
65+ id = { id }
66+ className = { cx ( fr . cx ( "fr-modal" , topAnchor && "fr-modal--top" ) , className ) }
67+ ref = { ref }
68+ data-fr-concealing-backdrop = { concealingBackdrop }
69+ >
70+ < div className = { fr . cx ( "fr-container" , "fr-container--fluid" , "fr-container-md" ) } >
71+ < div className = { fr . cx ( "fr-grid-row" , "fr-grid-row--center" ) } >
72+ < div
73+ className = { ( ( ) => {
74+ switch ( size ) {
75+ case "large" :
76+ return fr . cx ( "fr-col-12" , "fr-col-md-10" , "fr-col-lg-8" ) ;
77+ case "small" :
78+ return fr . cx ( "fr-col-12" , "fr-col-md-6" , "fr-col-lg-4" ) ;
79+ case "medium" :
80+ return fr . cx ( "fr-col-12" , "fr-col-md-8" , "fr-col-lg-6" ) ;
81+ }
82+ } ) ( ) }
83+ >
84+ < div className = { fr . cx ( "fr-modal__body" ) } >
85+ < div className = { fr . cx ( "fr-modal__header" ) } >
86+ < button
87+ className = { fr . cx ( "fr-link--close" , "fr-link" ) }
88+ title = { t ( "close" ) }
89+ aria-controls = { id }
11790 >
118- { [ ...buttons ]
119- . reverse ( )
120- . map ( ( { doClosesModal = true , ...buttonProps } , i ) => (
121- < li key = { i } >
122- < Button
123- { ...buttonProps }
124- priority = {
125- buttonProps . priority ??
126- ( i === 0 ? "primary" : "secondary" )
127- }
128- { ...( ! doClosesModal
129- ? { }
130- : "linkProps" in buttonProps
131- ? {
132- "linkProps" : {
133- ...buttonProps . linkProps ,
134- "aria-controls" : id
135- } as any
136- }
137- : {
138- "nativeButtonProps" : {
139- ...buttonProps . nativeButtonProps ,
140- "aria-controls" : id
141- } as any
142- } ) }
143- />
144- </ li >
145- ) ) }
146- </ ul >
91+ { t ( "close" ) }
92+ </ button >
14793 </ div >
148- ) }
94+ < div className = { fr . cx ( "fr-modal__content" ) } >
95+ < h1
96+ id = "fr-modal-title-modal-1"
97+ className = { fr . cx ( "fr-modal__title" ) }
98+ >
99+ { iconId !== undefined && (
100+ < span className = { fr . cx ( iconId , "fr-fi--lg" ) } />
101+ ) }
102+ { title }
103+ </ h1 >
104+ { children }
105+ </ div >
106+ { buttons !== undefined && (
107+ < div className = "fr-modal__footer" >
108+ < ul
109+ className = { fr . cx (
110+ "fr-btns-group" ,
111+ "fr-btns-group--right" ,
112+ "fr-btns-group--inline-reverse" ,
113+ "fr-btns-group--inline-lg" ,
114+ "fr-btns-group--icon-left"
115+ ) }
116+ >
117+ { [ ...buttons ]
118+ . reverse ( )
119+ . map (
120+ (
121+ { doClosesModal = true , ...buttonProps } ,
122+ i
123+ ) => (
124+ < li key = { i } >
125+ < Button
126+ { ...buttonProps }
127+ priority = {
128+ buttonProps . priority ??
129+ ( i === 0
130+ ? "primary"
131+ : "secondary" )
132+ }
133+ { ...( ! doClosesModal
134+ ? { }
135+ : "linkProps" in buttonProps
136+ ? {
137+ "linkProps" : {
138+ ...buttonProps . linkProps ,
139+ "aria-controls" : id
140+ } as any
141+ }
142+ : {
143+ "nativeButtonProps" : {
144+ ...buttonProps . nativeButtonProps ,
145+ "aria-controls" : id
146+ } as any
147+ } ) }
148+ />
149+ </ li >
150+ )
151+ ) }
152+ </ ul >
153+ </ div >
154+ ) }
155+ </ div >
149156 </ div >
150157 </ div >
151158 </ div >
152- </ div >
153- </ dialog >
154- ) ;
155- } ) ;
159+ </ dialog >
160+ ) ;
161+ } )
162+ ) ;
156163
157164Modal . displayName = symToStr ( { Modal } ) ;
158165
0 commit comments