dce-reactkit 3.0.0-beta.3 → 3.0.0-beta.32

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.
Files changed (42) hide show
  1. package/.eslintrc.js +95 -0
  2. package/README.md +1 -546
  3. package/dist/cjs/index.js +787 -35684
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/types/components/AppWrapper.d.ts +26 -1
  6. package/dist/cjs/types/components/TabBox.d.ts +1 -0
  7. package/dist/cjs/types/helpers/genRouteHandler.d.ts +30 -0
  8. package/dist/cjs/types/helpers/handleError.d.ts +18 -0
  9. package/dist/cjs/types/helpers/handleSuccess.d.ts +8 -0
  10. package/dist/cjs/types/helpers/visitServerEndpoint.d.ts +23 -0
  11. package/dist/cjs/types/index.d.ts +7 -1
  12. package/dist/cjs/types/server/initServer.d.ts +21 -0
  13. package/dist/cjs/types/types/ParamType.d.ts +17 -0
  14. package/dist/cjs/types/types/ReactKitErrorCode.d.ts +3 -1
  15. package/dist/esm/index.js +717 -35602
  16. package/dist/esm/index.js.map +1 -1
  17. package/dist/esm/types/components/AppWrapper.d.ts +26 -1
  18. package/dist/esm/types/components/TabBox.d.ts +1 -0
  19. package/dist/esm/types/helpers/genRouteHandler.d.ts +30 -0
  20. package/dist/esm/types/helpers/handleError.d.ts +18 -0
  21. package/dist/esm/types/helpers/handleSuccess.d.ts +8 -0
  22. package/dist/esm/types/helpers/visitServerEndpoint.d.ts +23 -0
  23. package/dist/esm/types/index.d.ts +7 -1
  24. package/dist/esm/types/server/initServer.d.ts +21 -0
  25. package/dist/esm/types/types/ParamType.d.ts +17 -0
  26. package/dist/esm/types/types/ReactKitErrorCode.d.ts +3 -1
  27. package/dist/index.d.ts +125 -3
  28. package/package.json +13 -3
  29. package/rollup.config.js +0 -1
  30. package/src/components/AppWrapper.tsx +72 -12
  31. package/src/components/ErrorBox.tsx +4 -4
  32. package/src/components/LoadingSpinner.tsx +3 -3
  33. package/src/components/Modal.tsx +214 -97
  34. package/src/components/TabBox.tsx +65 -58
  35. package/src/helpers/genRouteHandler.ts +326 -0
  36. package/src/helpers/handleError.ts +65 -0
  37. package/src/helpers/handleSuccess.ts +18 -0
  38. package/src/helpers/visitServerEndpoint.tsx +110 -0
  39. package/src/index.ts +15 -0
  40. package/src/server/initServer.ts +53 -0
  41. package/src/types/ParamType.tsx +18 -0
  42. package/src/types/ReactKitErrorCode.tsx +3 -1
@@ -7,7 +7,6 @@
7
7
  import React, { useState, useEffect } from 'react';
8
8
 
9
9
  // Import other components
10
- import BootstrapModal from 'react-bootstrap/Modal';
11
10
  import waitMs from '../helpers/waitMs';
12
11
 
13
12
  // Import types
@@ -16,69 +15,12 @@ import ModalButtonType from '../types/ModalButtonType';
16
15
  import ModalSize from '../types/ModalSize';
17
16
  import ModalType from '../types/ModalType';
18
17
 
19
- /*------------------------------------------------------------------------*/
20
- /* Style */
21
- /*------------------------------------------------------------------------*/
22
-
23
- const style = `
24
- /* More opaque backdrop */
25
- .Modal-backdrop {
26
- background-color: black !important;
27
- opacity: 0.8 !important;
28
- z-index: 10000000 !important;
29
- }
30
-
31
- /* Customize the modal header and body */
32
- .modal-header {
33
- /* Dark theme */
34
- background-color: #222 !important;
35
- color: white !important;
36
-
37
- /* Border */
38
- border: 1px solid #545454 !important;
39
- }
40
- .modal-body {
41
- /* Dark theme */
42
- background-color: #222 !important;
43
- color: white !important;
44
-
45
- /* Border */
46
- border-top: 0 !important;
47
- border-left: 1px solid #545454 !important;
48
- border-bottom: 1px solid #545454 !important;
49
- border-right: 1px solid #545454 !important;
50
- border-bottom-left-radius: 3px;
51
- border-bottom-right-radius: 3px;
52
- }
53
-
54
- /* Create our own animation */
55
- .modal-content {
56
- animation-name: Modal-drop-in;
57
- animation-duration: 0.4s;
58
- animation-iteration-count: 1;
59
- animation-fill-mode: forwards;
60
- animation-timing-function: ease-out;
61
- }
62
- @keyframes Modal-drop-in {
63
- 0% {
64
- transform: scale(0.8);
65
- opacity: 0.5;
66
- }
67
- 100% {
68
- transform: scale(1);
69
- opacity: 1;
70
- }
71
- }
72
- `;
73
-
74
18
  /*------------------------------------------------------------------------*/
