dce-reactkit 3.7.10 → 3.7.11

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.
@@ -5,7 +5,6 @@
5
5
  */
6
6
  import React from 'react';
7
7
  import Variant from '../types/Variant';
8
- import ModalProps from './Modal/ModalProps';
9
8
  type Props = {
10
9
  children: React.ReactNode;
11
10
  };
@@ -62,25 +61,5 @@ export declare const addFatalErrorHandler: (handler: () => void) => void;
62
61
  * @author Gabe Abrams
63
62
  */
64
63
  export declare const showSessionExpiredMessage: () => Promise<void>;
65
- /**
66
- * Add a modal to the screen
67
- * @author Gabe Abrams
68
- * @param id the uniqueId of the modal
69
- * @param props the props for the modal
70
- */
71
- export declare const addModal: (id: number, props: ModalProps) => Promise<void>;
72
- /**
73
- * Update a modal on the screen by id (if it exists) with new props
74
- * @author Gabe Abrams
75
- * @param id the uniqueId of the modal
76
- * @param props the new props for the modal
77
- */
78
- export declare const updateModal: (id: number, props: ModalProps) => Promise<void>;
79
- /**
80
- * Remove a modal from the screen by id (if it exists)
81
- * @author Gabe Abrams
82
- * @param id the uniqueId of the modal
83
- */
84
- export declare const removeModal: (id: number) => Promise<void>;
85
64
  declare const AppWrapper: React.FC<Props>;
86
65
  export default AppWrapper;
@@ -1,5 +1,6 @@
1
1
  /**
2
- * General use modal component
2
+ * The displayable modal component (this is the modal that's added to the
3
+ * wrapper, not the one that the programmer renders)
3
4
  * @author Gabe Abrams
4
5
  */
5
6
  import React from 'react';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * The number of modal portals that can be rendered at once.
3
+ * @author Gabe Abrams
4
+ */
5
+ declare const NUM_MODAL_PORTALS = 50;
6
+ export default NUM_MODAL_PORTALS;
package/dist/index.d.ts CHANGED
@@ -18,6 +18,85 @@ declare enum Variant {
18
18
  Dark = "dark"
19
19
  }
20
20
 
