@@ -21,27 +21,35 @@ import {useModalDismissSignal} from './hooks';
21
21
22
22
import styles from './ModalDialog.css' ;
23
23
24
+ type ID = any ;
25
+
24
26
type DIALOG_ACTION_HIDE = { |
25
27
type : 'HIDE' ,
28
+ id : ID ,
26
29
| } ;
27
30
type DIALOG_ACTION_SHOW = { |
28
31
type : 'SHOW' ,
29
32
canBeDismissed ?: boolean ,
30
33
content : React$Node ,
34
+ id : ID ,
31
35
title ?: React$Node | null ,
32
36
| } ;
33
37
34
38
type Action = DIALOG_ACTION_HIDE | DIALOG_ACTION_SHOW ;
35
39
36
40
type Dispatch = ( action : Action ) => void ;
37
41
38
- type State = { |
42
+ type Dialog = { |
39
43
canBeDismissed : boolean ,
40
44
content : React$Node | null ,
41
- isVisible : boolean ,
45
+ id : ID ,
42
46
title : React$Node | null ,
43
47
| } ;
44
48
49
+ type State = { |
50
+ dialogs : Array < Dialog > ,
51
+ | } ;
52
+
45
53
type ModalDialogContextType = { |
46
54
...State ,
47
55
dispatch : Dispatch ,
@@ -56,17 +64,19 @@ function dialogReducer(state, action) {
56
64
switch ( action . type ) {
57
65
case 'HIDE' :
58
66
return {
59
- canBeDismissed : true ,
60
- content : null ,
61
- isVisible : false ,
62
- title : null ,
67
+ dialogs : state . dialogs . filter ( dialog => dialog . id !== action . id ) ,
63
68
} ;
64
69
case 'SHOW' :
65
70
return {
66
- canBeDismissed : action . canBeDismissed !== false ,
67
- content : action . content ,
68
- isVisible : true ,
69
- title : action . title || null ,
71
+ dialogs : [
72
+ ...state . dialogs ,
73
+ {
74
+ canBeDismissed : action . canBeDismissed !== false ,
75
+ content : action . content ,
76
+ id : action . id ,
77
+ title : action . title || null ,
78
+ } ,
79
+ ] ,
70
80
} ;
71
81
default :
72
82
throw new Error ( `Invalid action "${ action . type } "` ) ;
@@ -79,18 +89,12 @@ type Props = {|
79
89
80
90
function ModalDialogContextController ( { children} : Props ) {
81
91
const [ state , dispatch ] = useReducer < State , State , Action > ( dialogReducer , {
82
- canBeDismissed : true ,
83
- content : null ,
84
- isVisible : false ,
85
- title : null ,
92
+ dialogs : [ ] ,
86
93
} ) ;
87
94
88
95
const value = useMemo < ModalDialogContextType > (
89
96
( ) => ( {
90
- canBeDismissed : state . canBeDismissed ,
91
- content : state . content ,
92
- isVisible : state . isVisible ,
93
- title : state . title ,
97
+ dialogs : state . dialogs ,
94
98
dispatch,
95
99
} ) ,
96
100
[ state , dispatch ] ,
@@ -104,17 +108,44 @@ function ModalDialogContextController({children}: Props) {
104
108
}
105
109
106
110
function ModalDialog ( _ : { || } ) {
107
- const { isVisible } = useContext ( ModalDialogContext ) ;
108
- return isVisible ? < ModalDialogImpl / > : null ;
109
- }
111
+ const { dialogs, dispatch} = useContext ( ModalDialogContext ) ;
112
+
113
+ if ( dialogs . length === 0 ) {
114
+ return null ;
115
+ }
110
116
111
- function ModalDialogImpl ( _ : { || } ) {
112
- const { canBeDismissed, content, dispatch, title} = useContext (
113
- ModalDialogContext ,
117
+ return (
118
+ < div className = { styles . Background } >
119
+ { dialogs . map ( dialog => (
120
+ < ModalDialogImpl
121
+ key = { dialog . id }
122
+ canBeDismissed = { dialog . canBeDismissed }
123
+ content = { dialog . content }
124
+ dispatch = { dispatch }
125
+ id = { dialog . id }
126
+ title = { dialog . title }
127
+ />
128
+ ) ) }
129
+ </ div >
114
130
) ;
131
+ }
132
+
133
+ function ModalDialogImpl ( {
134
+ canBeDismissed,
135
+ content,
136
+ dispatch,
137
+ id,
138
+ title,
139
+ } : { |
140
+ canBeDismissed : boolean ,
141
+ content : React$Node | null ,
142
+ dispatch : Dispatch ,
143
+ id : ID ,
144
+ title : React$Node | null ,
145
+ | } ) {
115
146
const dismissModal = useCallback ( ( ) => {
116
147
if ( canBeDismissed ) {
117
- dispatch ( { type : 'HIDE' } ) ;
148
+ dispatch ( { type : 'HIDE' , id } ) ;
118
149
}
119
150
} , [ canBeDismissed , dispatch ] ) ;
120
151
const dialogRef = useRef < HTMLDivElement | null > ( null ) ;
@@ -135,24 +166,19 @@ function ModalDialogImpl(_: {||}) {
135
166
} ;
136
167
137
168
return (
138
- < div className = { styles . Background } onClick = { dismissModal } >
139
- < div
140
- ref = { dialogRef }
141
- className = { styles . Dialog }
142
- onClick = { handleDialogClick } >
143
- { title !== null && < div className = { styles . Title } > { title } </ div > }
144
- { content }
145
- { canBeDismissed && (
146
- < div className = { styles . Buttons } >
147
- < Button
148
- autoFocus = { true }
149
- className = { styles . Button }
150
- onClick = { dismissModal } >
151
- Okay
152
- </ Button >
153
- </ div >
154
- ) }
155
- </ div >
169
+ < div ref = { dialogRef } className = { styles . Dialog } onClick = { handleDialogClick } >
170
+ { title !== null && < div className = { styles . Title } > { title } </ div > }
171
+ { content }
172
+ { canBeDismissed && (
173
+ < div className = { styles . Buttons } >
174
+ < Button
175
+ autoFocus = { true }
176
+ className = { styles . Button }
177
+ onClick = { dismissModal } >
178
+ Okay
179
+ </ Button >
180
+ </ div >
181
+ ) }
156
182
</ div >
157
183
) ;
158
184
}
0 commit comments