dce-reactkit 3.7.10 → 3.7.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +58 -27944
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/AppWrapper.d.ts +0 -21
- package/dist/cjs/types/components/Modal/index.d.ts +2 -1
- package/dist/cjs/types/constants/NUM_MODAL_PORTALS.d.ts +6 -0
- package/dist/esm/index.js +57 -27944
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/AppWrapper.d.ts +0 -21
- package/dist/esm/types/components/Modal/index.d.ts +2 -1
- package/dist/esm/types/constants/NUM_MODAL_PORTALS.d.ts +6 -0
- package/dist/index.d.ts +81 -80
- package/package.json +3 -2
- package/src/components/AppWrapper.tsx +14 -116
- package/src/components/IntelliTable.tsx +1 -1
- package/src/components/Modal/index.tsx +489 -36
- package/src/constants/NUM_MODAL_PORTALS.ts +7 -0
- package/dist/cjs/types/components/Modal/ModalForWrapper.d.ts +0 -9
- package/dist/esm/types/components/Modal/ModalForWrapper.d.ts +0 -9
- package/src/components/Modal/ModalForWrapper.tsx +0 -520
|
@@ -1,16 +1,151 @@
|
|
|
1
|
+
/* eslint-disable react/no-unused-prop-types */
|
|
2
|
+
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
3
|
+
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
4
|
+
/* eslint-disable react/destructuring-assignment */
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
|
-
*
|
|
7
|
+
* The displayable modal component (this is the modal that's added to the
|
|
8
|
+
* wrapper, not the one that the programmer renders)
|
|
3
9
|
* @author Gabe Abrams
|
|
4
10
|
*/
|
|
5
11
|
|
|
6
12
|
// Import React
|
|
7
|
-
import React, { useEffect, useRef } from 'react';
|
|
13
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
14
|
+
import ReactDOM from 'react-dom';
|
|
15
|
+
|
|
16
|
+
// Import other components
|
|
17
|
+
import waitMs from '../../helpers/waitMs';
|
|
8
18
|
|
|
9
|
-
// Import
|
|
19
|
+
// Import types
|
|
20
|
+
import Variant from '../../types/Variant';
|
|
21
|
+
import ModalButtonType from '../../types/ModalButtonType';
|
|
22
|
+
import ModalSize from '../../types/ModalSize';
|
|
23
|
+
import ModalType from '../../types/ModalType';
|
|
10
24
|
import ModalProps from './ModalProps';
|
|
11
25
|
|
|
12
|
-
// Import
|
|
13
|
-
import
|
|
26
|
+
// Import constants
|
|
27
|
+
import NUM_MODAL_PORTALS from '../../constants/NUM_MODAL_PORTALS';
|
|
28
|
+
|
|
29
|
+
// Import shared helpers
|
|
30
|
+
// TODO: fix dependency cycle
|
|
31
|
+
// eslint-disable-next-line import/no-cycle
|
|
32
|
+
import { isDarkModeOn } from '../../client/initClient';
|
|
33
|
+
|
|
34
|
+
/*------------------------------------------------------------------------*/
|
|
35
|
+
/* ------------------------------ Constants ----------------------------- */
|
|
36
|
+
/*------------------------------------------------------------------------*/
|
|
37
|
+
|
|
38
|
+
// Base level of z-index
|
|
39
|
+
const BASE_Z_INDEX = 1000000000;
|
|
40
|
+
const BASE_Z_INDEX_ON_TOP = 2000000000;
|
|
41
|
+
|
|
42
|
+
// Constants
|
|
43
|
+
const MS_TO_ANIMATE = 200; // Animation duration
|
|
44
|
+
|
|
45
|
+
// Modal type to list of buttons
|
|
46
|
+
const modalTypeToModalButtonTypes: {
|
|
47
|
+
[k: string]: ModalButtonType[]
|
|
48
|
+
} = {
|
|
49
|
+
[ModalType.Okay]: [
|
|
50
|
+
ModalButtonType.Okay,
|
|
51
|
+
],
|
|
52
|
+
[ModalType.OkayCancel]: [
|
|
53
|
+
ModalButtonType.Okay,
|
|
54
|
+
ModalButtonType.Cancel,
|
|
55
|
+
],
|
|
56
|
+
[ModalType.YesNo]: [
|
|
57
|
+
ModalButtonType.Yes,
|
|
58
|
+
ModalButtonType.No,
|
|
59
|
+
],
|
|
60
|
+
[ModalType.YesNoCancel]: [
|
|
61
|
+
ModalButtonType.Yes,
|
|
62
|
+
ModalButtonType.No,
|
|
63
|
+
ModalButtonType.Cancel,
|
|
64
|
+
],
|
|
65
|
+
[ModalType.AbandonGoBack]: [
|
|
66
|
+
ModalButtonType.Abandon,
|
|
67
|
+
ModalButtonType.GoBack,
|
|
68
|
+
],
|
|
69
|
+
[ModalType.ImSureCancel]: [
|
|
70
|
+
ModalButtonType.ImSure,
|
|
71
|
+
ModalButtonType.Cancel,
|
|
72
|
+
],
|
|
73
|
+
[ModalType.DeleteCancel]: [
|
|
74
|
+
ModalButtonType.Delete,
|
|
75
|
+
ModalButtonType.Cancel,
|
|
76
|
+
],
|
|
77
|
+
[ModalType.ConfirmCancel]: [
|
|
78
|
+
ModalButtonType.Confirm,
|
|
79
|
+
ModalButtonType.Cancel,
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get button type styling and labels
|
|
85
|
+
* @author Gabe Abrams
|
|
86
|
+
* @returns map of button type to label and variant
|
|
87
|
+
*/
|
|
88
|
+
const getModalButtonTypeToLabelAndVariant = () => {
|
|
89
|
+
const dark = isDarkModeOn();
|
|
90
|
+
return {
|
|
91
|
+
[ModalButtonType.Okay]: {
|
|
92
|
+
label: 'Okay',
|
|
93
|
+
variant: (
|
|
94
|
+
dark
|
|
95
|
+
? Variant.Light
|
|
96
|
+
: Variant.Dark
|
|
97
|
+
),
|
|
98
|
+
},
|
|
99
|
+
[ModalButtonType.Cancel]: {
|
|
100
|
+
label: 'Cancel',
|
|
101
|
+
variant: Variant.Secondary,
|
|
102
|
+
},
|
|
103
|
+
[ModalButtonType.Yes]: {
|
|
104
|
+
label: 'Yes',
|
|
105
|
+
variant: (
|
|
106
|
+
dark
|
|
107
|
+
? Variant.Light
|
|
108
|
+
: Variant.Dark
|
|
109
|
+
),
|
|
110
|
+
},
|
|
111
|
+
[ModalButtonType.No]: {
|
|
112
|
+
label: 'No',
|
|
113
|
+
variant: Variant.Secondary,
|
|
114
|
+
},
|
|
115
|
+
[ModalButtonType.Abandon]: {
|
|
116
|
+
label: 'Abandon Changes',
|
|
117
|
+
variant: Variant.Warning,
|
|
118
|
+
},
|
|
119
|
+
[ModalButtonType.GoBack]: {
|
|
120
|
+
label: 'Go Back',
|
|
121
|
+
variant: Variant.Secondary,
|
|
122
|
+
},
|
|
123
|
+
[ModalButtonType.Continue]: {
|
|
124
|
+
label: 'Continue',
|
|
125
|
+
variant: (
|
|
126
|
+
dark
|
|
127
|
+
? Variant.Light
|
|
128
|
+
: Variant.Dark
|
|
129
|
+
),
|
|
130
|
+
},
|
|
131
|
+
[ModalButtonType.ImSure]: {
|
|
132
|
+
label: 'I am sure',
|
|
133
|
+
variant: Variant.Warning,
|
|
134
|
+
},
|
|
135
|
+
[ModalButtonType.Delete]: {
|
|
136
|
+
label: 'Yes, Delete',
|
|
137
|
+
variant: Variant.Danger,
|
|
138
|
+
},
|
|
139
|
+
[ModalButtonType.Confirm]: {
|
|
140
|
+
label: 'Confirm',
|
|
141
|
+
variant: (
|
|
142
|
+
dark
|
|
143
|
+
? Variant.Light
|
|
144
|
+
: Variant.Dark
|
|
145
|
+
),
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
};
|
|
14
149
|
|
|
15
150
|
/*------------------------------------------------------------------------*/
|
|
16
151
|
/* --------------------------- Static Helpers --------------------------- */
|
|
@@ -29,6 +164,74 @@ const getNextUniqueId = (): number => {
|
|
|
29
164
|
return nextUniqueId++;
|
|
30
165
|
};
|
|
31
166
|
|
|
167
|
+
/*------------------------------------------------------------------------*/
|
|
168
|
+
/* -------------------------------- Style ------------------------------- */
|
|
169
|
+
/*------------------------------------------------------------------------*/
|
|
170
|
+
|
|
171
|
+
const style = `
|
|
172
|
+
.Modal-backdrop {
|
|
173
|
+
position: fixed;
|
|
174
|
+
top: 0;
|
|
175
|
+
left: 0;
|
|
176
|
+
width: 100vw;
|
|
177
|
+
height: 200vh;
|
|
178
|
+
background-color: rgba(0, 0, 0, 0.7);
|
|
179
|
+
}
|
|
180
|
+
.Modal-fading-in {
|
|
181
|
+
animation-name: Modal-fading-in;
|
|
182
|
+
animation-duration: ${Math.floor(MS_TO_ANIMATE * 2)}ms;
|
|
183
|
+
animation-iteration-count: 1;
|
|
184
|
+
animation-fill-mode: both;
|
|
185
|
+
animation-timing-function: ease-out;
|
|
186
|
+
}
|
|
187
|
+
@keyframes Modal-fading-in {
|
|
188
|
+
0% {
|
|
189
|
+
opacity: 0;
|
|
190
|
+
}
|
|
191
|
+
100% {
|
|
192
|
+
opacity: 1;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
.Modal-animating-in {
|
|
196
|
+
animation-name: Modal-animating-in;
|
|
197
|
+
animation-duration: ${MS_TO_ANIMATE}ms;
|
|
198
|
+
animation-iteration-count: 1;
|
|
199
|
+
animation-fill-mode: both;
|
|
200
|
+
animation-timing-function: ease-out;
|
|
201
|
+
}
|
|
202
|
+
@keyframes Modal-animating-in {
|
|
203
|
+
0% {
|
|
204
|
+
transform: scale(1.05) translate(0, -1.5rem);
|
|
205
|
+
opacity: 0;
|
|
206
|
+
}
|
|
207
|
+
100% {
|
|
208
|
+
transform: scale(1) translate(0, 0);
|
|
209
|
+
opacity: 1;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
.Modal-animating-pop {
|
|
213
|
+
animation-name: Modal-animating-pop;
|
|
214
|
+
animation-duration: ${MS_TO_ANIMATE}ms;
|
|
215
|
+
animation-iteration-count: 1;
|
|
216
|
+
animation-fill-mode: both;
|
|
217
|
+
animation-timing-function: ease-in-out;
|
|
218
|
+
}
|
|
219
|
+
@keyframes Modal-animating-pop {
|
|
220
|
+
0% {
|
|
221
|
+
transform: scale(1);
|
|
222
|
+
opacity: 1;
|
|
223
|
+
}
|
|
224
|
+
50% {
|
|
225
|
+
transform: scale(1.05);
|
|
226
|
+
opacity: 0.9;
|
|
227
|
+
}
|
|
228
|
+
100% {
|
|
229
|
+
transform: scale(1);
|
|
230
|
+
opacity: 1;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
`;
|
|
234
|
+
|
|
32
235
|
/*------------------------------------------------------------------------*/
|
|
33
236
|
/* ------------------------------ Component ----------------------------- */
|
|
34
237
|
/*------------------------------------------------------------------------*/
|
|
@@ -38,62 +241,313 @@ const Modal: React.FC<ModalProps> = (props) => {
|
|
|
38
241
|
/* -------------------------------- Setup ------------------------------- */
|
|
39
242
|
/*------------------------------------------------------------------------*/
|
|
40
243
|
|
|
244
|
+
/* -------------- Props ------------- */
|
|
245
|
+
|
|
246
|
+
const {
|
|
247
|
+
type = ModalType.NoButtons,
|
|
248
|
+
size = ModalSize.Large,
|
|
249
|
+
title,
|
|
250
|
+
children,
|
|
251
|
+
onClose,
|
|
252
|
+
dontAllowBackdropExit,
|
|
253
|
+
dontShowXButton,
|
|
254
|
+
onTopOfOtherModals,
|
|
255
|
+
} = props;
|
|
256
|
+
|
|
257
|
+
/* -------------- State ------------- */
|
|
258
|
+
|
|
259
|
+
// True if animation is in use
|
|
260
|
+
const [animatingIn, setAnimatingIn] = useState(true);
|
|
261
|
+
const [animatingPop, setAnimatingPop] = useState(false);
|
|
262
|
+
|
|
41
263
|
/* -------------- Refs -------------- */
|
|
42
264
|
|
|
43
|
-
//
|
|
44
|
-
const
|
|
265
|
+
// Keep track of whether modal is still mounted
|
|
266
|
+
const mounted = useRef(false);
|
|
267
|
+
|
|
268
|
+
// Keep track of unique modal id
|
|
269
|
+
const id = useRef<number>(0);
|
|
270
|
+
if (!id.current) {
|
|
271
|
+
id.current = getNextUniqueId();
|
|
272
|
+
}
|
|
45
273
|
|
|
46
274
|
/*------------------------------------------------------------------------*/
|
|
47
275
|
/* ------------------------- Lifecycle Functions ------------------------ */
|
|
48
276
|
/*------------------------------------------------------------------------*/
|
|
49
277
|
|
|
50
278
|
/**
|
|
51
|
-
* Mount
|
|
279
|
+
* Mount
|
|
52
280
|
* @author Gabe Abrams
|
|
53
281
|
*/
|
|
54
282
|
useEffect(
|
|
55
283
|
() => {
|
|
56
|
-
|
|
284
|
+
(async () => {
|
|
285
|
+
// Set defaults
|
|
286
|
+
setAnimatingIn(true);
|
|
287
|
+
setAnimatingPop(false);
|
|
288
|
+
// Wait for animation
|
|
289
|
+
await waitMs(MS_TO_ANIMATE);
|
|
290
|
+
// Update to state after animated in
|
|
291
|
+
if (mounted.current) {
|
|
292
|
+
setAnimatingIn(false);
|
|
293
|
+
}
|
|
294
|
+
})();
|
|
295
|
+
|
|
296
|
+
return () => {
|
|
297
|
+
mounted.current = false;
|
|
298
|
+
};
|
|
57
299
|
},
|
|
58
300
|
[],
|
|
59
301
|
);
|
|
60
302
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*/
|
|
65
|
-
useEffect(
|
|
66
|
-
() => {
|
|
67
|
-
// Update modal props
|
|
68
|
-
updateModal(id.current, props);
|
|
69
|
-
},
|
|
70
|
-
[props],
|
|
71
|
-
);
|
|
303
|
+
/*------------------------------------------------------------------------*/
|
|
304
|
+
/* ------------------------- Component Functions ------------------------ */
|
|
305
|
+
/*------------------------------------------------------------------------*/
|
|
72
306
|
|
|
73
307
|
/**
|
|
74
|
-
*
|
|
308
|
+
* Handles the closing of the modal
|
|
75
309
|
* @author Gabe Abrams
|
|
310
|
+
* @param modalButtonType the button that was clicked when closing the
|
|
311
|
+
* modal
|
|
76
312
|
*/
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
);
|
|
313
|
+
const handleClose = async (modalButtonType: ModalButtonType) => {
|
|
314
|
+
// Don't close if no handler
|
|
315
|
+
if (!onClose) {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
onClose(modalButtonType);
|
|
320
|
+
};
|
|
86
321
|
|
|
87
322
|
/*------------------------------------------------------------------------*/
|
|
88
323
|
/* ------------------------------- Render ------------------------------- */
|
|
89
324
|
/*------------------------------------------------------------------------*/
|
|
90
325
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
326
|
+
// Calculate Z-index
|
|
327
|
+
const baseZIndex = (
|
|
328
|
+
onTopOfOtherModals
|
|
329
|
+
? BASE_Z_INDEX_ON_TOP
|
|
330
|
+
: BASE_Z_INDEX
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
// Get list of buttons for this modal type
|
|
334
|
+
const ModalButtonTypes: ModalButtonType[] = modalTypeToModalButtonTypes[type] ?? [];
|
|
335
|
+
|
|
336
|
+
// Get map of button type to label and variant
|
|
337
|
+
const ModalButtonTypeToLabelAndVariant = getModalButtonTypeToLabelAndVariant();
|
|
338
|
+
|
|
339
|
+
// Create buttons
|
|
340
|
+
const buttons = ModalButtonTypes.map((modalButtonType: ModalButtonType, i) => {
|
|
341
|
+
// Get default style
|
|
342
|
+
let {
|
|
343
|
+
label,
|
|
344
|
+
variant,
|
|
345
|
+
} = ModalButtonTypeToLabelAndVariant[modalButtonType];
|
|
346
|
+
|
|
347
|
+
// Override with customizations
|
|
348
|
+
const newLabel = props[`${modalButtonType}Label`];
|
|
349
|
+
if (newLabel) {
|
|
350
|
+
label = newLabel;
|
|
351
|
+
}
|
|
352
|
+
const newVariant = props[`${modalButtonType}Variant`];
|
|
353
|
+
if (newVariant) {
|
|
354
|
+
variant = newVariant;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Check if this button is last
|
|
358
|
+
const last = (i === ModalButtonTypes.length - 1);
|
|
359
|
+
|
|
360
|
+
// Create the button
|
|
361
|
+
return (
|
|
362
|
+
<button
|
|
363
|
+
key={modalButtonType}
|
|
364
|
+
type="button"
|
|
365
|
+
className={`Modal-${modalButtonType}-button btn btn-${variant} ${last ? '' : 'me-1'}`}
|
|
366
|
+
onClick={() => {
|
|
367
|
+
handleClose(modalButtonType);
|
|
368
|
+
}}
|
|
369
|
+
>
|
|
370
|
+
{label}
|
|
371
|
+
</button>
|
|
372
|
+
);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
// Put all buttons in a footer
|
|
376
|
+
const footer = (
|
|
377
|
+
(buttons && buttons.length)
|
|
378
|
+
? (
|
|
379
|
+
<div>
|
|
380
|
+
{buttons}
|
|
381
|
+
</div>
|
|
382
|
+
)
|
|
383
|
+
: undefined
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
// Choose an animation
|
|
387
|
+
let animationClass = '';
|
|
388
|
+
let backdropAnimationClass = '';
|
|
389
|
+
if (animatingIn) {
|
|
390
|
+
animationClass = 'Modal-animating-in';
|
|
391
|
+
backdropAnimationClass = 'Modal-fading-in';
|
|
392
|
+
} else if (animatingPop) {
|
|
393
|
+
animationClass = 'Modal-animating-pop';
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Render the modal
|
|
397
|
+
const contentToRender = (
|
|
398
|
+
<div
|
|
399
|
+
className="modal show"
|
|
400
|
+
tabIndex={-1}
|
|
401
|
+
style={{
|
|
402
|
+
zIndex: baseZIndex,
|
|
403
|
+
display: 'block',
|
|
404
|
+
margin: 'auto',
|
|
405
|
+
left: 0,
|
|
406
|
+
right: 0,
|
|
407
|
+
}}
|
|
408
|
+
>
|
|
409
|
+
<style>{style}</style>
|
|
410
|
+
<div
|
|
411
|
+
className={`Modal-backdrop ${backdropAnimationClass}`}
|
|
412
|
+
style={{
|
|
413
|
+
zIndex: baseZIndex + 1,
|
|
414
|
+
}}
|
|
415
|
+
onClick={async () => {
|
|
416
|
+
// Skip if exit via backdrop not allowed
|
|
417
|
+
if (dontAllowBackdropExit || !onClose) {
|
|
418
|
+
// Show pop animation
|
|
419
|
+
if (!animatingPop) {
|
|
420
|
+
setAnimatingPop(true);
|
|
421
|
+
|
|
422
|
+
// Wait then stop pop animation
|
|
423
|
+
await waitMs(MS_TO_ANIMATE);
|
|
424
|
+
setAnimatingPop(false);
|
|
425
|
+
}
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
// Handle close
|
|
429
|
+
handleClose(ModalButtonType.Cancel);
|
|
430
|
+
}}
|
|
431
|
+
/>
|
|
432
|
+
<div
|
|
433
|
+
className={`modal-dialog modal-${size} ${animationClass} modal-dialog-scrollable modal-dialog-centered`}
|
|
434
|
+
style={{
|
|
435
|
+
zIndex: baseZIndex + 2,
|
|
436
|
+
}}
|
|
437
|
+
>
|
|
438
|
+
<div
|
|
439
|
+
className="modal-content"
|
|
440
|
+
style={{
|
|
441
|
+
borderColor: (
|
|
442
|
+
isDarkModeOn()
|
|
443
|
+
? 'gray'
|
|
444
|
+
: undefined
|
|
445
|
+
),
|
|
446
|
+
}}
|
|
447
|
+
>
|
|
448
|
+
<div
|
|
449
|
+
className="modal-header"
|
|
450
|
+
style={{
|
|
451
|
+
color: (
|
|
452
|
+
isDarkModeOn()
|
|
453
|
+
? 'white'
|
|
454
|
+
: undefined
|
|
455
|
+
),
|
|
456
|
+
backgroundColor: (
|
|
457
|
+
isDarkModeOn()
|
|
458
|
+
? '#444'
|
|
459
|
+
: undefined
|
|
460
|
+
),
|
|
461
|
+
borderBottom: (
|
|
462
|
+
isDarkModeOn()
|
|
463
|
+
? '0.1rem solid gray'
|
|
464
|
+
: undefined
|
|
465
|
+
),
|
|
466
|
+
}}
|
|
467
|
+
>
|
|
468
|
+
<h5
|
|
469
|
+
className="modal-title"
|
|
470
|
+
style={{
|
|
471
|
+
fontWeight: 'bold',
|
|
472
|
+
}}
|
|
473
|
+
>
|
|
474
|
+
{title}
|
|
475
|
+
</h5>
|
|
476
|
+
|
|
477
|
+
{(onClose && !dontShowXButton) && (
|
|
478
|
+
<button
|
|
479
|
+
type="button"
|
|
480
|
+
className="Modal-x-button btn-close"
|
|
481
|
+
aria-label="Close"
|
|
482
|
+
style={{
|
|
483
|
+
backgroundColor: (
|
|
484
|
+
isDarkModeOn()
|
|
485
|
+
? 'white'
|
|
486
|
+
: undefined
|
|
487
|
+
),
|
|
488
|
+
}}
|
|
489
|
+
onClick={() => {
|
|
490
|
+
// Handle close
|
|
491
|
+
handleClose(ModalButtonType.Cancel);
|
|
492
|
+
}}
|
|
493
|
+
/>
|
|
494
|
+
)}
|
|
495
|
+
</div>
|
|
496
|
+
{children && (
|
|
497
|
+
<div
|
|
498
|
+
className="modal-body"
|
|
499
|
+
style={{
|
|
500
|
+
color: (
|
|
501
|
+
isDarkModeOn()
|
|
502
|
+
? 'white'
|
|
503
|
+
: undefined
|
|
504
|
+
),
|
|
505
|
+
backgroundColor: (
|
|
506
|
+
isDarkModeOn()
|
|
507
|
+
? '#444'
|
|
508
|
+
: undefined
|
|
509
|
+
),
|
|
510
|
+
}}
|
|
511
|
+
>
|
|
512
|
+
{children}
|
|
513
|
+
</div>
|
|
514
|
+
)}
|
|
515
|
+
{footer && (
|
|
516
|
+
<div
|
|
517
|
+
className="modal-footer pt-1 pb-1"
|
|
518
|
+
style={{
|
|
519
|
+
color: (
|
|
520
|
+
isDarkModeOn()
|
|
521
|
+
? 'white'
|
|
522
|
+
: undefined
|
|
523
|
+
),
|
|
524
|
+
backgroundColor: (
|
|
525
|
+
isDarkModeOn()
|
|
526
|
+
? '#444'
|
|
527
|
+
: undefined
|
|
528
|
+
),
|
|
529
|
+
borderTop: (
|
|
530
|
+
isDarkModeOn()
|
|
531
|
+
? '0.1rem solid gray'
|
|
532
|
+
: undefined
|
|
533
|
+
),
|
|
534
|
+
}}
|
|
535
|
+
>
|
|
536
|
+
{footer}
|
|
537
|
+
</div>
|
|
538
|
+
)}
|
|
539
|
+
</div>
|
|
540
|
+
</div>
|
|
541
|
+
</div>
|
|
542
|
+
);
|
|
543
|
+
|
|
544
|
+
// Determine which portal to use
|
|
545
|
+
const portalNumber = id.current % NUM_MODAL_PORTALS;
|
|
94
546
|
|
|
95
|
-
|
|
96
|
-
|
|
547
|
+
// Render in a portal
|
|
548
|
+
return ReactDOM.createPortal(
|
|
549
|
+
contentToRender,
|
|
550
|
+
document.getElementById(`modal-portal-${portalNumber}`) as HTMLElement,
|
|
97
551
|
);
|
|
98
552
|
};
|
|
99
553
|
|
|
@@ -101,5 +555,4 @@ const Modal: React.FC<ModalProps> = (props) => {
|
|
|
101
555
|
/* ------------------------------- Wrap Up ------------------------------ */
|
|
102
556
|
/*------------------------------------------------------------------------*/
|
|
103
557
|
|
|
104
|
-
// Export component
|
|
105
558
|
export default Modal;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The displayable modal component (this is the modal that's added to the
|
|
3
|
-
* wrapper, not the one that the programmer renders)
|
|
4
|
-
* @author Gabe Abrams
|
|
5
|
-
*/
|
|
6
|
-
import React from 'react';
|
|
7
|
-
import ModalProps from './ModalProps';
|
|
8
|
-
declare const Modal: React.FC<ModalProps>;
|
|
9
|
-
export default Modal;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The displayable modal component (this is the modal that's added to the
|
|
3
|
-
* wrapper, not the one that the programmer renders)
|
|
4
|
-
* @author Gabe Abrams
|
|
5
|
-
*/
|
|
6
|
-
import React from 'react';
|
|
7
|
-
import ModalProps from './ModalProps';
|
|
8
|
-
declare const Modal: React.FC<ModalProps>;
|
|
9
|
-
export default Modal;
|