@onehat/ui 0.2.54 → 0.2.56

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.2.54",
3
+ "version": "0.2.56",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "license": "UNLICENSED",
21
21
  "dependencies": {
22
- "@onehat/data": "^1.16.10",
22
+ "@onehat/data": "^1.17.0",
23
23
  "@hookform/resolvers": "^2.9.11",
24
24
  "@k-renwick/colour-mixer": "^1.2.1",
25
25
  "ckeditor5-custom-build": "file:ckeditor5",
@@ -27,7 +27,7 @@ export default function Editor(props) {
27
27
  onEditMode = () => {
28
28
  setEditorMode(EDITOR_MODE__EDIT);
29
29
  },
30
- onBack = () => {
30
+ onViewMode = () => {
31
31
  setEditorMode(EDITOR_MODE__VIEW);
32
32
  };
33
33
 
@@ -40,6 +40,7 @@ export default function Editor(props) {
40
40
  record={selection[0]}
41
41
  Repository={Repository}
42
42
  onEditMode={isViewOnly ? null : onEditMode}
43
+ onClose={onClose}
43
44
  {...props}
44
45
  />;
45
46
  }
@@ -49,7 +50,7 @@ export default function Editor(props) {
49
50
 
50
51
  return <Form
51
52
  record={selection}
52
- onBack={onBack}
53
+ onViewMode={onViewMode}
53
54
  onCancel={onCancel}
54
55
  onSave={onSave}
55
56
  onClose={onClose}
@@ -463,7 +463,8 @@ export function Combo(props) {
463
463
  w={width + 'px'}
464
464
  h={height ? height + 'px' : null}
465
465
  minWidth={menuMinWidth}
466
- overflow="scroll"
466
+ overflow="auto"
467
+ bg="#fff"
467
468
  >
468
469
  <Popover.Body
469
470
  ref={menuRef}
@@ -484,6 +485,7 @@ export function Combo(props) {
484
485
  py: 1,
485
486
  pl: 4,
486
487
  pr: 2,
488
+ w: '100%',
487
489
  };
488
490
  }}
489
491
  {...props}
@@ -147,16 +147,16 @@ function FileElement(props) {
147
147
  setIsDropping(false);
148
148
  };
149
149
 
150
- useEffect(() => {
151
- const {
152
- dataUri,
153
- control,
154
- filename,
155
- } = value;
156
- setLocalDataUri(localDataUri);
157
- setLocalControl(localControl);
158
- setLocalFilename(localFilename);
159
- }, []);
150
+ // useEffect(() => {
151
+ // const {
152
+ // dataUri,
153
+ // control,
154
+ // filename,
155
+ // } = value;
156
+ // setLocalDataUri(dataUri);
157
+ // setLocalControl(control);
158
+ // setLocalFilename(filename);
159
+ // }, []);
160
160
 
161
161
  if (CURRENT_MODE === UI_MODE_REACT_NATIVE) {
162
162
  throw new Error('Not yet implemented for RN.');
@@ -31,7 +31,7 @@ import AngleLeft from '../Icons/AngleLeft.js';
31
31
  import Eye from '../Icons/Eye.js';
32
32
  import Rotate from '../Icons/Rotate.js';
33
33
  import Pencil from '../Icons/Pencil.js';
34
- import Footer from '../Panel/Footer.js';
34
+ import Footer from '../Layout/Footer.js';
35
35
  import Label from '../Form/Label.js';
36
36
  import _ from 'lodash';
37
37
 
@@ -282,14 +282,10 @@ function Form(props) {
282
282
  });
283
283
  return <Element key={ix} title={title} {...defaults} {...propsToPass} {...editorTypeProps}>{children}</Element>;
284
284
  }
285
-
286
- if (!name) {
287
- throw new Error('name is required');
288
- }
289
285
 
290
286
  if (isViewOnly || !isEditable) {
291
287
  const Text = getComponentFromType('Text');
292
- if (!label && Repository) {
288
+ if (!label && Repository && model.titles?.[name]) {
293
289
  label = model.titles[name];
294
290
  }
295
291
  const value = (record && record[name]) || (startingValues && startingValues[name]) || null;
@@ -307,7 +303,7 @@ function Form(props) {
307
303
  return <Row key={ix} px={2} pb={1}>{element}</Row>;
308
304
  }
309
305
 
310
- if (!label && Repository) {
306
+ if (!label && Repository && model.titles?.[name]) {
311
307
  label = model.titles[name];
312
308
  }
313
309
 
@@ -500,7 +496,7 @@ function Form(props) {
500
496
  onPress={onViewMode}
501
497
  leftIcon={<Icon as={Eye} color="#fff" size="sm" />}
502
498
  color="#fff"
503
- >View</Button>}
499
+ >To View</Button>}
504
500
  </Row>
505
501
  {!_.isEmpty(additionalButtons) &&
506
502
  <Row p={2} alignItems="center" justifyContent="flex-end">
@@ -10,7 +10,8 @@ export default function Label(props) {
10
10
  } = props;
11
11
  return <Row
12
12
  w={w}
13
- // maxWidth="30%"
13
+ minWidth="120px"
14
+ maxWidth="50%"
14
15
  alignItems="center"
15
16
  pl={2}
16
17
  {...props}
@@ -52,18 +52,6 @@ import _ from 'lodash';
52
52
  // The default export is *with* the HOC. A separate *raw* component is
53
53
  // exported which can be combined with many HOCs for various functionality.
54
54
 
55
- // Desired features: ---------
56
- // Rows
57
- // Rows with ability to use multiple lines (I was thinking custom render fns on rows, could possibly already do this!)
58
- // selection
59
- // Draggable selection (not super important)
60
- // editor
61
- // [ ] Show inline editor for selected row
62
- // Dragging of window (see withWindowedEditor)
63
- // custom cell types
64
- // Most would use text, and depend on @onehat/data for formatting
65
- // Display tree data
66
-
67
55
  export function Grid(props) {
68
56
  const {
69
57
 
@@ -74,9 +62,6 @@ export function Grid(props) {
74
62
  return {
75
63
  borderBottomWidth: 1,
76
64
  borderBottomColor: 'trueGray.500',
77
- py: 2,
78
- pl: 4,
79
- pr: 2,
80
65
  };
81
66
  },
82
67
  flatListProps = {},
@@ -363,8 +348,10 @@ export function Grid(props) {
363
348
  mixWith = styles.GRID_ROW_HOVER_BG;
364
349
  }
365
350
  if (mixWith) {
366
- const mixWithObj = nbToRgb(mixWith);
367
- bg = colourMixer.blend(bg, 0.9, mixWithObj.color);
351
+ const
352
+ mixWithObj = nbToRgb(mixWith),
353
+ ratio = mixWithObj.alpha ? 1 - mixWithObj.alpha : 0.5;
354
+ bg = colourMixer.blend(bg, ratio, mixWithObj.color);
368
355
  }
369
356
  let WhichGridRow = GridRow,
370
357
  rowReorderProps = {};
@@ -676,6 +663,7 @@ export function Grid(props) {
676
663
  sortable = true,
677
664
  w,
678
665
  flex,
666
+ ...propsToPass
679
667
  } = columnConfig,
680
668
 
681
669
  config = {
@@ -693,6 +681,7 @@ export function Grid(props) {
693
681
  w,
694
682
  flex,
695
683
  showDragHandles: false,
684
+ ...propsToPass,
696
685
  };
697
686
 
698
687
  if (!config.w && !config.flex) {
@@ -754,7 +743,7 @@ export function Grid(props) {
754
743
  if (!Repository) {
755
744
  return () => {};
756
745
  }
757
- if (!disableSelectorSelected) {
746
+ if (!disableSelectorSelected && selectorId) {
758
747
  let id = selectorSelected?.id;
759
748
  if (_.isEmpty(selectorSelected)) {
760
749
  id = noSelectorMeansNoResults ? 'NO_MATCHES' : null;
@@ -808,7 +797,7 @@ export function Grid(props) {
808
797
  scrollEnabled={true}
809
798
  nestedScrollEnabled={true}
810
799
  contentContainerStyle={{
811
- overflow: 'scroll',
800
+ overflow: 'auto',
812
801
  borderWidth: isReorderMode ? 4 : 0,
813
802
  borderColor: isReorderMode ? '#23d9ea' : null,
814
803
  borderStyle: 'dashed',
@@ -32,10 +32,39 @@ export default function GridRow(props) {
32
32
  const renderColumns = (item) => {
33
33
  if (_.isArray(columnsConfig)) {
34
34
  return _.map(columnsConfig, (config, key) => {
35
+ const propsToPass = columnProps[key] || {};
36
+ if (config.w) {
37
+ propsToPass.w = config.w;
38
+ } else if (config.flex) {
39
+ propsToPass.flex = config.flex;
40
+ propsToPass.minWidth = 100;
41
+ } else {
42
+ propsToPass.flex = 1;
43
+ }
44
+ propsToPass.p = 1;
45
+ propsToPass.justifyContent = 'center';
46
+
35
47
  let value;
36
48
  if (_.isPlainObject(config)) {
37
49
  if (config.renderer) {
38
- return config.renderer(item, key);
50
+ const extraProps = _.omit(config, [
51
+ 'columnId',
52
+ 'header',
53
+ 'fieldName',
54
+ 'type',
55
+ 'isEditable',
56
+ 'editor',
57
+ 'format',
58
+ 'renderer',
59
+ 'reorderable',
60
+ 'resizable',
61
+ 'sortable',
62
+ 'w',
63
+ 'flex',
64
+ 'showDragHandles',
65
+ ]);
66
+
67
+ return <Row key={key} {...propsToPass} {...extraProps}>{config.renderer(item)}</Row>;
39
68
  }
40
69
  if (config.fieldName) {
41
70
  if (item.properties && item.properties[config.fieldName]) {
@@ -63,16 +92,6 @@ export default function GridRow(props) {
63
92
  if (_.isFunction(value)) {
64
93
  return value(key);
65
94
  }
66
-
67
- const propsToPass = columnProps[key] || {};
68
- if (config.w) {
69
- propsToPass.w = config.w;
70
- } else if (config.flex) {
71
- propsToPass.flex = config.flex;
72
- propsToPass.minWidth = 100;
73
- } else {
74
- propsToPass.flex = 1;
75
- }
76
95
 
77
96
  return <Text
78
97
  key={key}
@@ -13,7 +13,7 @@ import {
13
13
  ALERT_MODE_CUSTOM,
14
14
  } from '../../Constants/Alert.js';
15
15
  import Panel from '../Panel/Panel.js';
16
- import Footer from '../Panel/Footer.js';
16
+ import Footer from '../Layout/Footer.js';
17
17
  import TriangleExclamation from '../Icons/TriangleExclamation.js';
18
18
  import _ from 'lodash';
19
19
 
@@ -51,10 +51,8 @@ export default function withData(WrappedComponent) {
51
51
  Repository = oneHatData.getRepository(model);
52
52
  }
53
53
 
54
-
55
- if (autoLoad && Repository && !Repository.isLoaded && Repository.isRemote && !Repository.isAutoLoad && !Repository.isLoading) {
54
+ if (Repository && (autoLoad || Repository.autoLoad) && !Repository.isLoaded && Repository.isRemote && !Repository.isAutoLoad && !Repository.isLoading) {
56
55
  await Repository.load();
57
- // TODO: Implement some method by which I can detect if Repository is still loading and wait until it's done!
58
56
  }
59
57
 
60
58
  setLocalRepository(Repository);
@@ -0,0 +1,14 @@
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 xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" {...props}>
9
+ <Path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2s-6.3 25.5 4.1 33.7l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7l-105.2-82.4c39.6-40.6 66.4-86.1 79.9-118.4 3.3-7.9 3.3-16.7 0-24.6-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zm184.3 144.4c25.5-23.3 59.6-37.5 96.9-37.5 79.5 0 144 64.5 144 144 0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5 0-53-43-96-96-96-2.8 0-5.6.1-8.4.4 5.3 9.3 8.4 20.1 8.4 31.6 0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1-79.5 0-144-64.5-144-144 0-6.9.5-13.6 1.4-20.2l-94.3-74.3c-22.8 29.7-39.1 59.3-48.6 82.2-3.3 7.9-3.3 16.7 0 24.6 14.9 35.7 46.2 87.7 93 131.1 47 43.8 111.7 80.6 192.5 80.6 47.8 0 89.9-12.9 126.2-32.5z" />
10
+ </Icon>
11
+ )
12
+ }
13
+
14
+ export default SvgComponent
@@ -0,0 +1,14 @@
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 xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" {...props}>
9
+ <Path d="M352 128c0 70.7-57.3 128-128 128S96 198.7 96 128 153.3 0 224 0s128 57.3 128 128zM0 482.3C0 383.8 79.8 304 178.3 304h91.4c98.5 0 178.3 79.8 178.3 178.3 0 16.4-13.3 29.7-29.7 29.7H29.7C13.3 512 0 498.7 0 482.3zM504 312v-64h-64c-13.3 0-24-10.7-24-24s10.7-24 24-24h64v-64c0-13.3 10.7-24 24-24s24 10.7 24 24v64h64c13.3 0 24 10.7 24 24s-10.7 24-24 24h-64v64c0 13.3-10.7 24-24 24s-24-10.7-24-24z" />
10
+ </Icon>
11
+ )
12
+ }
13
+
14
+ export default SvgComponent
@@ -0,0 +1,17 @@
1
+ import {
2
+ Box,
3
+ } from 'native-base';
4
+
5
+ export default function CenterBox(props) {
6
+ return <Box
7
+ alignItems="center"
8
+ justifyContent="center"
9
+ flex={1}
10
+ w="100%"
11
+ p={2}
12
+ safeAreaBottom
13
+ {...props}
14
+ >
15
+ {props.children}
16
+ </Box>;
17
+ }
@@ -5,7 +5,7 @@ import {
5
5
  } from 'native-base';
6
6
  import Accordion from 'react-native-collapsible/Accordion'; // https://www.npmjs.com/package/react-native-collapsible
7
7
  import testProps from '../../Functions/testProps';
8
- import Footer from './Footer.js';
8
+ import Footer from '../Layout/Footer.js';
9
9
  import Toolbar from '../Toolbar/Toolbar.js';
10
10
  import PaginationToolbar from '../Toolbar/PaginationToolbar.js';
11
11
  import NoRecordsFound from './NoRecordsFound.js';
@@ -10,7 +10,7 @@ export default function Toolbar(props) {
10
10
  borderBottomWidth={1}
11
11
  borderBottomColor="trueGray.400"
12
12
  p={2}
13
- overflow="scroll"
13
+ overflow="auto"
14
14
  {...props}
15
15
  >
16
16
  {props.children}
@@ -33,7 +33,7 @@ const defaults = {
33
33
  FORM_INPUT_BG: WHITE,
34
34
  FORM_INPUT_FONTSIZE: DEFAULT_FONTSIZE,
35
35
  FORM_INPUT_FOCUS_BG: FOCUS,
36
- FORM_LABEL_WIDTH: '170px',
36
+ FORM_LABEL_WIDTH: '30%',
37
37
  FORM_LABEL_FONTSIZE: DEFAULT_FONTSIZE,
38
38
  FORM_NUMBER_FONTSIZE: DEFAULT_FONTSIZE,
39
39
  FORM_TEXT_FONTSIZE: DEFAULT_FONTSIZE,
@@ -1,8 +1,13 @@
1
1
  import { bindActionCreators } from 'redux';
2
2
  import { connect } from 'react-redux';
3
- import actionCreators from '../../../Models/actions/ActionCreators';
4
3
  import _ from 'lodash';
5
4
 
5
+ let actionCreators = null;
6
+
7
+ export function setActionCreators(ac) {
8
+ actionCreators = ac;
9
+ }
10
+
6
11
  // Usage:
7
12
  // At top of file:
8
13
  // import withRedux from '../../OneHat/Data/hoc/WithData';
@@ -12,6 +12,8 @@ function isRgb(color) {
12
12
  // Try to convert this to actual RGB colors.
13
13
  export default function nbToRgb(color) {
14
14
 
15
+ let regex, alpha, matches;
16
+
15
17
  if (isRgb(color)) {
16
18
  // already in RGB format; simply return it
17
19
  return {
@@ -25,13 +27,12 @@ export default function nbToRgb(color) {
25
27
  color = themeOverrideColors[color];
26
28
  }
27
29
 
28
- let regex, alpha, matches;
29
-
30
+ // Detect 'primary.100:alpha.20' format
30
31
  regex = /^([\w#\.]+)(:alpha\.([\d]{1,2}))?$/;
31
32
  matches = color.match(regex);
32
33
  if (matches[3]) {
33
34
  // alpha part exists. parse it
34
- alpha = parseInt(matches[3], 10) / 100;
35
+ alpha = parseInt(matches[3], 10) / 100; // convert '20' to .2
35
36
  }
36
37
  if (matches[1]) {
37
38
  // color part exists. parse it
@@ -3,11 +3,10 @@ import UiGlobals from '../UiGlobals.js';
3
3
  import _ from 'lodash';
4
4
 
5
5
  export default async function setSaved(key, value) {
6
- const Repo = oneHatData.getRepository(UiGlobals.uiSavesRepo);
7
- if (!Repo) {
8
- return null;
9
- }
10
-
6
+ const
7
+ Repo = oneHatData.getRepository(UiGlobals.uiSavesRepo),
8
+ entity = Repo?.getById(key);
9
+
11
10
  let isOneBuild = false,
12
11
  isJson = false,
13
12
  model = null;
@@ -33,8 +32,6 @@ export default async function setSaved(key, value) {
33
32
  }
34
33
  isJson = true;
35
34
  }
36
-
37
- const entity = Repo.getById(key);
38
35
  if (entity) {
39
36
  entity.setValues({
40
37
  value,
@@ -3,7 +3,7 @@ import useWindowSize from './useWindowSize.js';
3
3
  // This hook takes the submitted window size and adjusts it
4
4
  // to fit the actual screen size
5
5
 
6
- export default function(width, height, percentage = 0.9) {
6
+ export default function(width, height, percentage = 1) {
7
7
 
8
8
  const windowSize = useWindowSize();
9
9
 
@@ -1,16 +1,25 @@
1
1
  // from https://designcode.io/react-hooks-usewindowsize-hook
2
2
 
3
3
  import { useLayoutEffect, useState } from 'react';
4
+ import _ from 'lodash';
4
5
 
5
6
  // For web only!
6
7
  export default function useWindowSize() {
7
- const [windowSize, setWindowSize] = useState({ width: 0, height: 0 });
8
+ const [windowSize, setWindowSize] = useState({
9
+ width: window?.innerWidth || 0,
10
+ height: window?.innerHeight || 0,
11
+ });
8
12
 
9
13
  const handleSize = () => {
10
- setWindowSize({
11
- width: window.innerWidth,
12
- height: window.innerHeight
13
- });
14
+ const
15
+ existingSize = windowSize,
16
+ newSize = {
17
+ width: window?.innerWidth || 0,
18
+ height: window?.innerHeight || 0,
19
+ };
20
+ if (!_.isEqual(existingSize, newSize)) {
21
+ setWindowSize(newSize);
22
+ }
14
23
  };
15
24
 
16
25
  useLayoutEffect(() => {
@@ -14,9 +14,9 @@ const ThemeOverrides = {
14
14
  // secondary: {
15
15
  // 500: '#1F3854', // default for buttons
16
16
  // },
17
- selected: '#ffc',
18
- hover: '#eee',
19
- selectedHover: '#eeb',
17
+ selected: '#ff0:alpha.20',
18
+ hover: '#000:alpha.10',
19
+ selectedHover: '#cc0',
20
20
  unselected: '#bbb',
21
21
  disabled: '#ccc',
22
22
  control: '#1B518C',
File without changes