21
+ /**
22
+ * A wrapper for the entire React app that adds global functionality like
23
+ * handling for fatal error messages, adds bootstrap support
24
+ * @author Gabe Abrams
25
+ */
26
+
27
+ type Props$k = {
28
+ children: React$1.ReactNode;
29
+ };
30
+ /**
31
+ * Redirect to a new page
32
+ * @author Gabe Abrams
33
+ * @param url the url to redirect to
34
+ * @param destination the destination of the redirect, for example "YouTube"
35
+ * and will be used in the following text: `Redirecting to ${destination}...`
36
+ */
37
+ declare const leaveToURL: (url: string, destination: string) => Promise<void>;
38
+ /**
39
+ * Show an alert modal with an "Okay" button
40
+ * @author Gabe Abrams
41
+ * @param title the title text to display at the top of the alert
42
+ * @param text the text to display in the alert
43
+ */
44
+ declare const alert: (title: string, text: string) => Promise<undefined>;
45
+ /**
46
+ * Show a confirmation modal with an "Okay" and a "Cancel" button
47
+ * (with the option to customize the text of those buttons)
48
+ * @author Gabe Abrams
49
+ * @param title the title text to display at the top of the alert
50
+ * @param text the text to display in the alert
51
+ * @param [opts={}] additional options for the confirmation dialog
52
+ * @param [opts.confirmButtonText=Okay] the text of the confirm button
53
+ * @param [opts.confirmButtonVariant=Variant.Dark] the variant of the confirm
54
+ * button
55
+ * @param [opts.cancelButtonText=Cancel] the text of the cancel button
56
+ * @param [opts.cancelButtonVariant=Variant.Secondary] the variant of the cancel
57
+ * button
58
+ * @returns true if the user confirmed
59
+ */
60
+ declare const confirm: (title: string, text: string, opts?: {
61
+ confirmButtonText?: string;
62
+ confirmButtonVariant?: Variant;
63
+ cancelButtonText?: string;
64
+ cancelButtonVariant?: Variant;
65
+ }) => Promise<boolean>;
66
+ /**
67
+ * Show a fatal error message
68
+ * @author Gabe Abrams
69
+ * @param error the error to show
70
+ * @param [errorTitle] title of the error box
71
+ */
72
+ declare const showFatalError: (error: any, errorTitle?: string) => Promise<void>;
73
+ /**
74
+ * Add a handler for when a fatal error occurs (or when a session expiry occurs)
75
+ * @author Gabe Abrams
76
+ */
77
+ declare const addFatalErrorHandler: (handler: () => void) => void;
78
+ declare const AppWrapper: React$1.FC<Props$k>;
79
+
80
+ /**
81
+ * Loading spinner/indicator
82
+ * @author Gabe Abrams
83
+ */
84
+ declare const LoadingSpinner: () => JSX.Element;
85
+
86
+ /**
87
+ * Displays an error
88
+ * @author Gabe Abrams
89
+ */
90
+
91
+ type Props$j = {
92
+ error: any;
93
+ title?: string;
94
+ onClose?: () => void;
95
+ variant?: Variant;
96
+ icon?: IconProp;
97
+ };
98
+ declare const ErrorBox: React$1.FC<Props$j>;
99
+
21
100
  /**
22
101
  * Types of buttons in the modal
23
102
  * @author Gabe Abrams
@@ -99,86 +178,8 @@ type ModalProps = {
99
178
  };
100
179
 
101
180
  /**
102
- * A wrapper for the entire React app that adds global functionality like
103
- * handling for fatal error messages, adds bootstrap support
104
- * @author Gabe Abrams
105
- */
106
-
107
- type Props$k = {
108
- children: React$1.ReactNode;
109
- };
110
- /**
111
- * Redirect to a new page
112
- * @author Gabe Abrams
113
- * @param url the url to redirect to
114
- * @param destination the destination of the redirect, for example "YouTube"
115
- * and will be used in the following text: `Redirecting to ${destination}...`
116
- */
117
- declare const leaveToURL: (url: string, destination: string) => Promise<void>;
118
- /**
119
- * Show an alert modal with an "Okay" button
120
- * @author Gabe Abrams
121
- * @param title the title text to display at the top of the alert
122
- * @param text the text to display in the alert
123
- */
124
- declare const alert: (title: string, text: string) => Promise<undefined>;
125
- /**
126
- * Show a confirmation modal with an "Okay" and a "Cancel" button
127
- * (with the option to customize the text of those buttons)
128
- * @author Gabe Abrams
129
- * @param title the title text to display at the top of the alert
130
- * @param text the text to display in the alert
131
- * @param [opts={}] additional options for the confirmation dialog
132
- * @param [opts.confirmButtonText=Okay] the text of the confirm button
133
- * @param [opts.confirmButtonVariant=Variant.Dark] the variant of the confirm
134
- * button
135
- * @param [opts.cancelButtonText=Cancel] the text of the cancel button
136
- * @param [opts.cancelButtonVariant=Variant.Secondary] the variant of the cancel
137
- * button
138
- * @returns true if the user confirmed
139
- */
140
- declare const confirm: (title: string, text: string, opts?: {
141
- confirmButtonText?: string;
142
- confirmButtonVariant?: Variant;
143
- cancelButtonText?: string;
144
- cancelButtonVariant?: Variant;
145
- }) => Promise<boolean>;
146
- /**
147
- * Show a fatal error message
148
- * @author Gabe Abrams
149
- * @param error the error to show
150
- * @param [errorTitle] title of the error box
151
- */
152
- declare const showFatalError: (error: any, errorTitle?: string) => Promise<void>;
153
- /**
154
- * Add a handler for when a fatal error occurs (or when a session expiry occurs)
155
- * @author Gabe Abrams
156
- */
157
- declare const addFatalErrorHandler: (handler: () => void) => void;
158
- declare const AppWrapper: React$1.FC<Props$k>;
159
-
160
- /**
161
- * Loading spinner/indicator
162
- * @author Gabe Abrams
163
- */
164
- declare const LoadingSpinner: () => JSX.Element;
165
-
166
- /**
167
- * Displays an error
168
- * @author Gabe Abrams
169
- */
170
-
171
- type Props$j = {
172
- error: any;
173
- title?: string;
174
- onClose?: () => void;
175
- variant?: Variant;
176
- icon?: IconProp;
177
- };
178
- declare const ErrorBox: React$1.FC<Props$j>;
179
-
180
- /**
181
- * General use modal component
181
+ * The displayable modal component (this is the modal that's added to the
182
+ * wrapper, not the one that the programmer renders)
182
183
  * @author Gabe Abrams
183
184
  */
