@onehat/ui 0.3.100 → 0.3.103

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.3.100",
3
+ "version": "0.3.103",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -296,6 +296,7 @@ function Form(props) {
296
296
  onChange: onEditorChange,
297
297
  useSelectorId = false,
298
298
  isHidden = false,
299
+ getDynamicProps,
299
300
  ...propsToPass
300
301
  } = item,
301
302
  editorTypeProps = {};
@@ -459,6 +460,10 @@ function Form(props) {
459
460
  if (propsToPass.selectorId || editorTypeProps.selectorId) { // editorTypeProps.selectorId causes just this one field to use selectorId
460
461
  editorTypeProps.selectorSelected = record;
461
462
  }
463
+ let dynamicProps = {};
464
+ if (getDynamicProps) {
465
+ dynamicProps = getDynamicProps({ fieldState, formSetValue, formGetValues, formState });
466
+ }
462
467
  let element = <Element
463
468
  name={name}
464
469
  value={value}
@@ -478,6 +483,7 @@ function Form(props) {
478
483
  {...defaults}
479
484
  {...propsToPass}
480
485
  {...editorTypeProps}
486
+ {...dynamicProps}
481
487
  />;
482
488
  if (editorType !== EDITOR_TYPE__INLINE) {
483
489
  let message = null;
@@ -13,8 +13,10 @@ import {
13
13
  ALERT_MODE_YES,
14
14
  ALERT_MODE_YES_NO,
15
15
  ALERT_MODE_CUSTOM,
16
+ ALERT_MODE_INFO,
16
17
  } from '../../Constants/Alert.js';
17
18
  import TriangleExclamation from '../Icons/TriangleExclamation.js';
19
+ import CircleInfo from '../Icons/CircleInfo.js';
18
20
  import _ from 'lodash';
19
21
 
20
22
  export default function withAlert(WrappedComponent) {
@@ -77,6 +79,15 @@ export default function withAlert(WrappedComponent) {
77
79
  onCancel = () => {
78
80
  setIsAlertShown(false);
79
81
  },
82
+ onInfo = (msg) => {
83
+ clearAll();
84
+ setMode(ALERT_MODE_INFO);
85
+ setTitle('Info');
86
+ setMessage(msg);
87
+ setIncludeCancel(false);
88
+ setCanClose(true);
89
+ showAlert();
90
+ },
80
91
  onOk = () => {
81
92
  if (okCallback) {
82
93
  okCallback();
@@ -122,6 +133,7 @@ export default function withAlert(WrappedComponent) {
122
133
  }
123
134
  switch(mode) {
124
135
  case ALERT_MODE_OK:
136
+ case ALERT_MODE_INFO:
125
137
  buttons.push(<Button
126
138
  key="okBtn"
127
139
  ref={autoFocusRef}
@@ -171,8 +183,8 @@ export default function withAlert(WrappedComponent) {
171
183
  alert={onAlert}
172
184
  confirm={onConfirm}
173
185
  hideAlert={hideAlert}
186
+ showInfo={onInfo}
174
187
  />
175
-
176
188
  <AlertDialog
177
189
  leastDestructiveRef={cancelRef}
178
190
  isOpen={isAlertShown}
@@ -182,9 +194,9 @@ export default function withAlert(WrappedComponent) {
182
194
  {canClose && <AlertDialog.CloseButton />}
183
195
  <AlertDialog.Header>{title}</AlertDialog.Header>
184
196
  <AlertDialog.Body>
185
- <Row>
197
+ <Row alignItems="center">
186
198
  <Column w="40px" p={0} mr={5}>
187
- <Icon as={TriangleExclamation} size={10} color="#f00" />
199
+ <Icon as={mode === ALERT_MODE_INFO ? CircleInfo : TriangleExclamation} size={10} color={mode === ALERT_MODE_INFO ? '#000' : '#f00'} />
188
200
  </Column>
189
201
  <Text flex={1}>{message}</Text>
190
202
  </Row>
@@ -265,11 +265,10 @@ export default function withFilters(WrappedComponent) {
265
265
  field,
266
266
  type: filterType,
267
267
  title,
268
- } = filter,
269
-
270
- propertyDef = Repository.getSchema().getPropertyDefinition(field);
268
+ } = filter;
271
269
 
272
270
  if (!title) {
271
+ const propertyDef = Repository.getSchema().getPropertyDefinition(field);
273
272
  title = propertyDef?.title;
274
273
  }
275
274
 
@@ -328,7 +327,7 @@ export default function withFilters(WrappedComponent) {
328
327
 
329
328
  if (!isReady) {
330
329
  const savedFilters = await getSaved(id + '-filters');
331
- if (!_.isEmpty(savedFilters)) {
330
+ if (!_.isEmpty(savedFilters) && !isUsingCustomFilters) {
332
331
  // load saved filters
333
332
  filtersToUse = savedFilters;
334
333
  setFilters(savedFilters, true, false); // false to skip save
@@ -337,7 +336,7 @@ export default function withFilters(WrappedComponent) {
337
336
 
338
337
  if (isUsingCustomFilters) {
339
338
  _.each(filtersToUse, (filter) => {
340
- const repoFiltersFromFilter = filter.getRepoFilters(value);
339
+ const repoFiltersFromFilter = filter.getRepoFilters(filter.value);
341
340
  _.each(repoFiltersFromFilter, (repoFilter) => { // one custom filter might generate multiple filters for the repository
342
341
  newRepoFilters.push(repoFilter);
343
342
  });
@@ -410,10 +409,12 @@ export default function withFilters(WrappedComponent) {
410
409
  const
411
410
  renderedFilters = renderFilters(),
412
411
  hasFilters = !!renderedFilters.length;
413
- topToolbar = <Toolbar justifyContent="space-between" alignItems="center">
414
- <Text pr={2} userSelect="none">Filters:{hasFilters ? '' : ' None'}</Text>
415
- {renderedFilters}
416
- <Row flex={hasFilters ? null : 1} justifyContent="flex-end">
412
+ topToolbar = <Toolbar>
413
+ <Row flex={1} alignItems="center">
414
+ <Text pr={2} userSelect="none">Filters:{hasFilters ? '' : ' None'}</Text>
415
+ {renderedFilters}
416
+ </Row>
417
+ <Row flex={hasFilters ? null : 1} alignItems="center" alignSelf="flex-end">
417
418
  <IconButton
418
419
  key="clear"
419
420
  _icon={{
@@ -0,0 +1,23 @@
1
+ // Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc.
2
+ import * as React from "react"
3
+ import Svg, { Path } from "react-native-svg"
4
+ import { Icon } from 'native-base';
5
+
6
+ function SvgComponent(props) {
7
+ return (
8
+ <Icon
9
+ xmlns="http://www.w3.org/2000/svg"
10
+ height={16}
11
+ width={14}
12
+ viewBox="0 0 448 512"
13
+ {...props}
14
+ >
15
+ <Path
16
+ fill="#1E3050"
17
+ d="M224 0c-17.7 0-32 14.3-32 32v19.2C119 66 64 130.6 64 208v18.8c0 47-17.3 92.4-48.5 127.6l-7.4 8.3c-8.4 9.4-10.4 22.9-5.3 34.4S19.4 416 32 416h384c12.6 0 24-7.4 29.2-18.9s3.1-25-5.3-34.4l-7.4-8.3c-31.2-35.2-48.5-80.5-48.5-127.6V208c0-77.4-55-142-128-156.8V32c0-17.7-14.3-32-32-32zm45.3 493.3c12-12 18.7-28.3 18.7-45.3H160c0 17 6.7 33.3 18.7 45.3S207 512 224 512s33.3-6.7 45.3-18.7z"
18
+ />
19
+ </Icon>
20
+ )
21
+ }
22
+
23
+ export default SvgComponent
@@ -1,30 +1,82 @@
1
1
  import {
2
- Button,
3
- Modal,
4
- Row,
2
+ Box,
5
3
  Text,
6
4
  } from 'native-base';
5
+ import {
6
+ Modal,
7
+ View,
8
+ } from 'react-native';
9
+ import {
10
+ UI_MODE_REACT_NATIVE,
11
+ UI_MODE_WEB,
12
+ } from '../../Constants/UiModes.js';
13
+ import UiGlobals from '../../UiGlobals.js';
7
14
  import Loading from './Loading.js';
8
15
 
16
+ const
17
+ height = 50,
18
+ width = 200;
19
+
20
+ // NOTE: THis component does NOT use the native-base Modal
21
+ // because we need it to appear on top of all other Modals.
22
+ // Therefore, we're using the ReactNative Modal, which at least for web
23
+ // we can control the zIndex of.
24
+
9
25
  export default function WaitMessage(props) {
10
26
  const {
11
27
  textMessage = 'Please wait...',
12
28
  } = props;
13
29
 
14
- return <Modal {...props} _backdrop={{ bg: "#000" }}>
15
- <Modal.Content>
16
- <Modal.Body
17
- borderTopWidth={0}
18
- bg="#fff"
19
- p={3}
20
- justifyContent="center"
21
- alignItems="center"
22
- borderRadius={5}
23
- flexDirection="row"
24
- >
25
- <Loading minHeight="auto" h={5} w={5} mr={2} />
26
- <Text color="#000">{textMessage}</Text>
27
- </Modal.Body>
28
- </Modal.Content>
30
+ let transform;
31
+ if (UiGlobals.mode === UI_MODE_WEB) {
32
+ transform = 'translateX(-50%) translateY(-50%)';
33
+ }
34
+ if (UiGlobals.mode === UI_MODE_REACT_NATIVE) {
35
+ const
36
+ translatePercentage = -50,
37
+ translateY = (height * translatePercentage) / 100,
38
+ translateX = (width * translatePercentage) / 100;
39
+ transform = [
40
+ {
41
+ translateX,
42
+ },
43
+ {
44
+ translateY,
45
+ },
46
+ ];
47
+ }
48
+
49
+ return <Modal visible={true} transparent={true} {...props}>
50
+ <View style={{
51
+ flex: 1,
52
+ backgroundColor: 'rgba(0, 0, 0, 0.3)',
53
+ justifyContent: 'center',
54
+ alignItems: 'center',
55
+ }}>
56
+ <View style={{
57
+ position: 'absolute',
58
+ top: '50%',
59
+ left: '50%',
60
+ transform,
61
+ height: height + 'px',
62
+ width: width + 'px',
63
+ zIndex: 100000, // should be the highest modal
64
+ }}>
65
+ <Box
66
+ borderTopWidth={0}
67
+ bg="#fff"
68
+ p={3}
69
+ h={height + 'px'}
70
+ w={width + 'px'}
71
+ justifyContent="center"
72
+ alignItems="center"
73
+ borderRadius={5}
74
+ flexDirection="row"
75
+ >
76
+ <Loading minHeight="auto" h={5} w={5} mr={2} />
77
+ <Text color="#000">{textMessage}</Text>
78
+ </Box>
79
+ </View>
80
+ </View>
29
81
  </Modal>;
30
82
  }
@@ -22,7 +22,7 @@ function ManagerScreen(props) {
22
22
  title,
23
23
  sideModeComponent,
24
24
  fullModeComponent,
25
- id,
25
+ reference,
26
26
  } = props,
27
27
  styles = UiGlobals.styles,
28
28
  [isReady, setIsReady] = useState(false),
@@ -32,18 +32,22 @@ function ManagerScreen(props) {
32
32
  return; // no change
33
33
  }
34
34
  setModeRaw(newMode);
35
- setSaved(id + '-mode', newMode);
35
+ if (reference) {
36
+ setSaved(reference + '-mode', newMode);
37
+ }
36
38
  };
37
39
 
38
40
  useEffect(() => {
39
41
  // Restore saved settings
40
42
  (async () => {
41
43
 
42
- let key, val;
43
- key = id + '-mode';
44
- val = await getSaved(key);
45
- if (!_.isNil(val)) {
46
- setMode(val);
44
+ if (reference) {
45
+ const
46
+ key = reference + '-mode',
47
+ val = await getSaved(key);
48
+ if (!_.isNil(val)) {
49
+ setMode(val);
50
+ }
47
51
  }
48
52
 
49
53
  if (!isReady) {
@@ -432,7 +432,7 @@ function TabBar(props) {
432
432
  p={2}
433
433
  pb={0}
434
434
  bg={styles.TAB_BAR_BG}
435
- h={isCollapsed ? '30px' : tabHeight}
435
+ h={isCollapsed ? '38px' : tabHeight}
436
436
  >
437
437
  <ScrollView
438
438
  horizontal={true}
@@ -2,3 +2,4 @@ export const ALERT_MODE_OK = 'ALERT_MODE_OK';
2
2
  export const ALERT_MODE_YES = 'ALERT_MODE_YES';
3
3
  export const ALERT_MODE_YES_NO = 'ALERT_MODE_YES_NO';
4
4
  export const ALERT_MODE_CUSTOM = 'ALERT_MODE_CUSTOM';
5
+ export const ALERT_MODE_INFO = 'ALERT_MODE_INFO';