@onehat/ui 0.4.71 → 0.4.73

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 (75) hide show
  1. package/package.json +2 -1
  2. package/src/Components/Buttons/Button.js +20 -6
  3. package/src/Components/Container/ScreenContainer.js +1 -0
  4. package/src/Components/Editor/InlineEditor.js +2 -1
  5. package/src/Components/Form/Field/Color.js +2 -1
  6. package/src/Components/Form/Field/Combo/Combo.js +55 -37
  7. package/src/Components/Form/Field/Combo/MeterTypesCombo.js +4 -2
  8. package/src/Components/Form/Field/Date.js +9 -8
  9. package/src/Components/Form/Field/Input.js +5 -4
  10. package/src/Components/Form/Field/Json.js +3 -2
  11. package/src/Components/Form/Field/TextArea.js +1 -1
  12. package/src/Components/Form/FieldSet.js +1 -1
  13. package/src/Components/Form/Form.js +4 -1
  14. package/src/Components/Gluestack/accordion/index.tsx +5 -1
  15. package/src/Components/Gluestack/actionsheet/index.tsx +5 -1
  16. package/src/Components/Gluestack/alert/index.tsx +5 -1
  17. package/src/Components/Gluestack/badge/index.tsx +5 -1
  18. package/src/Components/Gluestack/button/index.tsx +5 -1
  19. package/src/Components/Gluestack/checkbox/index.tsx +5 -1
  20. package/src/Components/Gluestack/fab/index.tsx +5 -1
  21. package/src/Components/Gluestack/form-control/index.tsx +5 -1
  22. package/src/Components/Gluestack/icon/createIcon.js +74 -0
  23. package/src/Components/Gluestack/icon/index.tsx +46 -88
  24. package/src/Components/Gluestack/input/index.tsx +5 -1
  25. package/src/Components/Gluestack/select/index.tsx +5 -1
  26. package/src/Components/Grid/Grid.js +24 -11
  27. package/src/Components/Grid/GridHeaderRow.js +4 -3
  28. package/src/Components/Grid/GridRow.js +35 -34
  29. package/src/Components/Grid/RowDragHandle.js +25 -10
  30. package/src/Components/Grid/RowHandle.js +55 -0
  31. package/src/{Hooks → Components/Grid}/useAsyncRenderers.js +1 -1
  32. package/src/Components/Hoc/Secondary/withSecondaryData.js +2 -1
  33. package/src/Components/Hoc/Secondary/withSecondaryEditor.js +3 -2
  34. package/src/Components/Hoc/Secondary/withSecondarySelection.js +3 -2
  35. package/src/Components/Hoc/Secondary/withSecondaryValue.js +2 -1
  36. package/src/Components/Hoc/withAlert.js +21 -11
  37. package/src/Components/Hoc/withCollapsible.js +9 -4
  38. package/src/Components/Hoc/withComponent.js +6 -0
  39. package/src/Components/Hoc/withContextMenu.js +6 -0
  40. package/src/Components/Hoc/withData.js +3 -2
  41. package/src/Components/Hoc/withDnd.js +52 -40
  42. package/src/Components/Hoc/withDraggable.js +21 -5
  43. package/src/Components/Hoc/withEditor.js +2 -1
  44. package/src/Components/Hoc/withEvents.js +11 -1
  45. package/src/Components/Hoc/withFilters.js +7 -2
  46. package/src/Components/Hoc/withModal.js +3 -2
  47. package/src/Components/Hoc/withPdfButtons.js +3 -2
  48. package/src/Components/Hoc/withPermissions.js +3 -2
  49. package/src/Components/Hoc/withPresetButtons.js +3 -2
  50. package/src/Components/Hoc/withSelection.js +2 -8
  51. package/src/Components/Hoc/withToast.js +4 -2
  52. package/src/Components/Hoc/withTooltip.js +10 -1
  53. package/src/Components/Hoc/withValue.js +3 -9
  54. package/src/Components/Messages/GlobalModals.js +70 -0
  55. package/src/Components/Messages/Loading.js +2 -2
  56. package/src/Components/Messages/ProgressModal.js +63 -0
  57. package/src/Components/Messages/WaitMessage.js +7 -2
  58. package/src/Components/Report/Report.js +15 -5
  59. package/src/Components/Toolbar/Pagination.js +1 -1
  60. package/src/Components/Toolbar/Toolbar.js +26 -6
  61. package/src/Components/Tree/Tree.js +22 -6
  62. package/src/Components/Tree/TreeNode.js +11 -11
  63. package/src/Components/Tree/TreeNodeDragHandle.js +8 -4
  64. package/src/Components/Viewer/MeterTypeText.js +21 -1
  65. package/src/Components/Viewer/TextWithLinks.js +2 -1
  66. package/src/Constants/Dates.js +5 -2
  67. package/src/Constants/MeterTypes.js +2 -0
  68. package/src/Functions/addIconProps.js +46 -0
  69. package/src/Functions/downloadInBackground.js +47 -7
  70. package/src/Functions/getReport.js +5 -2
  71. package/src/Functions/testProps.js +1 -1
  72. package/src/Functions/trackEngagementHit.js +2 -1
  73. package/src/Hooks/useWhyDidYouUpdate.js +33 -0
  74. package/src/PlatformImports/Web/Attachments.js +1 -1
  75. package/src/Components/Hoc/withBlank.js +0 -10
