@onehat/ui 0.4.9 → 0.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/ui",
3
- "version": "0.4.9",
3
+ "version": "0.4.11",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -55,6 +55,7 @@ export function ComboComponent(props) {
55
55
  isEditor = false,
56
56
  isDisabled = false,
57
57
  isInTag = false,
58
+ minimizeForRow = false,
58
59
  tooltipPlacement = 'bottom',
59
60
  placeholder,
60
61
  onRowPress,
@@ -542,28 +543,29 @@ export function ComboComponent(props) {
542
543
  `}
543
544
  />;
544
545
  }
546
+ const triggerClassName = `
547
+ Combo-trigger
548
+ h-full
549
+ border
550
+ border-l-0
551
+ border-gray-400
552
+ rounded-l-none
553
+ rounded-r-md
554
+ ${styles.FORM_COMBO_TRIGGER_BG}
555
+ ${styles.FORM_COMBO_TRIGGER_BG_HOVER}
556
+ `;
545
557
  trigger = <IconButton
546
558
  {...testProps('trigger')}
547
559
  ref={triggerRef}
548
560
  icon={CaretDown}
549
561
  _icon={{
550
- size: 'sm',
562
+ size: 'md',
551
563
  className: 'text-grey-500',
552
564
  }}
553
565
  isDisabled={isDisabled}
554
566
  onPress={onTriggerPress}
555
567
  onBlur={onTriggerBlur}
556
- className={`
557
- trigger
558
- h-full
559
- border
560
- border-l-0
561
- border-gray-400
562
- rounded-l-none
563
- rounded-r-md
564
- ${styles.FORM_COMBO_TRIGGER_BG}
565
- ${styles.FORM_COMBO_TRIGGER_BG_HOVER}
566
- `}
568
+ className={triggerClassName}
567
569
  />;
568
570
 
569
571
  if (UiGlobals.mode === UI_MODE_WEB) {
@@ -619,6 +621,7 @@ export function ComboComponent(props) {
619
621
  grow
620
622
  h-full
621
623
  min-h-0
624
+ max-h-[40px]
622
625
  flex-1
623
626
  m-0
624
627
  rounded-tr-none
@@ -1009,16 +1012,19 @@ export function ComboComponent(props) {
1009
1012
  refProps.ref = tooltipRef;
1010
1013
  }
1011
1014
 
1012
- const className = `
1015
+ let className = `
1013
1016
  Combo-HStack
1014
1017
  flex-1
1015
1018
  h-[40px]
1016
1019
  min-h-[40px]
1017
1020
  justify-center
1018
- items-center
1021
+ items-stretch
1019
1022
  `;
1020
1023
  if (props.className) {
1021
- props.className += ' ' + className;
1024
+ className += ' ' + props.className;
1025
+ }
1026
+ if (minimizeForRow) {
1027
+ className += ' h-auto min-h-0 max-h-[40px]';
1022
1028
  }
1023
1029
 
1024
1030
  if (isRendered && additionalButtons?.length && containerWidth < 500) {
@@ -48,6 +48,7 @@ export const DateElement = forwardRef((props, ref) => {
48
48
  _input = {},
49
49
  isDisabled = false,
50
50
  limitWidth = false,
51
+ minimizeForRow = false,
51
52
  minValue,
52
53
  maxValue,
53
54
  testID,
@@ -219,7 +220,6 @@ export const DateElement = forwardRef((props, ref) => {
219
220
  }
220
221
  };
221
222
 
222
-
223
223
  useEffect(() => {
224
224
 
225
225
  // When value changes from outside, adjust text value
@@ -372,8 +372,7 @@ export const DateElement = forwardRef((props, ref) => {
372
372
  flex-1
373
373
  h-full
374
374
  m-0
375
- rounded-tr-none
376
- rounded-br-none
375
+ rounded-r-lg
377
376
  ${styles.FORM_DATE_INPUT_BG}
378
377
  ${styles.FORM_DATE_INPUT_BG_FOCUS}
379
378
  ${styles.FORM_DATE_READOUT_FONTSIZE}
@@ -576,6 +575,9 @@ export const DateElement = forwardRef((props, ref) => {
576
575
  if (props.className) {
577
576
  className += props.className;
578
577
  }
578
+ if (minimizeForRow) {
579
+ className += ' h-auto min-h-0 max-h-[50px]';
580
+ }
579
581
  const style = props.style || {};
580
582
  if (!_.isNil(height)) {
581
583
  style.height = height;
@@ -30,6 +30,7 @@ const InputElement = forwardRef((props, ref) => {
30
30
  rightIcon,
31
31
  rightIconHandler,
32
32
  placeholder,
33
+ className,
33
34
  ...propsToPass
34
35
  } = props,
35
36
  styles = UiGlobals.styles,
@@ -109,10 +110,6 @@ const InputElement = forwardRef((props, ref) => {
109
110
  if (!disableAutoFlex && !hasWidth(props) && !hasFlex(props)) {
110
111
  style.flex = 1;
111
112
  }
112
- // flex-1
113
- // block
114
- // h-auto
115
- // h-[10px]
116
113
  let inputClassName = `
117
114
  Input
118
115
  ${styles.FORM_INPUT_BG}
@@ -125,15 +122,14 @@ const InputElement = forwardRef((props, ref) => {
125
122
  h-auto
126
123
  w-full
127
124
  p-2
128
- text-left
125
+ text-center
129
126
  ${styles.FORM_INPUT_FONTSIZE}
130
127
  ${styles.FORM_INPUT_BG}
131
128
  ${styles.FORM_INPUT_BG_FOCUS}
132
129
  ${styles.FORM_INPUT_BG_HOVER}
133
130
  `;
134
- if (props.className) {
135
- inputClassName += props.className;
136
- inputFieldClassName += props.className;
131
+ if (className) {
132
+ inputClassName += className;
137
133
  }
138
134
 
139
135
  return <Input
@@ -30,6 +30,7 @@ const
30
30
  maxValue = 100,
31
31
  step = 10,
32
32
  autoSubmitDelay = UiGlobals.autoSubmitDelay,
33
+ minimizeForRow = false,
33
34
  tooltip = null,
34
35
  isDisabled = false,
35
36
  testID,
@@ -150,12 +151,24 @@ const
150
151
  }
151
152
 
152
153
  let className = `
153
- w-full
154
- items-center
155
- `;
154
+ w-full
155
+ items-center
156
+ `,
157
+ inputClassName = `
158
+ InputWithTooltip
159
+ h-full
160
+ w-[60px]
161
+ mr-4
162
+ text-center
163
+ rounded-md
164
+ ${styles.SLIDER_READOUT_FONTSIZE}
165
+ `;
156
166
  if (props.className) {
157
167
  className += ' ' + props.className;
158
168
  }
169
+ if (minimizeForRow) {
170
+ inputClassName += ' h-auto min-h-0 max-h-[50px] mr-1';
171
+ }
159
172
 
160
173
  return <HStack
161
174
  className={className}
@@ -168,16 +181,7 @@ const
168
181
  onKeyPress={onInputKeyPress}
169
182
  isDisabled={isDisabled}
170
183
  disableAutoFlex={true}
171
- className={`
172
- InputWithTooltip
173
- h-full
174
- w-[50px]
175
- p-2
176
- mr-4
177
- text-center
178
- rounded-md
179
- ${styles.SLIDER_READOUT_FONTSIZE}
180
- `}
184
+ className={inputClassName}
181
185
  {...props._input}
182
186
  />
183
187
  <HStack className="flex-1">
@@ -22,7 +22,6 @@ function TagComponent(props) {
22
22
  isViewOnly = false,
23
23
  isValueAlwaysArray,
24
24
  isValueAsStringifiedJson,
25
- isFilter = false,
26
25
  minimizeForRow = false,
27
26
  Editor,
28
27
  _combo = {},
@@ -286,12 +285,20 @@ function TagComponent(props) {
286
285
  ${styles.FORM_TAG_PADDING}
287
286
  `,
288
287
  comboClassName = '';
288
+ if (_combo.className) {
289
+ comboClassName = _combo.className;
290
+ }
289
291
  if (minimizeForRow) {
290
- valueBoxesClassName += ' h-auto min-h-0 flex-1 max-h-[50px] overflow-auto';
291
- comboClassName += ' h-auto min-h-0 flex-1';
292
+ if (isViewOnly) {
293
+ // combo is not shown, so allow valueBoxes to take up more space
294
+ valueBoxesClassName += ' h-auto min-h-[50px] max-h-[50px] overflow-auto flex-1';
295
+ } else {
296
+ // shrink both down
297
+ valueBoxesClassName += ' h-auto min-h-[25px] max-h-[25px] overflow-auto flex-1';
298
+ comboClassName += ' h-auto min-h-0 max-h-[25px] flex-1';
299
+ }
292
300
  }
293
301
 
294
-
295
302
  return <VStack
296
303
  className={className}
297
304
  style={style}
@@ -311,6 +318,7 @@ function TagComponent(props) {
311
318
  tooltip={tooltip}
312
319
  usePermissions={props.usePermissions}
313
320
  {..._combo}
321
+ className={comboClassName}
314
322
  />}
315
323
  </VStack>;
316
324
 
@@ -91,7 +91,8 @@ const
91
91
  inputClassName += ' ' + props.className;
92
92
  }
93
93
  if (minimizeForRow) {
94
- textareaClassName += ' max-h-[50px] overflow-auto';
94
+ textareaClassName += ' h-auto min-h-0 max-h-[40px] overflow-auto';
95
+ inputClassName += ' py-0';
95
96
  }
96
97
 
97
98
  return <Textarea className={textareaClassName}>
@@ -76,7 +76,7 @@ export default function FieldSet(props) {
76
76
  }
77
77
  };
78
78
 
79
- const className = `
79
+ let className = `
80
80
  FieldSet-Box
81
81
  mb-4
82
82
  mx-0
@@ -86,7 +86,7 @@ export default function FieldSet(props) {
86
86
  ${styles.FORM_FIELDSET_BG}
87
87
  `;
88
88
  if (props.className) {
89
- props.className += className;
89
+ className += props.className;
90
90
  }
91
91
 
92
92
 
@@ -315,6 +315,7 @@ function Form(props) {
315
315
  let element = <Element
316
316
  {...testProps('field-' + fieldName)}
317
317
  value={value}
318
+ minimizeForRow={true}
318
319
  parent={self}
319
320
  reference={fieldName}
320
321
  {...configPropsToPass}
@@ -1150,16 +1151,15 @@ function Form(props) {
1150
1151
  if (!isEditorViewOnly && !hideResetButton) {
1151
1152
  showResetBtn = true;
1152
1153
  }
1153
- if (editorType !== EDITOR_TYPE__SIDE) { // side editor won't show either close or cancel buttons!
1154
- // determine whether we should show the close or cancel button
1154
+ // determine whether we should show the close or cancel button
1155
+ if (editorType !== EDITOR_TYPE__SIDE) {
1155
1156
  if (isEditorViewOnly) {
1156
1157
  showCloseBtn = true;
1157
1158
  } else {
1158
- const formIsDirty = formState.isDirty;
1159
1159
  // if (editorType === EDITOR_TYPE__WINDOWED && onCancel) {
1160
1160
  // showCancelBtn = true;
1161
1161
  // }
1162
- if (formIsDirty || isPhantom) {
1162
+ if (formState.isDirty || isPhantom) {
1163
1163
  if (isSingle && onCancel) {
1164
1164
  showCancelBtn = true;
1165
1165
  }
@@ -1169,6 +1169,11 @@ function Form(props) {
1169
1169
  }
1170
1170
  }
1171
1171
  }
1172
+ } else {
1173
+ // side editor only
1174
+ if (isPhantom && isSingle && onCancel) {
1175
+ showCancelBtn = true;
1176
+ }
1172
1177
  }
1173
1178
  if (!isEditorViewOnly && onSave) {
1174
1179
  showSaveBtn = true;
@@ -1200,7 +1205,6 @@ function Form(props) {
1200
1205
  key="resetBtn"
1201
1206
  onPress={() => doReset()}
1202
1207
  icon={Rotate}
1203
- className="mr-2"
1204
1208
  isDisabled={!formState.isDirty}
1205
1209
  />}
1206
1210
 
@@ -1208,9 +1212,9 @@ function Form(props) {
1208
1212
  <Button
1209
1213
  {...testProps('cancelBtn')}
1210
1214
  key="cancelBtn"
1211
- variant="outline"
1215
+ variant={editorType === EDITOR_TYPE__INLINE ? 'solid' : 'outline'}
1212
1216
  onPress={onCancel}
1213
- className="text-white mr-2"
1217
+ className="text-white"
1214
1218
  text="Cancel"
1215
1219
  />}
1216
1220
 
@@ -1218,9 +1222,9 @@ function Form(props) {
1218
1222
  <Button
1219
1223
  {...testProps('closeBtn')}
1220
1224
  key="closeBtn"
1221
- variant="outline"
1225
+ variant={editorType === EDITOR_TYPE__INLINE ? 'solid' : 'outline'}
1222
1226
  onPress={onClose}
1223
- className="text-white mr-2"
1227
+ className="text-white"
1224
1228
  text="Close"
1225
1229
  />}
1226
1230
 
@@ -1272,6 +1276,7 @@ function Form(props) {
1272
1276
  w-[100px]
1273
1277
  min-w-[300px]
1274
1278
  py-2
1279
+ gap-2
1275
1280
  justify-center
1276
1281
  items-center
1277
1282
  rounded-b-lg
@@ -1282,8 +1287,11 @@ function Form(props) {
1282
1287
  </Box>;
1283
1288
  } else {
1284
1289
  if (!disableFooter) {
1285
- let footerClassName = '';
1286
- footerClassName += ' justify-end';
1290
+ let footerClassName = `
1291
+ Form-Footer
1292
+ justify-end
1293
+ gap-2
1294
+ `;
1287
1295
  if (editorType === EDITOR_TYPE__INLINE) {
1288
1296
  footerClassName += `
1289
1297
  sticky
@@ -107,6 +107,7 @@ const
107
107
 
108
108
  function GridComponent(props) {
109
109
  const {
110
+
110
111
  columnsConfig = [], // json configurations for each column
111
112
  columnProps = {},
112
113
  defaultHiddenColumns = [],
@@ -1177,13 +1178,14 @@ function GridComponent(props) {
1177
1178
  />;
1178
1179
 
1179
1180
  if (CURRENT_MODE === UI_MODE_WEB) {
1181
+ // fix scrolling bug on nested FlatLists (inner one would not scroll without this)
1180
1182
  grid = <ScrollView
1181
1183
  horizontal={false}
1182
- className="ScrollView"
1184
+ className="ScrollView overflow-auto"
1183
1185
  contentContainerStyle={{
1184
1186
  height: '100%',
1185
1187
  }}
1186
- >{grid}</ScrollView>; // fix scrolling bug on nested FlatLists
1188
+ >{grid}</ScrollView>;
1187
1189
  } else
1188
1190
  if (CURRENT_MODE === UI_MODE_NATIVE) {
1189
1191
  grid = <ScrollView className="flex-1 w-full">{grid}</ScrollView>
@@ -250,8 +250,8 @@ function GridRow(props) {
250
250
  className={`
251
251
  GridRow-phantom
252
252
  absolute
253
- h-[2px]
254
- w-[2px]
253
+ h-2
254
+ w-2
255
255
  top-0
256
256
  left-0
257
257
  bg-[#f00]
@@ -310,14 +310,12 @@ function GridRow(props) {
310
310
  if (isOnlyOneVisibleColumn) {
311
311
  rowClassName += ' w-full';
312
312
  }
313
- if (isOver) {
314
- rowClassName += ' border-4 border-[#0ff]';
315
- } else {
316
- rowClassName += ' border-b border-b-grey-100';
317
- }
318
313
  if (rowProps?.className) {
319
314
  rowClassName += ' ' + rowProps.className;
320
315
  }
316
+ if (isOver) {
317
+ rowClassName += ' border-4 border-[#0ff]';
318
+ }
321
319
  return <HStackNative
322
320
  {...testProps('row' + (isSelected ? '-selected' : ''))}
323
321
  {...rowProps}
@@ -105,7 +105,9 @@ function withAlert(WrappedComponent) {
105
105
  }),
106
106
  onOk: () => {
107
107
  hideModal();
108
- onOk();
108
+ if (onOk) {
109
+ onOk();
110
+ }
109
111
  },
110
112
  includeCancel,
111
113
  canClose,
@@ -188,7 +188,7 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
188
188
  case ADD:
189
189
  key = 'addBtn';
190
190
  text = 'Add';
191
- handler = onAdd;
191
+ handler = (parent, e) => onAdd();
192
192
  icon = Plus;
193
193
  if (selectorId && !selectorSelected) {
194
194
  isDisabled = true;
@@ -200,7 +200,7 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
200
200
  case EDIT:
201
201
  key = 'editBtn';
202
202
  text = 'Edit';
203
- handler = onEdit;
203
+ handler = (parent, e) => onEdit();
204
204
  icon = Edit;
205
205
  if (selectorId && !selectorSelected) {
206
206
  isDisabled = true;
@@ -216,6 +216,7 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
216
216
  key = 'deleteBtn';
217
217
  text = 'Delete';
218
218
  handler = onDelete;
219
+ handler = (parent, e) => onDelete();
219
220
  icon = Trash;
220
221
  if (selectorId && !selectorSelected) {
221
222
  isDisabled = true;
@@ -236,7 +237,7 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
236
237
  case VIEW:
237
238
  key = 'viewBtn';
238
239
  text = 'View';
239
- handler = onView;
240
+ handler = (parent, e) => onView();
240
241
  icon = Eye;
241
242
  isDisabled = !selection.length || selection.length !== 1;
242
243
  if (selectorId && !selectorSelected) {
@@ -249,7 +250,7 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
249
250
  case COPY:
250
251
  key = 'copyBtn';
251
252
  text = 'Copy to Clipboard';
252
- handler = onCopyToClipboard;
253
+ handler = (parent, e) => onCopyToClipboard();
253
254
  icon = Clipboard;
254
255
  isDisabled = !selection.length;
255
256
  if (selectorId && !selectorSelected) {
@@ -262,7 +263,7 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
262
263
  case DUPLICATE:
263
264
  key = 'duplicateBtn';
264
265
  text = 'Duplicate';
265
- handler = onDuplicate;
266
+ handler = (parent, e) => onDuplicate();
266
267
  icon = Duplicate;
267
268
  isDisabled = !selection.length || selection.length !== 1;
268
269
  if (selectorId && !selectorSelected) {
@@ -283,7 +284,7 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
283
284
  case UPLOAD_DOWNLOAD:
284
285
  key = 'uploadDownloadBtn';
285
286
  text = 'Upload/Download';
286
- handler = onUploadDownload;
287
+ handler = (parent, e) => onUploadDownload();
287
288
  icon = UploadDownload;
288
289
  break;
289
290
  default:
@@ -137,13 +137,12 @@ function Panel(props) {
137
137
  className={`
138
138
  Panel-VSstack
139
139
  flex-1
140
- flex
141
140
  w-full
142
141
  overflow-hidden
143
142
  `}
144
143
  >
145
144
  {isScrollable ?
146
- <ScrollView className="ScrollView">
145
+ <ScrollView className="Panel-ScrollView">
147
146
  {children}
148
147
  </ScrollView> :
149
148
  children}
@@ -1,9 +1,11 @@
1
- import React from 'react';
1
+ import { cloneElement, isValidElement } from 'react';
2
2
  import {
3
+ Box,
3
4
  HStack,
4
5
  Icon,
5
6
  Text,
6
7
  VStack,
8
+ VStackNative,
7
9
  } from '@project-components/Gluestack';
8
10
  import { EDITOR_TYPE__PLAIN } from '../../Constants/Editor';
9
11
  import {
@@ -41,15 +43,14 @@ function Report(props) {
41
43
  buttons = [];
42
44
 
43
45
  const propsIcon = props._icon || {};
44
- propsIcon.size = 60;
45
- propsIcon.px = 5;
46
+ propsIcon.className = 'w-full h-full text-primary-500';
46
47
  let icon = props.icon;
47
48
  if (_.isEmpty(icon)) {
48
49
  icon = ChartLine;
49
50
  }
50
- if (React.isValidElement(icon)) {
51
+ if (isValidElement(icon)) {
51
52
  if (!_.isEmpty(propsIcon)) {
52
- icon = React.cloneElement(icon, {...propsIcon});
53
+ icon = cloneElement(icon, {...propsIcon});
53
54
  }
54
55
  } else {
55
56
  icon = <Icon as={icon} {...propsIcon} />;
@@ -60,14 +61,13 @@ function Report(props) {
60
61
  ...testProps('excelBtn'),
61
62
  key: 'excelBtn',
62
63
  text: 'Download Excel',
63
- leftIcon: <Icon as={Excel} size="md" className="text-white" />,
64
+ icon: Excel,
64
65
  onPress: (data) => getReport({
65
66
  reportId,
66
67
  data,
67
68
  reportType: REPORT_TYPES__EXCEL,
68
69
  showReportHeaders,
69
70
  }),
70
- ml: 1,
71
71
  });
72
72
  }
73
73
  if (!disablePdf) {
@@ -75,22 +75,30 @@ function Report(props) {
75
75
  ...testProps('pdfBtn'),
76
76
  key: 'pdfBtn',
77
77
  text: 'Download PDF',
78
- leftIcon: <Icon as={Pdf} size="md" className="text-white" />,
78
+ icon: Pdf,
79
79
  onPress: (data) => getReport({
80
80
  reportId,
81
81
  data,
82
82
  reportType: REPORT_TYPES__PDF,
83
83
  showReportHeaders,
84
84
  }),
85
- ml: 1,
86
85
  });
87
86
  }
88
- return <VStack
87
+ return <VStackNative
89
88
  {...testProps('Report-' + reportId)}
90
- className="w-full border border-primary-300 pt-4 mb-3"
89
+ className={`
90
+ w-full
91
+ border
92
+ border-primary-300
93
+ p-4
94
+ mb-3
95
+ rounded-lg
96
+ `}
91
97
  >
92
98
  <HStack>
93
- {icon && <VStack>{icon}</VStack>}
99
+ <Box className="w-[50px] mr-4">
100
+ {icon}
101
+ </Box>
94
102
  <VStack className="flex-1">
95
103
  <Text className="text-2xl max-w-full">{title}</Text>
96
104
  <Text className="text-sm">{description}</Text>
@@ -101,7 +109,7 @@ function Report(props) {
101
109
  additionalFooterButtons={buttons}
102
110
  {...props._form}
103
111
  />
104
- </VStack>;
112
+ </VStackNative>;
105
113
  }
106
114
 
107
115
  export default withComponent(Report);
@@ -362,14 +362,17 @@ function Viewer(props) {
362
362
  canEdit = false;
363
363
  }
364
364
 
365
- let className = 'Viewer-VStackNative';
365
+ let className = `
366
+ Viewer-VStackNative
367
+ h-full
368
+ bg-white
369
+ `;
366
370
  if (props.className) {
367
371
  className += ' ' + props.className;
368
372
  }
369
373
 
370
374
  return <VStackNative
371
375
  {...testProps(self)}
372
- {...props}
373
376
  className={className}
374
377
  onLayout={onLayout}
375
378
  >
@@ -379,9 +382,10 @@ function Viewer(props) {
379
382
  _web={{ height: 1 }}
380
383
  ref={scrollViewRef}
381
384
  className={`
382
- ScrollView
385
+ Viewer-ScrollView
383
386
  w-full
384
387
  pb-1
388
+ flex-1
385
389
  `}
386
390
  >
387
391
  {canEdit && onEditMode &&