75
19
  /* Constants */
76
20
  /*------------------------------------------------------------------------*/
77
21
 
78
22
  // Constants
79
- const MS_TO_ANIMATE = 400; // Time to animate in/out (defined by bootstrap)
80
- const MS_ANIMATE_IN_DELAY = 10;
81
- // Time to wait before animating in (must be >0 or animation won't trigger)
23
+ const MS_TO_ANIMATE = 200; // Animation duration
82
24
 
83
25
  // Modal type to list of buttons
84
26
  const modalTypeToModalButtonTypes: {
@@ -162,6 +104,116 @@ const ModalButtonTypeToLabelAndVariant = {
162
104
  },
163
105
  };
164
106
 
107
+ /*------------------------------------------------------------------------*/
108
+ /* Style */
109
+ /*------------------------------------------------------------------------*/
110
+
111
+ const style = `
112
+ .Modal-backdrop {
113
+ position: fixed;
114
+ top: 0;
115
+ left: 0;
116
+ width: 100vw;
117
+ height: 100vw;
118
+ background-color: rgba(0, 0, 0, 0.7);
119
+ }
120
+
121
+ .Modal-fading-in {
122
+ animation-name: Modal-fading-in;
123
+ animation-duration: ${Math.floor(MS_TO_ANIMATE * 2)}ms;
124
+ animation-iteration-count: 1;
125
+ animation-fill-mode: both;
126
+ animation-timing-function: ease-out;
127
+ }
128
+
129
+ @keyframes Modal-fading-in {
130
+ 0% {
131
+ opacity: 0;
132
+ }
133
+ 100% {
134
+ opacity: 1;
135
+ }
136
+ }
137
+
138
+ .Modal-fading-out {
139
+ animation-name: Modal-fading-out;
140
+ animation-duration: ${MS_TO_ANIMATE}ms;
141
+ animation-iteration-count: 1;
142
+ animation-fill-mode: both;
143
+ animation-timing-function: ease-in;
144
+ }
145
+
146
+ @keyframes Modal-fading-out {
147
+ 0% {
148
+ opacity: 1;
149
+ }
150
+ 100% {
151
+ opacity: 0;
152
+ }
153
+ }
154
+
155
+ .Modal-animating-in {
156
+ animation-name: Modal-animating-in;
157
+ animation-duration: ${MS_TO_ANIMATE}ms;
158
+ animation-iteration-count: 1;
159
+ animation-fill-mode: both;
160
+ animation-timing-function: ease-out;
161
+ }
162
+
163
+ @keyframes Modal-animating-in {
164
+ 0% {
165
+ transform: scale(1.05) translate(0, -1.5rem);
166
+ opacity: 0;
167
+ }
168
+ 100% {
169
+ transform: scale(1) translate(0, 0);
170
+ opacity: 1;
171
+ }
172
+ }
173
+
174
+ .Modal-animating-pop {
175
+ animation-name: Modal-animating-pop;
176
+ animation-duration: ${MS_TO_ANIMATE}ms;
177
+ animation-iteration-count: 1;
178
+ animation-fill-mode: both;
179
+ animation-timing-function: ease-in-out;
180
+ }
181
+
182
+ @keyframes Modal-animating-pop {
183
+ 0% {
184
+ transform: scale(1);
185
+ opacity: 1;
186
+ }
187
+ 50% {
188
+ transform: scale(1.05);
189
+ opacity: 0.9;
190
+ }
191
+ 100% {
192
+ transform: scale(1);
193
+ opacity: 1;
194
+ }
195
+ }
196
+
197
+ .Modal-animating-out {
198
+ animation-name: Modal-animating-out;
199
+ animation-duration: ${MS_TO_ANIMATE}ms;
200
+ animation-iteration-count: 1;
201
+ animation-fill-mode: both;
202
+ animation-timing-function: ease-in;
203
+ }
204
+
205
+ @keyframes Modal-animating-out {
206
+ 0% {
207
+ transform: scale(1) translate(0, 0);
208
+ opacity: 1;
209
+ }
210
+ 100% {
211
+ transform: scale(1.05) translate(0, -1.5rem);
212
+ opacity: 0;
213
+ }
214
+ }
215
+ `;
216
+
165
217
  /*------------------------------------------------------------------------*/
