@@ -72,6 +72,10 @@ export interface CModalProps extends HTMLAttributes<HTMLDivElement> {
72
72
* Remove animation to create modal that simply appear rather than fade in to view.
73
73
*/
74
74
transition ?: boolean
75
+ /*
76
+ * By default the component is unmounted after close animation, if you want to keep the component mounted set this property to false
77
+ */
78
+ unmountOnClose ?: boolean
75
79
/**
76
80
* Toggle the visibility of modal component.
77
81
*/
@@ -102,11 +106,13 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
102
106
scrollable,
103
107
size,
104
108
transition = true ,
109
+ unmountOnClose = true ,
105
110
visible,
106
111
} ,
107
112
ref ,
108
113
) => {
109
114
const modalRef = useRef < HTMLDivElement > ( null )
115
+ const modalContentRef = useRef < HTMLDivElement > ( null )
110
116
const forkedRef = useForkedRef ( ref , modalRef )
111
117
112
118
const [ _visible , setVisible ] = useState ( visible )
@@ -121,6 +127,16 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
121
127
setVisible,
122
128
}
123
129
130
+ useEffect ( ( ) => {
131
+ modalRef . current && modalRef . current . addEventListener ( 'click' , handleClickOutside )
132
+ modalRef . current && modalRef . current . addEventListener ( 'keyup' , handleKeyDown )
133
+
134
+ return ( ) => {
135
+ modalRef . current && modalRef . current . removeEventListener ( 'click' , handleClickOutside )
136
+ modalRef . current && modalRef . current . removeEventListener ( 'keyup' , handleKeyDown )
137
+ }
138
+ } , [ _visible ] )
139
+
124
140
const handleDismiss = ( ) => {
125
141
if ( backdrop === 'static' ) {
126
142
return setStaticBackdrop ( true )
@@ -167,6 +183,15 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
167
183
return ( ) => document . body . classList . remove ( 'modal-open' )
168
184
} , [ _visible ] )
169
185
186
+ const handleClickOutside = ( event : Event ) => {
187
+ if (
188
+ modalContentRef . current &&
189
+ ! modalContentRef . current . contains ( event . target as HTMLElement )
190
+ ) {
191
+ handleDismiss ( )
192
+ }
193
+ }
194
+
170
195
const handleKeyDown = useCallback (
171
196
( event ) => {
172
197
if ( event . key === 'Escape' && keyboard ) {
@@ -190,9 +215,8 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
190
215
fullscreen = { fullscreen }
191
216
scrollable = { scrollable }
192
217
size = { size }
193
- onClick = { ( event ) => event . stopPropagation ( ) }
194
218
>
195
- < CModalContent > { children } </ CModalContent >
219
+ < CModalContent ref = { modalContentRef } > { children } </ CModalContent >
196
220
</ CModalDialog >
197
221
</ div >
198
222
</ CModalContext . Provider >
@@ -201,23 +225,21 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
201
225
202
226
return (
203
227
< >
204
- < div onClick = { handleDismiss } onKeyDown = { handleKeyDown } >
205
- < Transition
206
- in = { _visible }
207
- mountOnEnter
208
- onEnter = { onShow }
209
- onExit = { onClose }
210
- unmountOnExit
211
- timeout = { ! transition ? 0 : duration }
212
- >
213
- { ( state ) => {
214
- const transitionClass = getTransitionClass ( state )
215
- return typeof window !== 'undefined' && portal
216
- ? createPortal ( modal ( forkedRef , transitionClass ) , document . body )
217
- : modal ( forkedRef , transitionClass )
218
- } }
219
- </ Transition >
220
- </ div >
228
+ < Transition
229
+ in = { _visible }
230
+ mountOnEnter
231
+ onEnter = { onShow }
232
+ onExit = { onClose }
233
+ unmountOnExit = { unmountOnClose }
234
+ timeout = { ! transition ? 0 : duration }
235
+ >
236
+ { ( state ) => {
237
+ const transitionClass = getTransitionClass ( state )
238
+ return typeof window !== 'undefined' && portal
239
+ ? createPortal ( modal ( forkedRef , transitionClass ) , document . body )
240
+ : modal ( forkedRef , transitionClass )
241
+ } }
242
+ </ Transition >
221
243
{ typeof window !== 'undefined' && portal
222
244
? backdrop && createPortal ( < CBackdrop visible = { _visible } /> , document . body )
223
245
: backdrop && < CBackdrop visible = { _visible } /> }
@@ -244,6 +266,7 @@ CModal.propTypes = {
244
266
scrollable : PropTypes . bool ,
245
267
size : PropTypes . oneOf ( [ 'sm' , 'lg' , 'xl' ] ) ,
246
268
transition : PropTypes . bool ,
269
+ unmountOnClose : PropTypes . bool ,
247
270
visible : PropTypes . bool ,
248
271
}
249
272
0 commit comments