dce-reactkit 5.0.7 → 5.0.9

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.
@@ -0,0 +1,20 @@
1
+ import BackButtonController from '../types/BackButtonController';
2
+ /**
3
+ * Controller for driving back navigation from anywhere in the app. Requires
4
+ * useBackButton to have been called in the top-level app
5
+ * @author Yuen Ler Chow
6
+ */
7
+ export declare const backButtonController: BackButtonController;
8
+ /**
9
+ * Hook that makes the browser's back button navigate within the app instead of
10
+ * leaving it. Call this once in your top-level app, then use
11
+ * backButtonController to enter subpanels and describe their state.
12
+ *
13
+ * Assumes a single level of navigation: one home screen plus subpanels that the
14
+ * user returns home from.
15
+ * @author Yuen Ler Chow
16
+ * @param handleGoHomeFunc handler that performs the app state changes required
17
+ * to return to the home screen
18
+ */
19
+ declare const useBackButton: (handleGoHomeFunc: () => void) => void;
20
+ export default useBackButton;
@@ -22,6 +22,8 @@ export declare const _setStubResponse: (opts: {
22
22
  * @param opts.path - the path of the server endpoint
23
23
  * @param [opts.method=GET] - the method of the endpoint
24
24
  * @param [opts.params] - query/body parameters to include
25
+ * @param [opts.headers] - custom headers to include; values must already be
26
+ * string to avoid issue with header serialization
25
27
  * @returns response from server
26
28
  */
27
29
  declare const visitServerEndpoint: (opts: {
@@ -30,5 +32,8 @@ declare const visitServerEndpoint: (opts: {
30
32
  params?: {
31
33
  [x: string]: any;
32
34
  } | undefined;
35
+ headers?: {
36
+ [x: string]: string;
37
+ } | undefined;
33
38
  }) => Promise<any>;
34
39
  export default visitServerEndpoint;
@@ -37,6 +37,7 @@ import isMobileOrTablet from './helpers/isMobileOrTablet';
37
37
  import makeLinksClickable from './helpers/makeLinksClickable';
38
38
  import combineClassNames from './helpers/combineClassNames';
39
39
  import useForceRender from './helpers/useForceRender';
40
+ import useBackButton, { backButtonController } from './helpers/useBackButton';
40
41
  import isSelectAdmin from './helpers/isSelectAdmin';
41
42
  import ModalButtonType from './types/ModalButtonType';
42
43
  import ModalSize from './types/ModalSize';
@@ -45,8 +46,10 @@ import Variant from './types/Variant';
45
46
  import IntelliTableColumn from './types/IntelliTableColumn';
46
47
  import DropdownItemType from './types/DropdownItemType';
47
48
  import ProgressBarSize from './types/ProgressBarSize';
49
+ import BackState from './types/BackState';
50
+ import BackButtonController from './types/BackButtonController';
48
51
  import PickableItem from './components/ItemPicker/types/PickableItem';
49
52
  import DBEntry from './components/DBEntryManagerPanel/types/DBEntry';
50
53
  import DBEntryField from './components/DBEntryManagerPanel/types/DBEntryField';
51
54
  import DBEntryFieldType from './components/DBEntryManagerPanel/types/DBEntryFieldType';
52
- export { AppWrapper, LoadingSpinner, ErrorBox, Modal, TabBox, RadioButton, CheckboxButton, ButtonInputGroup, SimpleDateChooser, SimpleMonthChooser, SimpleTimeChooser, Drawer, PopSuccessMark, PopFailureMark, PopPendingMark, CopiableBox, ItemPicker, LogReviewer, IntelliTable, CSVDownloadButton, DBEntryManagerPanel, Tooltip, ToggleSwitch, AutoscrollToBottomContainer, MultiSwitch, Dropdown, ProgressBar, FakeProgressBar, alert, prompt, confirm, showFatalError, DynamicWord, stubServerEndpoint, canReviewLogs, isMobileOrTablet, makeLinksClickable, isSelectAdmin, initClient, visitServerEndpoint, logClientEvent, addFatalErrorHandler, leaveToURL, combineClassNames, useForceRender, setClientEventMetadataPopulator, ModalButtonType, ModalSize, ModalType, Variant, IntelliTableColumn, DropdownItemType, LogReviewerFilterState, ProgressBarSize, PickableItem, DBEntry, DBEntryField, DBEntryFieldType, ErrorWithCode, MINUTE_IN_MS, HOUR_IN_MS, DAY_IN_MS, LOG_REVIEW_ROUTE_PATH_PREFIX, LOG_ROUTE_PATH, LOG_REVIEW_STATUS_ROUTE, LOG_REVIEW_GET_LOGS_ROUTE, SELECT_ADMIN_CHECK_ROUTE, abbreviate, avg, ceilToNumDecimals, floorToNumDecimals, forceNumIntoBounds, padDecimalZeros, padZerosLeft, roundToNumDecimals, sum, waitMs, getOrdinal, getTimeInfoInET, getMondayOfTimestamp, startMinWait, getHumanReadableDate, getPartOfDay, stringsToHumanReadableList, onlyKeepLetters, parallelLimit, getMonthName, genCSV, extractProp, compareArraysByProp, getLocalTimeInfo, genCommaList, validateEmail, validatePhoneNumber, validateString, idify, prefixWithAOrAn, everyAsync, filterAsync, forEachAsync, mapAsync, someAsync, capitalize, shuffleArray, getWordCount, cloneDeep, getTimestampFromTimeInfoInET, spaceAtCapitals, ParamType, DayOfWeek, Log, LogType, LogSource, LogAction, LogBuiltInMetadata, LogMetadataType, LogFunction, LogTypeSpecificInfo, LogMainInfo, LogSourceSpecificInfo, LogLevel, CommonKitErrorCode, };
55
+ export { AppWrapper, LoadingSpinner, ErrorBox, Modal, TabBox, RadioButton, CheckboxButton, ButtonInputGroup, SimpleDateChooser, SimpleMonthChooser, SimpleTimeChooser, Drawer, PopSuccessMark, PopFailureMark, PopPendingMark, CopiableBox, ItemPicker, LogReviewer, IntelliTable, CSVDownloadButton, DBEntryManagerPanel, Tooltip, ToggleSwitch, AutoscrollToBottomContainer, MultiSwitch, Dropdown, ProgressBar, FakeProgressBar, alert, prompt, confirm, showFatalError, DynamicWord, stubServerEndpoint, canReviewLogs, isMobileOrTablet, makeLinksClickable, isSelectAdmin, initClient, visitServerEndpoint, logClientEvent, addFatalErrorHandler, leaveToURL, combineClassNames, useForceRender, useBackButton, backButtonController, setClientEventMetadataPopulator, ModalButtonType, ModalSize, ModalType, Variant, IntelliTableColumn, DropdownItemType, LogReviewerFilterState, ProgressBarSize, BackState, BackButtonController, PickableItem, DBEntry, DBEntryField, DBEntryFieldType, ErrorWithCode, MINUTE_IN_MS, HOUR_IN_MS, DAY_IN_MS, LOG_REVIEW_ROUTE_PATH_PREFIX, LOG_ROUTE_PATH, LOG_REVIEW_STATUS_ROUTE, LOG_REVIEW_GET_LOGS_ROUTE, SELECT_ADMIN_CHECK_ROUTE, abbreviate, avg, ceilToNumDecimals, floorToNumDecimals, forceNumIntoBounds, padDecimalZeros, padZerosLeft, roundToNumDecimals, sum, waitMs, getOrdinal, getTimeInfoInET, getMondayOfTimestamp, startMinWait, getHumanReadableDate, getPartOfDay, stringsToHumanReadableList, onlyKeepLetters, parallelLimit, getMonthName, genCSV, extractProp, compareArraysByProp, getLocalTimeInfo, genCommaList, validateEmail, validatePhoneNumber, validateString, idify, prefixWithAOrAn, everyAsync, filterAsync, forEachAsync, mapAsync, someAsync, capitalize, shuffleArray, getWordCount, cloneDeep, getTimestampFromTimeInfoInET, spaceAtCapitals, ParamType, DayOfWeek, Log, LogType, LogSource, LogAction, LogBuiltInMetadata, LogMetadataType, LogFunction, LogTypeSpecificInfo, LogMainInfo, LogSourceSpecificInfo, LogLevel, CommonKitErrorCode, };
@@ -0,0 +1,40 @@
1
+ import BackState from './BackState';
2
+ /**
3
+ * Controller for the back button, used to drive back navigation from anywhere
4
+ * in the app. Pass this to subpanels so they can describe their state and
5
+ * send the user home.
6
+ * @author Yuen Ler Chow
7
+ */
8
+ type BackButtonController = {
9
+ /**
10
+ * Call this when the user navigates to a child of the home screen (something
11
+ * they can come back from)
12
+ */
13
+ onSubpanelEntered: () => void;
14
+ /**
15
+ * Send the user back to the home screen
16
+ * @param [force] if true, go home immediately without checking the subpanel
17
+ * state (no confirmation, not blocked). If falsy, nothing happens when
18
+ * blocked and confirmation is required when there are unsaved changes
19
+ */
20
+ goHome: (force?: boolean) => Promise<void>;
21
+ /**
22
+ * Set the state of the current subpanel, which determines what happens when
23
+ * the user tries to go back
24
+ * @param newSubpanelState the new state of the subpanel
25
+ */
26
+ setSubpanelState: (newSubpanelState: BackState) => void;
27
+ /**
28
+ * Set the confirmation message shown if the user tries to go back while there
29
+ * are unsaved changes (cleared upon returning to the home screen)
30
+ * @param message the message to show
31
+ */
32
+ setCustomUnsavedChangesMessage: (message: string) => void;
33
+ /**
34
+ * Set the message shown if the user tries to go back while blocked (cleared
35
+ * upon returning to the home screen)
36
+ * @param message the message to show
37
+ */
38
+ setCustomBlockedMessage: (message: string) => void;
39
+ };
40
+ export default BackButtonController;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * State of the current subpanel, determining what happens when the user tries
3
+ * to go back to the home screen
4
+ * @author Yuen Ler Chow
5
+ */
6
+ declare enum BackState {
7
+ Normal = "Normal",
8
+ UnsavedChanges = "UnsavedChanges",
9
+ Blocked = "Blocked"
10
+ }
11
+ export default BackState;
package/dist/index.d.ts CHANGED
@@ -865,6 +865,8 @@ declare const initClient: (opts: ({
865
865
  * @param opts.path - the path of the server endpoint
866
866
  * @param [opts.method=GET] - the method of the endpoint
867
867
  * @param [opts.params] - query/body parameters to include
868
+ * @param [opts.headers] - custom headers to include; values must already be
869
+ * string to avoid issue with header serialization
868
870
  * @returns response from server
869
871
  */
870
872
  declare const visitServerEndpoint: (opts: {
@@ -873,6 +875,9 @@ declare const visitServerEndpoint: (opts: {
873
875
  params?: {
874
876
  [x: string]: any;
875
877
  } | undefined;
878
+ headers?: {
879
+ [x: string]: string;
880
+ } | undefined;
876
881
  }) => Promise<any>;
877
882
 
878
883
  /**
@@ -962,6 +967,75 @@ declare const combineClassNames: (classNames: (string | undefined | null | false
962
967
  */
963
968
  declare const useForceRender: (useReducer: any) => () => void;
964
969
 
970
+ /**
971
+ * State of the current subpanel, determining what happens when the user tries
972
+ * to go back to the home screen
973
+ * @author Yuen Ler Chow
974
+ */
975
+ declare enum BackState {
976
+ Normal = "Normal",
977
+ UnsavedChanges = "UnsavedChanges",
978
+ Blocked = "Blocked"
979
+ }
980
+
981
+ /**
982
+ * Controller for the back button, used to drive back navigation from anywhere
983
+ * in the app. Pass this to subpanels so they can describe their state and
984
+ * send the user home.
985
+ * @author Yuen Ler Chow
986
+ */
987
+ type BackButtonController = {
988
+ /**
989
+ * Call this when the user navigates to a child of the home screen (something
990
+ * they can come back from)
991
+ */
992
+ onSubpanelEntered: () => void;
993
+ /**
994
+ * Send the user back to the home screen
995
+ * @param [force] if true, go home immediately without checking the subpanel
996
+ * state (no confirmation, not blocked). If falsy, nothing happens when
997
+ * blocked and confirmation is required when there are unsaved changes
998
+ */
999
+ goHome: (force?: boolean) => Promise<void>;
1000
+ /**
1001
+ * Set the state of the current subpanel, which determines what happens when
1002
+ * the user tries to go back
1003
+ * @param newSubpanelState the new state of the subpanel
1004
+ */
1005
+ setSubpanelState: (newSubpanelState: BackState) => void;
1006
+ /**
1007
+ * Set the confirmation message shown if the user tries to go back while there
1008
+ * are unsaved changes (cleared upon returning to the home screen)
1009
+ * @param message the message to show
1010
+ */
1011
+ setCustomUnsavedChangesMessage: (message: string) => void;
1012
+ /**
1013
+ * Set the message shown if the user tries to go back while blocked (cleared
1014
+ * upon returning to the home screen)
1015
+ * @param message the message to show
1016
+ */
1017
+ setCustomBlockedMessage: (message: string) => void;
1018
+ };
1019
+
1020
+ /**
1021
+ * Controller for driving back navigation from anywhere in the app. Requires
1022
+ * useBackButton to have been called in the top-level app
1023
+ * @author Yuen Ler Chow
1024
+ */
1025
+ declare const backButtonController: BackButtonController;
1026
+ /**
1027
+ * Hook that makes the browser's back button navigate within the app instead of
1028
+ * leaving it. Call this once in your top-level app, then use
1029
+ * backButtonController to enter subpanels and describe their state.
1030
+ *
1031
+ * Assumes a single level of navigation: one home screen plus subpanels that the
1032
+ * user returns home from.
1033
+ * @author Yuen Ler Chow
1034
+ * @param handleGoHomeFunc handler that performs the app state changes required
1035
+ * to return to the home screen
1036
+ */
1037
+ declare const useBackButton: (handleGoHomeFunc: () => void) => void;
1038
+
965
1039
  /**
966
1040
  * Checks if the current user is a select admin
967
1041
  * @author Gardenia Liu
@@ -969,4 +1043,4 @@ declare const useForceRender: (useReducer: any) => () => void;
969
1043
  */
970
1044
  declare const isSelectAdmin: () => Promise<boolean>;
971
1045
 
972
- export { AppWrapper, AutoscrollToBottomContainer, ButtonInputGroup, CSVDownloadButton, CheckboxButton, CopiableBox, DBEntry, DBEntryField, DBEntryFieldType, DBEntryManagerPanel, Drawer, Dropdown, DropdownItemType, DynamicWord, ErrorBox, FakeProgressBar, IntelliTable, IntelliTableColumn, ItemPicker, LoadingSpinner, LogReviewer, Modal, ModalButtonType, ModalSize, ModalType, MultiSwitch, PickableItem, PopFailureMark, PopPendingMark, PopSuccessMark, ProgressBar, ProgressBarSize, RadioButton, SimpleDateChooser, SimpleMonthChooser, SimpleTimeChooser, TabBox, ToggleSwitch, Tooltip, Variant, addFatalErrorHandler, alert, canReviewLogs, combineClassNames, confirm, initClient, isMobileOrTablet, isSelectAdmin, leaveToURL, logClientEvent, makeLinksClickable, prompt, setClientEventMetadataPopulator, showFatalError, stubServerEndpoint, useForceRender, visitServerEndpoint };
1046
+ export { AppWrapper, AutoscrollToBottomContainer, BackButtonController, BackState, ButtonInputGroup, CSVDownloadButton, CheckboxButton, CopiableBox, DBEntry, DBEntryField, DBEntryFieldType, DBEntryManagerPanel, Drawer, Dropdown, DropdownItemType, DynamicWord, ErrorBox, FakeProgressBar, IntelliTable, IntelliTableColumn, ItemPicker, LoadingSpinner, LogReviewer, Modal, ModalButtonType, ModalSize, ModalType, MultiSwitch, PickableItem, PopFailureMark, PopPendingMark, PopSuccessMark, ProgressBar, ProgressBarSize, RadioButton, SimpleDateChooser, SimpleMonthChooser, SimpleTimeChooser, TabBox, ToggleSwitch, Tooltip, Variant, addFatalErrorHandler, alert, backButtonController, canReviewLogs, combineClassNames, confirm, initClient, isMobileOrTablet, isSelectAdmin, leaveToURL, logClientEvent, makeLinksClickable, prompt, setClientEventMetadataPopulator, showFatalError, stubServerEndpoint, useBackButton, useForceRender, visitServerEndpoint };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dce-reactkit",
3
- "version": "5.0.7",
3
+ "version": "5.0.9",
4
4
  "description": "Shared components for Harvard DCE apps",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -258,48 +258,50 @@ const NestableItemList: React.FC<Props> = (props) => {
258
258
 
259
259
  return (
260
260
  <div key={item.id}>
261
- {/* Dropdown Button */}
262
- <span
263
- className="NestableItemList-dropdown-button-container d-inline-block"
264
- style={{
265
- minWidth: '2rem',
266
- }}
267
- >
268
- {item.isGroup && (
269
- <button
270
- className={`NestableItemList-dropdown-button NestableItemList-dropdown-button-${item.id}`}
271
- style={{
272
- border: 0,
273
- backgroundColor: 'transparent',
274
- }}
275
- type="button"
276
- onClick={() => {
277
- dispatch({
278
- type: ActionType.ToggleChild,
279
- id: item.id,
280
- });
281
- }}
282
- aria-label={`${childExpanded[item.id] ? 'Hide' : 'Show'} items in ${accessibleName}`}
283
- >
284
- <FontAwesomeIcon
285
- icon={childExpanded[item.id] ? faChevronDown : faChevronRight}
286
- />
287
- </button>
288
- )}
289
- </span>
290
-
291
- {/* Checkbox and Text (optionally wrapped in a tooltip) */}
292
- {
293
- item.tooltip
294
- ? (
295
- <Tooltip text={item.tooltip}>
296
- <span className="d-inline-block">
297
- {checkbox}
298
- </span>
299
- </Tooltip>
300
- )
301
- : checkbox
302
- }
261
+ <div className="NestableItemList-item d-flex align-items-center">
262
+ {/* Dropdown Button */}
263
+ <span
264
+ className="NestableItemList-dropdown-button-container"
265
+ style={{
266
+ minWidth: '2rem',
267
+ }}
268
+ >
269
+ {item.isGroup && (
270
+ <button
271
+ className={`NestableItemList-dropdown-button NestableItemList-dropdown-button-${item.id}`}
272
+ style={{
273
+ border: 0,
274
+ backgroundColor: 'transparent',
275
+ }}
276
+ type="button"
277
+ onClick={() => {
278
+ dispatch({
279
+ type: ActionType.ToggleChild,
280
+ id: item.id,
281
+ });
282
+ }}
283
+ aria-label={`${childExpanded[item.id] ? 'Hide' : 'Show'} items in ${accessibleName}`}
284
+ >
285
+ <FontAwesomeIcon
286
+ icon={childExpanded[item.id] ? faChevronDown : faChevronRight}
287
+ />
288
+ </button>
289
+ )}
290
+ </span>
291
+
292
+ {/* Checkbox and Text (optionally wrapped in a tooltip) */}
293
+ {
294
+ item.tooltip
295
+ ? (
296
+ <Tooltip text={item.tooltip}>
297
+ <span className="d-inline-block">
298
+ {checkbox}
299
+ </span>
300
+ </Tooltip>
301
+ )
302
+ : checkbox
303
+ }
304
+ </div>
303
305
 
304
306
  {/* Children */}
305
307
  {(item.isGroup && childExpanded[item.id]) && (
@@ -63,6 +63,14 @@ const Tooltip: React.FC<Props> = (props) => {
63
63
  // Import bootstrap tooltip
64
64
  const BSTooltip = (await import('bootstrap')).Tooltip;
65
65
 
66
+ // The child may have unmounted while the dynamic import above was
67
+ // resolving (React nulls the ref on unmount). Constructing a
68
+ // Bootstrap tooltip with a null element causes an error,
69
+ // so bail out instead
70
+ if (!childRef.current) {
71
+ return;
72
+ }
73
+
66
74
  // Initialize
67
75
  t = new BSTooltip(
68
76
  childRef.current,
@@ -78,6 +86,15 @@ const Tooltip: React.FC<Props> = (props) => {
78
86
  return () => {
79
87
  if (t) {
80
88
  t.dispose();
89
+ // Bootstrap's hide() queues a transition-end callback that can
90
+ // fire AFTER dispose and touch the (now null) trigger map and
91
+ // element (twbs/bootstrap issue #37474). Point those private
92
+ // fields at harmless stand-ins so the late callback is a no-op
93
+ // instead of a crash.
94
+ /* eslint-disable no-underscore-dangle */
95
+ t._activeTrigger = {};
96
+ t._element = document.createElement('noscript');
97
+ /* eslint-enable no-underscore-dangle */
81
98
  }
82
99
  };
83
100
  },