184
185
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dce-reactkit",
3
- "version": "3.7.10",
3
+ "version": "3.7.11",
4
4
  "description": "Shared components for Harvard DCE apps",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -33,7 +33,8 @@
33
33
  "@fortawesome/react-fontawesome": "^x.x.x",
34
34
  "bootstrap": "^5.x.x",
35
35
  "express": "^x.x.x",
36
- "react": "^x.x.x"
36
+ "react": "^x.x.x",
37
+ "react-dom": "^17.0.2"
37
38
  },
38
39
  "devDependencies": {
39
40
  "@rollup/plugin-commonjs": "^22.0.0",
@@ -19,12 +19,11 @@ import ModalButtonType from '../types/ModalButtonType';
19
19
  import ModalType from '../types/ModalType';
20
20
  import Variant from '../types/Variant';
21
21
  import LogBuiltInMetadata from '../types/LogBuiltInMetadata';
22
- import ModalProps from './Modal/ModalProps';
23
22
 
24
23
  // Import shared components
25
24
  // TODO: fix dependency cycle
26
25
  // eslint-disable-next-line import/no-cycle
27
- import ModalForWrapper from './Modal/ModalForWrapper';
26
+ import ModalForWrapper from './Modal';
28
27
 
29
28
  // Import custom errors
30
29
  import ErrorWithCode from '../errors/ErrorWithCode';
@@ -38,6 +37,7 @@ import {
38
37
  isDarkModeOn,
39
38
  } from '../client/initClient';
40
39
  import waitMs from '../helpers/waitMs';
40
+ import NUM_MODAL_PORTALS from '../constants/NUM_MODAL_PORTALS';
41
41
 
42
42
  /*------------------------------------------------------------------------*/
43
43
  /* -------------------------------- Props ------------------------------- */
@@ -359,99 +359,6 @@ export const showSessionExpiredMessage = async () => {
359
359
  }
360
360
  };
361
361
 
362
- /*----------------------------------------*/
363
- /* --------------- Modals --------------- */
364
- /*----------------------------------------*/
365
-
366
- // Modal tuple with id and props
367
- type ModalTuple = {
368
- // Unique id
369
- id: number,
370
- // Modal props
371
- props: ModalProps,
372
- };
373
-
374
- // Stored copies of setters
375
- let setModals: (modals: ModalTuple[]) => void;
376
-
377
- // Stored copies of modals
378
- let modals: ModalTuple[] = [];
379
-
380
- /**
381
- * Add a modal to the screen
382
- * @author Gabe Abrams
383
- * @param id the uniqueId of the modal
384
- * @param props the props for the modal
385
- */
386
- export const addModal = async (
387
- id: number,
388
- props: ModalProps,
389
- ) => {
390
- // Wait for helper to exist
391
- await waitForHelper(() => {
392
- return !!setModals;
393
- });
394
-
395
- // Add modal
396
- modals.push({
397
- id,
398
- props,
399
- });
400
-
401
- // Update modals
402
- setModals(modals);
403
- };
404
-
405
- /**
406
- * Update a modal on the screen by id (if it exists) with new props
407
- * @author Gabe Abrams
408
- * @param id the uniqueId of the modal
409
- * @param props the new props for the modal
410
- */
411
- export const updateModal = async (
412
- id: number,
413
- props: ModalProps,
414
- ) => {
415
- // Wait for helper to exist
416
- await waitForHelper(() => {
417
- return !!setModals;
418
- });
419
-
420
- // Update modal
421
- modals = modals.map((modal) => {
422
- if (modal.id === id) {
423
- return {
424
- id,
425
- props,
426
- };
427
- }
428
- return modal;
429
- });
430
-
431
- // Update modals
432
- setModals(modals);
433
- };
434
-
435
- /**
436
- * Remove a modal from the screen by id (if it exists)
437
- * @author Gabe Abrams
438
- * @param id the uniqueId of the modal
439
- */
440
- export const removeModal = async (id: number) => {
441
- // Wait for helper to exist
442
- await waitForHelper(() => {
443
- return !!setModals;
444
- });
445
-
446
- // Remove modal
447
- modals = modals.filter((modal) => {
448
- return modal.id !== id;
449
- });
450
-
451
- // Update modals
452
- setModals(modals);
453
- };
454
-
455
362
  /*------------------------------------------------------------------------*/