@@ -7,6 +7,11 @@ import _ from 'lodash';
7
7
 
8
8
  export default function withTooltip(WrappedComponent) {
9
9
  return forwardRef((props, ref) => {
10
+
11
+ if (props.alreadyHasWithTooltip) {
12
+ return <WrappedComponent {...props} ref={ref} />;
13
+ }
14
+
10
15
  const {
11
16
  tooltip,
12
17
  tooltipPlacement = 'bottom',
@@ -16,7 +21,11 @@ export default function withTooltip(WrappedComponent) {
16
21
  ...propsToPass
17
22
  } = props;
18
23
 
19
- let component = <WrappedComponent {...propsToPass} ref={ref} />;
24
+ let component = <WrappedComponent
25
+ {...propsToPass}
26
+ alreadyHasWithTooltip={true}
27
+ ref={ref}
28
+ />;
20
29
 
21
30
  if (tooltip || !_.isEmpty(_tooltip)) {
22
31
  component = <Tooltip
@@ -9,14 +9,7 @@ import _ from 'lodash';
9
9
  export default function withValue(WrappedComponent) {
10
10
  return forwardRef((props, ref) => {
11
11
 
12
- if (props.disableWithValue) {
13
- return <WrappedComponent {...props} ref={ref} />;
14
- }
15
-
16
- if (props.setValue) {
17
- // bypass everything, since we're already using withValue() in hierarchy.
18
- // For example, Combo has withValue(), and intenally it uses Input which also has withValue(),
19
- // but we only need it defined once for the whole thing.
12
+ if (props.disableWithValue || props.alreadyHasWithValue) {
20
13
  return <WrappedComponent {...props} ref={ref} />;
21
14
  }
22
15
 
@@ -143,8 +136,9 @@ export default function withValue(WrappedComponent) {
143
136
 
144
137
  return <WrappedComponent
145
138
  {...props}
146
- ref={ref}
147
139
  disableWithValue={false}
140
+ alreadyHasWithValue={true}
141
+ ref={ref}
148
142
  value={convertedValue}
149
143
  setValue={setValueRef.current}
150
144
  onChangeSelection={onChangeSelection}
@@ -0,0 +1,70 @@
1
+
2
+ import { useSelector, useDispatch, } from 'react-redux';
3
+ import {
4
+ selectIsWaitModalShown,
5
+ selectAlertMessage,
6
+ selectDebugMessage,
7
+ selectInfoMessage,
8
+ selectWaitMessage,
9
+ setAlertMessage,
10
+ setDebugMessage,
11
+ setInfoMessage,
12
+ selectProgressMessage,
13
+ selectProgressPercentage,
14
+ } from '@src/models/Slices/DebugSlice';
15
+ import WaitMessage from './WaitMessage';
16
+ import ErrorMessage from './ErrorMessage';
17
+ import ProgressModal from './ProgressModal';
18
+
19
+
20
+
21
+ export default function GlobalModals(props) {
22
+ const {
23
+ progressColor = '#666',
24
+ } = props,
25
+ dispatch = useDispatch(),
26
+ isWaitModalShown = useSelector(selectIsWaitModalShown),
27
+ alertMessage = useSelector(selectAlertMessage),
28
+ debugMessage = useSelector(selectDebugMessage),
29
+ infoMessage = useSelector(selectInfoMessage),
30
+ waitMessage = useSelector(selectWaitMessage),
31
+ progressMessage = useSelector(selectProgressMessage),
32
+ progressPercentage = useSelector(selectProgressPercentage);
33
+
34
+ let moduleToShow = null;
35
+
36
+ if (debugMessage) {
37
+ moduleToShow =
38
+ <ErrorMessage
39
+ text={debugMessage}
40
+ onOk={() => dispatch(setDebugMessage(null))}
41
+ color="green"
42
+ />;
43
+ } else if (alertMessage) {
44
+ moduleToShow =
45
+ <ErrorMessage
46
+ text={alertMessage}
47
+ onOk={() => dispatch(setAlertMessage(null))}
48
+ />;
49
+ } else if (infoMessage) {
50
+ moduleToShow =
51
+ <ErrorMessage
52
+ text={infoMessage}
53
+ onOk={() => dispatch(setInfoMessage(null))}
54
+ color="#000"
55
+ />;
56
+ }
57
+ if (isWaitModalShown) {
58
+ moduleToShow = <WaitMessage text={waitMessage} />;
59
+ }
60
+ if (progressMessage && progressPercentage < 100) {
61
+ moduleToShow = <ProgressModal
62
+ progressMessage={progressMessage}
63
+ progressPercentage={progressPercentage}
64
+ color={progressColor}
65
+ />;
66
+ }
67
+
68
+ return moduleToShow;
69
+ }
70
+
@@ -10,14 +10,14 @@ import ScreenContainer from '../Container/ScreenContainer.js';
10
10
  export default function Loading(props) {
11
11
 
12
12
  if (props.isScreen) {
13
- return <ScreenContainer {...props}>
13
+ return <ScreenContainer className="h-full w-full" {...props}>
14
14
  <HStack className="flex-1 justify-center items-center">
15
15
  <Spinner className="text-primary-500 mr-1" />
16
16
  <Text>Loading</Text>
17
17
  </HStack>
18
18
  </ScreenContainer>;
19
19
  }
20
- return <HStackNative {...props} className="justify-center min-h-[100px]">
20
+ return <HStackNative {...props} className="justify-center min-h-[100px] h-full w-full">
21
21
  <Spinner className="flex-1 text-primary-500" />
22
22
  </HStackNative>;
23
23
  }
@@ -0,0 +1,63 @@
1
+ import { useState, useEffect, } from 'react';import {
2
+ HStack,
3
+ Modal, ModalBackdrop, ModalHeader, ModalContent, ModalCloseButton, ModalBody, ModalFooter,
4
+ Spinner,
5
+ Text,
6
+ VStack,
7
+ } from '@project-components/Gluestack';
8
+ import clsx from 'clsx';
9
+ import { useSelector } from 'react-redux';
10
+ import * as Progress from 'react-native-progress';
11
+ import testProps from '../../Functions/testProps';
12
+
13
+ let progressTimeout = null;
14
+
15
+ export default function ProgressModal(props) {
16
+ const {
17
+ progressMessage,
18
+ progressPercentage,
19
+ color = '#666',
20
+ } = props,
21
+ [progressBarWidth, setProgressBarWidth] = useState(175),
22
+ [isInited, setIsInited] = useState(false);
23
+
24
+ return <Modal
25
+ {...testProps('ProgressModal')}
26
+ isOpen={true}
27
+ className="Modal"
28
+ aria-disabled={true}
29
+ >
30
+ <ModalBackdrop />
31
+ <ModalContent
32
+ className={clsx(
33
+ 'ModalContent',
34
+ 'max-w-[400px]',
35
+ 'shadow-lg',
36
+ )}
37
+ >
38
+ <VStack
39
+ className={clsx(
40
+ 'VStack',
41
+ 'w-[90%]',
42
+ 'items-center',
43
+ 'justify-center',
44
+ 'self-center',
45
+ )}
46
+ onLayout={(e) => {
47
+ setProgressBarWidth(e.nativeEvent.layout.width);
48
+ setIsInited(true);
49
+ }}
50
+ >
51
+ <Text className="text-black mb-2">{progressMessage}</Text>
52
+ {isInited &&
53
+ <Progress.Bar
54
+ animated={false}
55
+ progress={progressPercentage / 100}
56
+ width={progressBarWidth}
57
+ height={20}
58
+ color={color}
59
+ />}
60
+ </VStack>
61
+ </ModalContent>
62
+ </Modal>;
63
+ }
@@ -5,6 +5,11 @@ import {
5
5
  Text,
6
6
  } from '@project-components/Gluestack';
7
7
  import clsx from 'clsx';
8
+ import {
9
+ CURRENT_MODE,
10
+ UI_MODE_WEB,
11
+ UI_MODE_NATIVE,
12
+ } from '../../Constants/UiModes.js';
8
13
  import testProps from '../../Functions/testProps.js';
9
14
 
10
15
  export default function WaitMessage(props) {
@@ -19,14 +24,14 @@ export default function WaitMessage(props) {
19
24
  {...testProps('WaitMessage')}
20
25
  isOpen={true}
21
26
  className="Modal"
22
- aria-disabled="true"
27
+ aria-disabled={true}
23
28
  >
24
29
  <ModalBackdrop />
25
30
  <ModalContent
26
31
  className={clsx(
27
32
  'ModalContent',
28
33
  'w-[200px]',
29
- 'h-[50px]',
34
+ CURRENT_MODE === UI_MODE_WEB ? 'h-[50px]' : '',
30
35
  'shadow-lg',
31
36
  )}
32
37
  >
@@ -41,6 +41,7 @@ function Report(props) {
41
41
  disableExcel = false,
42
42
  showReportHeaders = true,
43
43
  isQuickReport = false,
44
+ additionalData = {},
44
45
  quickReportData = {},
45
46
  alert,
46
47
  } = props,
@@ -50,7 +51,10 @@ function Report(props) {
50
51
  reportId,
51
52
  reportType: REPORT_TYPES__EXCEL,
52
53
  showReportHeaders,
53
- data: quickReportData,
54
+ data: {
55
+ ...additionalData,
56
+ ...quickReportData,
57
+ },
54
58
  });
55
59
  },
56
60
  downloadReport = (args) => {
@@ -74,8 +78,8 @@ function Report(props) {
74
78
 
75
79
  if (isQuickReport) {
76
80
  let className = clsx(
77
- 'Report',
78
- 'max-w-[100px]',
81
+ 'QuickReport',
82
+ 'flex-1',
79
83
  'm-2',
80
84
  );
81
85
  if (props.className) {
@@ -122,7 +126,10 @@ function Report(props) {
122
126
  icon: Excel,
123
127
  onPress: (data) => downloadReport({
124
128
  reportId,
125
- data,
129
+ data: {
130
+ ...data,
131
+ ...additionalData,
132
+ },
126
133
  reportType: REPORT_TYPES__EXCEL,
127
134
  showReportHeaders,
128
135
  }),
@@ -137,7 +144,10 @@ function Report(props) {
137
144
  icon: Pdf,
138
145
  onPress: (data) => downloadReport({
139
146
  reportId,
140
- data,
147
+ data: {
148
+ ...data,
149
+ ...additionalData,
150
+ },
141
151
  reportType: REPORT_TYPES__PDF,
142
152
  showReportHeaders,
143
153
  }),
@@ -212,7 +212,7 @@ export default function Pagination(props) {
212
212
  'Pagination',
213
213
  'items-center',
214
214
  'shrink-0',
215
- 'gap-2',
215
+ 'gap-1',
216
216
  )}
217
217
  >
218
218
  {items}
@@ -1,7 +1,12 @@
1
1
  import {
2
2
  HStackNative,
3
+ ScrollView,
3
4
  } from '@project-components/Gluestack';
4
5
  import clsx from 'clsx';
6
+ import {
7
+ CURRENT_MODE,
8
+ UI_MODE_NATIVE,
9
+ } from '../../Constants/UiModes.js';
5
10
  import UiGlobals from '../../UiGlobals.js';
6
11
 
7
12
  export default function Toolbar(props) {
@@ -20,13 +25,28 @@ export default function Toolbar(props) {
20
25
  'border-b-grey-400',
21
26
  styles.TOOLBAR_CLASSNAME,
22
27
  );
28
+ if (CURRENT_MODE === UI_MODE_NATIVE) {
29
+ className += ' min-w-[100%]';
30
+ }
23
31
  if (props.className) {
24
32
  className += ' ' + props.className
25
33
  }
26
- return <HStackNative
27
- className={className}
28
- style={props.style || {}}
29
- >
30
- {props.children}
31
- </HStackNative>;
34
+ let toolbar = <HStackNative
35
+ className={className}
36
+ style={props.style || {}}
37
+ >
38
+ {props.children}
39
+ </HStackNative>;
40
+
41
+ if (CURRENT_MODE === UI_MODE_NATIVE) {
42
+ toolbar = <ScrollView
43
+ horizontal={true}
44
+ className={clsx(
45
+ 'min-w-[100%]',
46
+ 'max-h-[50px]',
47
+ )}
48
+ >{toolbar}</ScrollView>;
49
+ }
50
+
51
+ return toolbar;
32
52
  };
@@ -1088,17 +1088,26 @@ function TreeComponent(props) {
1088
1088
  id: item.id,
1089
1089
  item,
1090
1090
  getSelection,
1091
+ isInSelection,
1091
1092
  type: nodeDragSourceType,
1093
+ onDragStart: () => {
1094
+ if (!isInSelection(item)) { // get updated isSelected (will be stale if using one in closure)
1095
+ // reset the selection to just this one node if it's not already selected
1096
+ setSelection([item]);
1097
+ }
1098
+ },
1092
1099
  };
1093
1100
 
1094
1101
  // Prevent root nodes from being dragged, and use custom logic if provided
1095
1102
  nodeDragProps.canDrag = (monitor) => {
1096
1103
  const currentSelection = getSelection();
1097
1104
 
1098
- // Check if any selected node is a root node (can't drag root nodes)
1099
- const hasRootNode = currentSelection.some(node => node.isRoot);
1100
- if (hasRootNode) {
1101
- return false;
1105
+ if (isInSelection(item)) {
1106
+ // make sure root node is not selected (can't drag root nodes)
1107
+ const hasRootNode = currentSelection.some(node => node.isRoot);
1108
+ if (hasRootNode) {
1109
+ return false;
1110
+ }
1102
1111
  }
1103
1112
 
1104
1113
  // Use custom drag validation if provided
@@ -1118,7 +1127,7 @@ function TreeComponent(props) {
1118
1127
  // Add drag preview rendering
1119
1128
  nodeDragProps.getDragProxy = getCustomDragProxy ?
1120
1129
  (dragItem) => getCustomDragProxy(item, getSelection()) :
1121
- null; // Let GlobalDragProxy handle the default case
1130
+ null; // let GlobalDragProxy handle the default case
1122
1131
 
1123
1132
  const dropTargetAccept = 'internal';
1124
1133
  nodeDragProps.isDropTarget = true;
@@ -1178,15 +1187,22 @@ function TreeComponent(props) {
1178
1187
  nodeDragProps.isDragSource = !item.isRoot; // Root nodes cannot be dragged
1179
1188
  nodeDragProps.dragSourceType = nodeDragSourceType;
1180
1189
  if (getNodeDragSourceItem) {
1181
- nodeDragProps.dragSourceItem = getNodeDragSourceItem(item, getSelection, nodeDragSourceType);
1190
+ nodeDragProps.dragSourceItem = getNodeDragSourceItem(item, getSelection, isInSelection, nodeDragSourceType);
1182
1191
  } else {
1183
1192
  nodeDragProps.dragSourceItem = {
1184
1193
  id: item.id,
1185
1194
  item,
1186
1195
  getSelection,
1196
+ isInSelection,
1187
1197
  type: nodeDragSourceType,
1188
1198
  };
1189
1199
  }
1200
+ nodeDragProps.dragSourceItem.onDragStart = () => {
1201
+ if (!isInSelection(item)) { // get updated isSelected (will be stale if using one in closure)
1202
+ // reset the selection to just this one node if it's not already selected
1203
+ setSelection([item]);
1204
+ }
1205
+ };
1190
1206
  if (canNodeMoveExternally) {
1191
1207
  nodeDragProps.canDrag = canNodeMoveExternally;
1192
1208
  }
@@ -16,7 +16,7 @@ import UiGlobals from '../../UiGlobals.js';
16
16
  import withDraggable from '../Hoc/withDraggable.js';
17
17
  import IconButton from '../Buttons/IconButton.js';
18
18
  import { withDragSource, withDropTarget } from '../Hoc/withDnd.js';
19
- import TreeNodeDragHandle from './TreeNodeDragHandle.js';
19
+ import RowHandle from '../Grid/RowHandle.js';
20
20
  import testProps from '../../Functions/testProps.js';
21
21
  import ChevronRight from '../Icons/ChevronRight.js';
22
22
  import ChevronDown from '../Icons/ChevronDown.js';
@@ -40,11 +40,13 @@ export default function TreeNode(props) {
40
40
  nodeProps = {},
41
41
  onToggle,
42
42
  bg,
43
+ isDraggable,
43
44
  isDragSource,
44
45
  isHovered,
45
46
  isHighlighted,
46
47
  isOver,
47
48
  isSelected,
49
+ showSelectHandle,
48
50
  canDrop,
49
51
  draggedItem,
50
52
  validateDrop, // same as canDrop (for visual feedback)
@@ -144,19 +146,21 @@ export default function TreeNode(props) {
144
146
  backgroundColor: bg,
145
147
  }}
146
148
  ref={(element) => {
147
- // Attach both drag and drop refs to the same element
148
- if (dragSourceRef && typeof dragSourceRef === 'function') {
149
- dragSourceRef(element);
150
- }
151
149
  if (dropTargetRef && dropTargetRef.current !== undefined) {
152
150
  // dropTargetRef is a ref object, not a callback
153
151
  dropTargetRef.current = element;
154
152
  }
155
153
  }}
156
154
  >
157
- {isPhantom && <Box t={0} l={0} className="absolute bg-[#f00] h-[2px] w-[2px]" />}
155
+ {isPhantom && <Box className="absolute t-0 l-0 bg-[#f00] h-[2px] w-[2px]" />}
158
156
 
159
- {isDragSource && <TreeNodeDragHandle />}
157
+ {(isDragSource || showSelectHandle) &&
158
+ <RowHandle
159
+ ref={dragSourceRef}
160
+ isDragSource={isDragSource}
161
+ isDraggable={isDraggable}
162
+ showSelectHandle={showSelectHandle}
163
+ />}
160
164
 
161
165
  {hasChildren && <IconButton
162
166
  {...testProps('expandBtn')}
@@ -180,12 +184,8 @@ export default function TreeNode(props) {
180
184
  'flex',
181
185
  'flex-1',
182
186
  'text-ellipsis',
183
- 'select-none',
184
187
  styles.TREE_NODE_CLASSNAME,
185
188
  )}
186
- style={{
187
- userSelect: 'none',
188
- }}
189
189
  >{text}</TextNative>}
190
190
 
191
191
  {content}
@@ -1,3 +1,4 @@
1
+ import { forwardRef } from 'react';
1
2
  import {
2
3
  Icon,
3
4
  VStack,
@@ -6,11 +7,11 @@ import clsx from 'clsx';
6
7
  import styles from '../../Styles/StyleSheets.js';
7
8
  import GripVertical from '../Icons/GripVertical.js';
8
9
 
9
- function TreeNodeDragHandle(props) {
10
+ const TreeNodeDragHandle = forwardRef(function(props, ref) {
10
11
  let className = clsx(
11
12
  'TreeNodeDragHandle',
12
13
  'h-full',
13
- 'w-[14px]',
14
+ 'w-[17px]',
14
15
  'px-[2px]',
15
16
  'border-l-2',
16
17
  'items-center',
@@ -21,14 +22,17 @@ function TreeNodeDragHandle(props) {
21
22
  className += ' ' + props.className;
22
23
  }
23
24
  return <VStack
25
+ {...props}
26
+ ref={ref}
24
27
  style={styles.ewResize}
25
28
  className={className}
26
29
  >
27
30
  <Icon
28
31
  as={GripVertical}
29
32
  size="xs"
30
- className="handle w-full h-full text-[#ccc]" />
33
+ className="handle w-full h-full text-[#ccc]"
34
+ />
31
35
  </VStack>;
32
- }
36
+ });
33
37
 
34
38
  export default TreeNodeDragHandle;
@@ -2,6 +2,13 @@ import {
2
2
  TextNative,
3
3
  } from '@project-components/Gluestack';
4
4
  import clsx from 'clsx';
5
+ import {
6
+ METER_TYPES__HOURS,
7
+ METER_TYPES__MILES,
8
+ METER_TYPES__HOURS_TEXT,
9
+ METER_TYPES__MILES_TEXT,
10
+ } from '../../Constants/MeterTypes';
11
+
5
12
  import UiGlobals from '../../UiGlobals';
6
13
 
7
14
  export default function MeterTypeText(props) {
@@ -17,8 +24,21 @@ export default function MeterTypeText(props) {
17
24
  if (props.className) {
18
25
  className += ' ' + props.className;
19
26
  }
27
+ let meterType = '';
28
+ switch(props.value) {
29
+ case METER_TYPES__HOURS:
30
+ meterType = METER_TYPES__HOURS_TEXT;
31
+ break;
32
+ case METER_TYPES__MILES:
33
+ meterType = METER_TYPES__MILES_TEXT;
34
+ break;
35
+ default:
36
+ meterType = 'unknown';
37
+ break;
38
+ }
39
+
20
40
  return <TextNative
21
41
  {...props}
22
42
  className={className}
23
- >{props.value ? 'Time (hrs)' : 'Distance (mi/km)'}</TextNative>;
43
+ >{meterType}</TextNative>;
24
44
  };
@@ -8,6 +8,7 @@ import {
8
8
  } from '@project-components/Gluestack';
9
9
  import clsx from 'clsx';
10
10
  import {
11
+ CURRENT_MODE,
11
12
  UI_MODE_WEB,
12
13
  } from '../../Constants/UiModes.js';
13
14
  import UiGlobals from '../../UiGlobals.js';
@@ -78,7 +79,7 @@ function TextWithLinksElement(props) {
78
79
  };
79
80
 
80
81
  const elementProps = {};
81
- if (UiGlobals.mode === UI_MODE_WEB) {
82
+ if (CURRENT_MODE === UI_MODE_WEB) {
82
83
  elementProps.textOverflow = 'ellipsis';
83
84
  }
84
85
  let className = clsx(
@@ -10,8 +10,11 @@ export const ONE_MONTH_AGO = moment().add(-1, 'months');
10
10
  export const TWO_MONTHS_AGO = moment().add(-2, 'months');
11
11
  export const SIX_MONTHS_AGO = moment().add(-6, 'months');
12
12
  export const ONE_MONTH_FROM_NOW = moment().add(1, 'months');
13
+ export const START_OF_THIS_MONTH = moment().startOf('months');
14
+ export const END_OF_LAST_MONTH = moment().subtract(1, 'months').endOf('month');
13
15
  export const ONE_YEAR_AGO = moment().add(-1, 'years');
14
16
  export const MOMENT_DATE_FORMAT_1 = 'YYYY-MM-DD HH:mm:ss';
15
- export const MOMENT_DATE_FORMAT_2 = 'MMMM Do YYYY, h:mm:ss a';
16
- export const MOMENT_DATE_FORMAT_3 = 'h:mm A';
17
+ export const MOMENT_DATE_FORMAT_2 = 'MMMM Do YYYY, h:mm:ss a'; // pretty datetime
18
+ export const MOMENT_DATE_FORMAT_3 = 'h:mm A'; // pretty time
17
19
  export const MOMENT_DATE_FORMAT_4 = 'YYYY-MM-DD';
20
+ export const MOMENT_DATE_FORMAT_5 = 'HH:mm:ss';
@@ -1,2 +1,4 @@
1
1
  export const METER_TYPES__HOURS = 1;
2
2
  export const METER_TYPES__MILES = 2;
3
+ export const METER_TYPES__HOURS_TEXT = 'Time (hrs)';
4
+ export const METER_TYPES__MILES_TEXT = 'Distance (mi/km)';
@@ -0,0 +1,46 @@
1
+
2
+ import clsx from 'clsx';
3
+ import {
4
+ UI_MODE_WEB,
5
+ UI_MODE_NATIVE,
6
+ CURRENT_MODE,
7
+ } from '../Constants/UiModes.js';
8
+ import _ from 'lodash';
9
+
10
+ export default function addIconProps(iconProps = {}) {
11
+
12
+ iconProps = _.cloneDeep(iconProps); // avoid mutating the original props, as they may be submitted to multiple components
13
+
14
+ iconProps.className = clsx(
15
+ 'Icon',
16
+ iconProps.className,
17
+ );
18
+
19
+ if (CURRENT_MODE === UI_MODE_WEB) {
20
+ return iconProps;
21
+ }
22
+
23
+ // native only
24
+
25
+ // marginx
26
+ iconProps.style = {
27
+ marginHorizontal: 8,
28
+ ...iconProps.style,
29
+ };
30
+
31
+ // On native, react-native-svg ignores className and will only size the icon based on
32
+ // explicit width / height props (or size if the wrapper supports it).
33
+ // If no size set, it falls back to the full intrinsic viewBox size, so we need to ensure we set a default size.
34
+ // If you want to override the size, pass width and height props to the icon.
35
+ if (iconProps.width || iconProps.height) {
36
+ return iconProps;
37
+ }
38
+ const nativeDefaults = {
39
+ width: 24,
40
+ height: 24,
41
+ };
42
+ return {
43
+ ...nativeDefaults,
44
+ ...iconProps,
45
+ };
46
+ }