166
218
  /* Types */
167
219
  /*------------------------------------------------------------------------*/
@@ -246,11 +298,17 @@ const Modal: React.FC<Props> = (props) => {
246
298
 
247
299
  /* -------------- State ------------- */
248
300
 
301
+ // If true, the modal is completely gone
302
+ // (not just invisible, also removed from the dom)
303
+ const [gone, setGone] = useState(false);
304
+
249
305
  // If true, the modal is shown
250
306
  const [visible, setVisible] = useState(false);
251
307
 
252
- // True if currently animating in
253
- const [animatingIn, setAnimatingIn] = useState(false);
308
+ // True if animation is in use
309
+ const [animatingIn, setAnimatingIn] = useState(true);
310
+ const [animatingPop, setAnimatingPop] = useState(false);
311
+ const [animatingOut, setAnimatingOut] = useState(false);
254
312
 
255
313
  /*------------------------------------------------------------------------*/
256
314
  /* Lifecycle Functions */
@@ -263,13 +321,10 @@ const Modal: React.FC<Props> = (props) => {
263
321
  useEffect(
264
322
  () => {
265
323
  (async () => {
266
- // Start the component animating in
267
- await waitMs(MS_ANIMATE_IN_DELAY);
268
- setAnimatingIn(true);
269
-
270
324
  // Wait and then set visible to true
271
325
  await waitMs(MS_TO_ANIMATE);
272
326
  setVisible(true);
327
+ setAnimatingIn(false);
273
328
  })();
274
329
  },
275
330
  [],
@@ -303,16 +358,23 @@ const Modal: React.FC<Props> = (props) => {
303
358
 
304
359
  // Update the state
305
360
  setVisible(false);
361
+ setAnimatingOut(true);
306
362
 
307
363
  // Call the handler after the modal has animated out
308
364
  await waitMs(MS_TO_ANIMATE);
309
365
  onClose(ModalButtonType);
366
+ setGone(true);
310
367
  };
311
368
 
312
369
  /*------------------------------------------------------------------------*/
313
370
  /* Render */
314
371
  /*------------------------------------------------------------------------*/
315
372
 
373
+ // Return nothing if gone
374
+ if (gone) {
375
+ return null;
376
+ }
377
+
316
378
  /*----------------------------------------*/
317
379
  /* Footer */
318
380
  /*----------------------------------------*/
@@ -344,8 +406,9 @@ const Modal: React.FC<Props> = (props) => {
344
406
  // Create the button
345
407
  return (
346
408
  <button
409
+ key={ModalButtonType}
347
410
  type="button"
348
- className={`Modal-${ModalButtonType}-button btn btn-${variant} ${last ? '' : 'mr-1'}`}
411
+ className={`Modal-${ModalButtonType}-button btn btn-${variant} ${last ? '' : 'me-1'}`}
349
412
  onClick={() => {
350
413
  handleClose(ModalButtonType);
351
414
  }}
@@ -366,47 +429,101 @@ const Modal: React.FC<Props> = (props) => {
366
429
  : undefined
367
430
  );
368
431
 
432
+ // Choose an animation
433
+ let animationClass = '';
434
+ let backdropAnimationClass = '';
435
+ if (animatingIn) {
436
+ animationClass = 'Modal-animating-in';
437
+ backdropAnimationClass = 'Modal-fading-in';
438
+ } else if (animatingOut) {
439
+ animationClass = 'Modal-animating-out';
440
+ backdropAnimationClass = 'Modal-fading-out';
441
+ } else if (animatingPop) {
442
+ animationClass = 'Modal-animating-pop';
443
+ }
444
+
369
445
  // Render the modal
370
446
  return (
371
- <BootstrapModal
372
- show={visible}
373
- size={size !== ModalSize.Medium ? size : undefined}
374
- onHide={() => {
375
- if (!dontAllowBackdropExit) {
376
- handleClose(ModalButtonType.Cancel);
377
- }
378
- }}
447
+ <div
448
+ className={`modal show modal-dialog-scrollable modal-dialog-centered modal-${size}`}
449
+ tabIndex={-1}
379
450
  style={{
380
451
  zIndex: (
381
452
  onTopOfOtherModals
382
- ? 6000000000
453
+ ? 5000000001
383
454
  : 5000000000
384
455
  ),
456
+ display: 'block',
457
+ margin: 'auto',
458
+ left: 0,
459
+ right: 0,
385
460
  }}
386
- backdropClassName="Modal-backdrop"
387
- centered
388
461
  >
389
462
  <style>{style}</style>
390
- {title && (
391
- <BootstrapModal.Header
392
- closeButton={!!onClose}
393
- >
394
- <BootstrapModal.Title>
395
- {title}
396
- </BootstrapModal.Title>
397
- </BootstrapModal.Header>
398
- )}
399
- {children && (
400
- <BootstrapModal.Body>
401
- {children}
402
- </BootstrapModal.Body>
403
- )}
404
- {footer && (
405
- <BootstrapModal.Footer>
406
- {footer}
407
- </BootstrapModal.Footer>
408
- )}
409
- </BootstrapModal>
463
+ <div
464
+ className={`Modal-backdrop ${backdropAnimationClass}`}
465
+ style={{
466
+ zIndex: 5000000003,
467
+ }}
468
+ onClick={async () => {
469
+ // Skip if exit via backdrop not allowed
470
+ if (dontAllowBackdropExit || !onClose) {
471
+ // Show pop animation
472
+ if (!animatingPop) {
473
+ setAnimatingPop(true);
474
+
475
+ // Wait then stop pop animation
476
+ await waitMs(MS_TO_ANIMATE);
477
+ setAnimatingPop(false);
478
+ }
479
+ return;
480
+ }
481
+ // Handle close
482
+ handleClose(ModalButtonType.Cancel);
483
+ }}
484
+ />
485
+ <div
486
+ className={`modal-dialog ${animationClass}`}
487
+ style={{
488
+ zIndex: 5000000002,
489
+ }}
490
+ >
491
+ <div className="modal-content">
492
+ <div className="modal-header">
493
+ <h5
494
+ className="modal-title"
495
+ style={{
496
+ fontWeight: 'bold',
497
+ }}
498
+ >
499
+ {title}
500
+ </h5>
501
+
502
+ {onClose && (
503
+ <button
504
+ type="button"
505
+ className="btn-close"
506
+ aria-label="Close"
507
+ onClick={() => {
508
+ // Handle close
509
+ handleClose(ModalButtonType.Cancel);
510
+ }}
511
+ />
512
+ )}
513
+ </div>
514
+ {children && (
515
+ <div className="modal-body">
516
+ {children}
517
+ </div>
518
+ )}
519
+ {footer && (
520
+ <div className="modal-footer pt-1 pb-1">
521
+ {footer}
522
+ </div>
523
+ )}
524
+ </div>
525
+ </div>
526
+ </div>
410
527
  );
411
528
  };
412
529
 
@@ -15,6 +15,8 @@ type Props = {
15
15
  title: React.ReactNode,
16
16
  // Children/contents inside the box
17
17
  children: React.ReactNode,
18
+ // If true, don't add padding below the tab box
19
+ noBottomPadding?: boolean,
18
20
  };
19
21
 
20
22
  /*------------------------------------------------------------------------*/
@@ -22,63 +24,67 @@ type Props = {
22
24
  /*------------------------------------------------------------------------*/
23
25
 
24
26
  const style = `
25
- /* Tab Box */
26
- .TabBox-box {
27
- /* Light Border */
28
- border: 2px solid #dedede;
29
-
30
- /* Rounded Corners (except top-left) */
31
- border-bottom-right-radius: 5px;
32
- border-bottom-left-radius: 5px;
33
- border-top-right-radius: 5px;
34
-
35
- /* Very Light Gray Border */
36
- background: #fdfdfd;
37
-
38
- /* Align Contents on Left */
39
- text-align: left;
40
- }
41
-
42
- /* Container for Title */
43
- .TabBox-title-container {
44
- /* Place on Left */
45
- position: relative;
46
- left: 0;
47
- text-align: left;
48
- }
49
-
50
- /* Tab-style Title */
51
- .TabBox-title {
52
- /* Place so it Barely Overlaps the Box Border */
53
- display: inline-block;
54
- position: relative;
55
- top: 2px; /* Gives Illusion that Border Doesn't Exist Below Tab */
56
-
57
- /* Title-sized Font */
58
- font-size: 25px;
59
-
60
- /* Add Border on Top and Sides */
61
- border-top: 2px solid #dedede;
62
- border-left: 2px solid #dedede;
63
- border-right: 2px solid #dedede;
64
-
65
- /* Round the Top Corners */
66
- border-top-left-radius: 5px;
67
- border-top-right-radius: 5px;
68
-
69
- /* Add Text Padding */
70
- padding-left: 12px;
71
- padding-right: 12px;
72
-
73
- /* Match Background Color of Box */
74
- background: #fdfdfd;
75
- }
76
-
77
- /* Make the TabBox's Children Appear Above Title if Overlap Occurs */
78
- .TabBox-children {
79
- position: relative;
80
- z-index: 1;
81
- }
27
+ /* Tab Box */
28
+ .TabBox-box {
29
+ /* Light Border */
30
+ border: 0.15rem solid #dedede;
31
+
32
+ /* Rounded Corners (except top-left) */
33
+ border-bottom-right-radius: 0.3rem;
34
+ border-bottom-left-radius: 0.3rem;
35
+ border-top-right-radius: 0.3rem;
36
+
37
+ /* Very Light Gray Border */
38
+ background: #fdfdfd;
39
+
40
+ /* Align Contents on Left */
41
+ text-align: left;
42
+
43
+ /* Add Text Padding */
44
+ padding-left: 0.3rem;
45
+ padding-right: 0.3rem;
46
+ }
47
+
48
+ /* Container for Title */
49
+ .TabBox-title-container {
50
+ /* Place on Left */
51
+ position: relative;
52
+ left: 0;
53
+ text-align: left;
54
+ }
55
+
56
+ /* Tab-style Title */
57
+ .TabBox-title {
58
+ /* Place so it Barely Overlaps the Box Border */
59
+ display: inline-block;
60
+ position: relative;
61
+ top: 0.15rem; /* Gives Illusion that Border Doesn't Exist Below Tab */
62
+
63
+ /* Title-sized Font */
64
+ font-size: 1.5rem;
65
+
66
+ /* Add Border on Top and Sides */
67
+ border-top: 0.15rem solid #dedede;
68
+ border-left: 0.15rem solid #dedede;
69
+ border-right: 0.15rem solid #dedede;
70
+
71
+ /* Round the Top Corners */
72
+ border-top-left-radius: 0.3rem;
73
+ border-top-right-radius: 0.3rem;
74
+
75
+ /* Add Text Padding */
76
+ padding-left: 0.5rem;
77
+ padding-right: 0.5rem;
78
+
79
+ /* Match Background Color of Box */
80
+ background: #fdfdfd;
81
+ }
82
+
83
+ /* Make the TabBox's Children Appear Above Title if Overlap Occurs */
84
+ .TabBox-children {
85
+ position: relative;
86
+ z-index: 1;
87
+ }
82
88
  `;
83
89
 
84
90
  /*------------------------------------------------------------------------*/
@@ -95,6 +101,7 @@ const TabBox: React.FC<Props> = (props) => {
95
101
  const {
96
102
  title,
97
103
  children,
104
+ noBottomPadding,
98
105
  } = props;
99
106
 
100
107
  /*------------------------------------------------------------------------*/
@@ -107,7 +114,7 @@ const TabBox: React.FC<Props> = (props) => {
107
114
 
108
115
  // Full UI
109
116
  return (
110
- <div>
117
+ <div className={`TabBox-container ${noBottomPadding ? '' : 'mb-2'}`}>
111
118
  {/* Style */}
112
119
  <style>{style}</style>
113
120