456
363
  /* -------------------------------- Style ------------------------------- */
457
364
  /*------------------------------------------------------------------------*/
@@ -558,13 +465,6 @@ const AppWrapper: React.FC<Props> = (props: Props): React.ReactElement => {
558
465
  ] = useState<boolean>(false);
559
466
  setSessionHasExpired = setSessionHasExpiredInner;
560
467
 
561
- // Modals
562
- const [
563
- modalsFromState,
564
- setModalsInner,
565
- ] = useState<ModalTuple[]>([]);
566
- setModals = setModalsInner;
567
-
568
468
  /*------------------------------------------------------------------------*/
569
469
  /* ------------------------------- Render ------------------------------- */
570
470
  /*------------------------------------------------------------------------*/
@@ -624,21 +524,19 @@ const AppWrapper: React.FC<Props> = (props: Props): React.ReactElement => {
624
524
  );
625
525
  }
626
526
 
627
- /* ---------- Custom Modals --------- */
628
-
629
- // List of modals added outside reactkit via the Modal component
630
- const customModals: React.ReactNode[] = [];
527
+ /* ------ Custom Modal Portals ------ */
631
528
 
632
- // Add custom modals
633
- modalsFromState.forEach((modalTuple) => {
634
- customModals.push(
635
- <ModalForWrapper
636
- key={String(modalTuple.props.key ?? modalTuple.id)}
637
- // eslint-disable-next-line react/jsx-props-no-spreading
638
- {...modalTuple.props}
529
+ // Custom modal portals
530
+ const customModalPortals: React.ReactNode[] = [];
531
+ for (let i = 0; i < NUM_MODAL_PORTALS; i++) {
532
+ const portalId = `modal-portal-${i}`;
533
+ customModalPortals.push(
534
+ <div
535
+ key={portalId}
536
+ id={portalId}
639
537
  />,
640
538
  );
641
- });
539
+ }
642
540
 
643
541
  /*----------------------------------------*/
644
542
  /* ---------------- Views --------------- */
@@ -801,8 +699,8 @@ const AppWrapper: React.FC<Props> = (props: Props): React.ReactElement => {
801
699
  {/* Modal */}
802
700
  {modal}
803
701
 
804
- {/* Custom Modals */}
805
- {customModals}
702
+ {/* Custom Modal Portals */}
703
+ {customModalPortals}
806
704
 
807
705
  {/* Body */}
808
706
  {body}
@@ -26,7 +26,7 @@ import roundToNumDecimals from '../helpers/roundToNumDecimals';
26
26
  import genCSV from '../helpers/genCSV';
27
27
 
28
28
  // Import shared components
29
- import Modal from './Modal/ModalForWrapper';
29
+ import Modal from './Modal';
30
30
  import ModalType from '../types/ModalType';
31
31
  import CheckboxButton from './CheckboxButton';
32
32
  import CSVDownloadButton from './CSVDownloadButton';