dce-reactkit 3.0.22 → 3.0.23
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 +153 -28
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +154 -29
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Modal.tsx +161 -20
package/src/components/Modal.tsx
CHANGED
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// Import React
|
|
7
|
-
import React from 'react';
|
|
7
|
+
import React, { useState, useEffect } from 'react';
|
|
8
|
+
|
|
9
|
+
// Import other components
|
|
10
|
+
import waitMs from '../helpers/waitMs';
|
|
8
11
|
|
|
9
12
|
// Import types
|
|
10
13
|
import Variant from '../types/Variant';
|
|
@@ -114,7 +117,6 @@ const style = `
|
|
|
114
117
|
height: 100vw;
|
|
115
118
|
background-color: rgba(0, 0, 0, 0.7);
|
|
116
119
|
}
|
|
117
|
-
|
|
118
120
|
.Modal-fading-in {
|
|
119
121
|
animation-name: Modal-fading-in;
|
|
120
122
|
animation-duration: ${Math.floor(MS_TO_ANIMATE * 2)}ms;
|
|
@@ -122,7 +124,6 @@ const style = `
|
|
|
122
124
|
animation-fill-mode: both;
|
|
123
125
|
animation-timing-function: ease-out;
|
|
124
126
|
}
|
|
125
|
-
|
|
126
127
|
@keyframes Modal-fading-in {
|
|
127
128
|
0% {
|
|
128
129
|
opacity: 0;
|
|
@@ -131,7 +132,21 @@ const style = `
|
|
|
131
132
|
opacity: 1;
|
|
132
133
|
}
|
|
133
134
|
}
|
|
134
|
-
|
|
135
|
+
.Modal-fading-out {
|
|
136
|
+
animation-name: Modal-fading-out;
|
|
137
|
+
animation-duration: ${MS_TO_ANIMATE}ms;
|
|
138
|
+
animation-iteration-count: 1;
|
|
139
|
+
animation-fill-mode: both;
|
|
140
|
+
animation-timing-function: ease-in;
|
|
141
|
+
}
|
|
142
|
+
@keyframes Modal-fading-out {
|
|
143
|
+
0% {
|
|
144
|
+
opacity: 1;
|
|
145
|
+
}
|
|
146
|
+
100% {
|
|
147
|
+
opacity: 0;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
135
150
|
.Modal-animating-in {
|
|
136
151
|
animation-name: Modal-animating-in;
|
|
137
152
|
animation-duration: ${MS_TO_ANIMATE}ms;
|
|
@@ -139,7 +154,6 @@ const style = `
|
|
|
139
154
|
animation-fill-mode: both;
|
|
140
155
|
animation-timing-function: ease-out;
|
|
141
156
|
}
|
|
142
|
-
|
|
143
157
|
@keyframes Modal-animating-in {
|
|
144
158
|
0% {
|
|
145
159
|
transform: scale(1.05) translate(0, -1.5rem);
|
|
@@ -150,6 +164,44 @@ const style = `
|
|
|
150
164
|
opacity: 1;
|
|
151
165
|
}
|
|
152
166
|
}
|
|
167
|
+
.Modal-animating-pop {
|
|
168
|
+
animation-name: Modal-animating-pop;
|
|
169
|
+
animation-duration: ${MS_TO_ANIMATE}ms;
|
|
170
|
+
animation-iteration-count: 1;
|
|
171
|
+
animation-fill-mode: both;
|
|
172
|
+
animation-timing-function: ease-in-out;
|
|
173
|
+
}
|
|
174
|
+
@keyframes Modal-animating-pop {
|
|
175
|
+
0% {
|
|
176
|
+
transform: scale(1);
|
|
177
|
+
opacity: 1;
|
|
178
|
+
}
|
|
179
|
+
50% {
|
|
180
|
+
transform: scale(1.05);
|
|
181
|
+
opacity: 0.9;
|
|
182
|
+
}
|
|
183
|
+
100% {
|
|
184
|
+
transform: scale(1);
|
|
185
|
+
opacity: 1;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
.Modal-animating-out {
|
|
189
|
+
animation-name: Modal-animating-out;
|
|
190
|
+
animation-duration: ${MS_TO_ANIMATE}ms;
|
|
191
|
+
animation-iteration-count: 1;
|
|
192
|
+
animation-fill-mode: both;
|
|
193
|
+
animation-timing-function: ease-in;
|
|
194
|
+
}
|
|
195
|
+
@keyframes Modal-animating-out {
|
|
196
|
+
0% {
|
|
197
|
+
transform: scale(1) translate(0, 0);
|
|
198
|
+
opacity: 1;
|
|
199
|
+
}
|
|
200
|
+
100% {
|
|
201
|
+
transform: scale(1.05) translate(0, -1.5rem);
|
|
202
|
+
opacity: 0;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
153
205
|
`;
|
|
154
206
|
|
|
155
207
|
/*------------------------------------------------------------------------*/
|
|
@@ -234,6 +286,77 @@ const Modal: React.FC<Props> = (props) => {
|
|
|
234
286
|
onTopOfOtherModals,
|
|
235
287
|
} = props;
|
|
236
288
|
|
|
289
|
+
/* -------------- State ------------- */
|
|
290
|
+
|
|
291
|
+
// If true, the modal is shown
|
|
292
|
+
const [visible, setVisible] = useState(false);
|
|
293
|
+
|
|
294
|
+
// True if animation is in use
|
|
295
|
+
const [animatingIn, setAnimatingIn] = useState(true);
|
|
296
|
+
const [animatingPop, setAnimatingPop] = useState(false);
|
|
297
|
+
const [animatingOut, setAnimatingOut] = useState(false);
|
|
298
|
+
|
|
299
|
+
/*------------------------------------------------------------------------*/
|
|
300
|
+
/* Lifecycle Functions */
|
|
301
|
+
/*------------------------------------------------------------------------*/
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Mount
|
|
305
|
+
* @author Gabe Abrams
|
|
306
|
+
*/
|
|
307
|
+
useEffect(
|
|
308
|
+
() => {
|
|
309
|
+
(async () => {
|
|
310
|
+
// Set defaults
|
|
311
|
+
setVisible(false);
|
|
312
|
+
setAnimatingIn(true);
|
|
313
|
+
setAnimatingPop(false);
|
|
314
|
+
setAnimatingOut(false);
|
|
315
|
+
// Wait for animation
|
|
316
|
+
await waitMs(MS_TO_ANIMATE);
|
|
317
|
+
// Update to state after animated in
|
|
318
|
+
setVisible(true);
|
|
319
|
+
setAnimatingIn(false);
|
|
320
|
+
})();
|
|
321
|
+
},
|
|
322
|
+
[],
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
/*------------------------------------------------------------------------*/
|
|
326
|
+
/* Component Functions */
|
|
327
|
+
/*------------------------------------------------------------------------*/
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Handles the closing of the modal
|
|
331
|
+
* @author Gabe Abrams
|
|
332
|
+
* @param ModalButtonType the button that was clicked when closing the
|
|
333
|
+
* modal
|
|
334
|
+
*/
|
|
335
|
+
const handleClose = async (ModalButtonType: ModalButtonType) => {
|
|
336
|
+
// Don't close if no handler
|
|
337
|
+
if (!onClose) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Don't close if animating in
|
|
342
|
+
if (animatingIn) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Don't close if already closed
|
|
347
|
+
if (!visible) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Update the state
|
|
352
|
+
setVisible(false);
|
|
353
|
+
setAnimatingOut(true);
|
|
354
|
+
|
|
355
|
+
// Call the handler after the modal has animated out
|
|
356
|
+
await waitMs(MS_TO_ANIMATE);
|
|
357
|
+
onClose(ModalButtonType);
|
|
358
|
+
};
|
|
359
|
+
|
|
237
360
|
/*------------------------------------------------------------------------*/
|
|
238
361
|
/* Render */
|
|
239
362
|
/*------------------------------------------------------------------------*/
|
|
@@ -246,19 +369,19 @@ const Modal: React.FC<Props> = (props) => {
|
|
|
246
369
|
const ModalButtonTypes: ModalButtonType[] = modalTypeToModalButtonTypes[type] ?? [];
|
|
247
370
|
|
|
248
371
|
// Create buttons
|
|
249
|
-
const buttons = ModalButtonTypes.map((
|
|
372
|
+
const buttons = ModalButtonTypes.map((ModalButtonType: ModalButtonType, i) => {
|
|
250
373
|
// Get default style
|
|
251
374
|
let {
|
|
252
375
|
label,
|
|
253
376
|
variant,
|
|
254
|
-
} = ModalButtonTypeToLabelAndVariant[
|
|
377
|
+
} = ModalButtonTypeToLabelAndVariant[ModalButtonType];
|
|
255
378
|
|
|
256
379
|
// Override with customizations
|
|
257
|
-
const newLabel = props[`${
|
|
380
|
+
const newLabel = props[`${ModalButtonType}Label`];
|
|
258
381
|
if (newLabel) {
|
|
259
382
|
label = newLabel;
|
|
260
383
|
}
|
|
261
|
-
const newVariant = props[`${
|
|
384
|
+
const newVariant = props[`${ModalButtonType}Variant`];
|
|
262
385
|
if (newVariant) {
|
|
263
386
|
variant = newVariant;
|
|
264
387
|
}
|
|
@@ -269,13 +392,11 @@ const Modal: React.FC<Props> = (props) => {
|
|
|
269
392
|
// Create the button
|
|
270
393
|
return (
|
|
271
394
|
<button
|
|
272
|
-
key={
|
|
395
|
+
key={ModalButtonType}
|
|
273
396
|
type="button"
|
|
274
|
-
className={`Modal-${
|
|
397
|
+
className={`Modal-${ModalButtonType}-button btn btn-${variant} ${last ? '' : 'me-1'}`}
|
|
275
398
|
onClick={() => {
|
|
276
|
-
|
|
277
|
-
onClose(buttonType);
|
|
278
|
-
}
|
|
399
|
+
handleClose(ModalButtonType);
|
|
279
400
|
}}
|
|
280
401
|
>
|
|
281
402
|
{label}
|
|
@@ -294,10 +415,23 @@ const Modal: React.FC<Props> = (props) => {
|
|
|
294
415
|
: undefined
|
|
295
416
|
);
|
|
296
417
|
|
|
418
|
+
// Choose an animation
|
|
419
|
+
let animationClass = '';
|
|
420
|
+
let backdropAnimationClass = '';
|
|
421
|
+
if (animatingIn) {
|
|
422
|
+
animationClass = 'Modal-animating-in';
|
|
423
|
+
backdropAnimationClass = 'Modal-fading-in';
|
|
424
|
+
} else if (animatingOut) {
|
|
425
|
+
animationClass = 'Modal-animating-out';
|
|
426
|
+
backdropAnimationClass = 'Modal-fading-out';
|
|
427
|
+
} else if (animatingPop) {
|
|
428
|
+
animationClass = 'Modal-animating-pop';
|
|
429
|
+
}
|
|
430
|
+
|
|
297
431
|
// Render the modal
|
|
298
432
|
return (
|
|
299
433
|
<div
|
|
300
|
-
className=
|
|
434
|
+
className={`modal show modal-dialog-scrollable modal-dialog-centered`}
|
|
301
435
|
tabIndex={-1}
|
|
302
436
|
style={{
|
|
303
437
|
zIndex: (
|
|
@@ -313,22 +447,29 @@ const Modal: React.FC<Props> = (props) => {
|
|
|
313
447
|
>
|
|
314
448
|
<style>{style}</style>
|
|
315
449
|
<div
|
|
316
|
-
className=
|
|
450
|
+
className={`Modal-backdrop ${backdropAnimationClass}`}
|
|
317
451
|
style={{
|
|
318
452
|
zIndex: 5000000003,
|
|
319
453
|
}}
|
|
320
454
|
onClick={async () => {
|
|
321
455
|
// Skip if exit via backdrop not allowed
|
|
322
456
|
if (dontAllowBackdropExit || !onClose) {
|
|
457
|
+
// Show pop animation
|
|
458
|
+
if (!animatingPop) {
|
|
459
|
+
setAnimatingPop(true);
|
|
460
|
+
|
|
461
|
+
// Wait then stop pop animation
|
|
462
|
+
await waitMs(MS_TO_ANIMATE);
|
|
463
|
+
setAnimatingPop(false);
|
|
464
|
+
}
|
|
323
465
|
return;
|
|
324
466
|
}
|
|
325
|
-
|
|
326
467
|
// Handle close
|
|
327
|
-
|
|
468
|
+
handleClose(ModalButtonType.Cancel);
|
|
328
469
|
}}
|
|
329
470
|
/>
|
|
330
471
|
<div
|
|
331
|
-
className={`modal-dialog modal-${size}
|
|
472
|
+
className={`modal-dialog modal-${size} ${animationClass}`}
|
|
332
473
|
style={{
|
|
333
474
|
zIndex: 5000000002,
|
|
334
475
|
}}
|
|
@@ -351,7 +492,7 @@ const Modal: React.FC<Props> = (props) => {
|
|
|
351
492
|
aria-label="Close"
|
|
352
493
|
onClick={() => {
|
|
353
494
|
// Handle close
|
|
354
|
-
|
|
495
|
+
handleClose(ModalButtonType.Cancel);
|
|
355
496
|
}}
|
|
356
497
|
/>
|
|
357
498
|
)}
|