@onehat/ui 0.2.53 → 0.2.55
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 +3 -2
- package/src/Components/Buttons/CheckboxButton.js +15 -0
- package/src/Components/Buttons/IconButton.js +15 -4
- package/src/Components/Editor/Editor.js +2 -2
- package/src/Components/Form/Field/Combo/Combo.js +1 -0
- package/src/Components/Form/Field/File.js +10 -10
- package/src/Components/Form/Form.js +2 -6
- package/src/Components/Form/Label.js +1 -1
- package/src/Components/Grid/Grid.js +18 -25
- package/src/Components/Grid/GridRow.js +30 -11
- package/src/Components/Hoc/withData.js +1 -3
- package/src/Components/Hoc/withFilters.js +10 -7
- package/src/Components/Panel/TabPanel.js +2 -4
- package/src/Components/Screens/DataMgt.js +0 -2
- package/src/Components/Toolbar/Pagination.js +0 -3
- package/src/Components/Toolbar/PaginationToolbar.js +13 -2
- package/src/Constants/Styles.js +4 -1
- package/src/Functions/nbToRgb.js +64 -0
- package/src/Functions/setSaved.js +0 -4
- package/src/Functions/setThemeOverrides.js +5 -0
- package/src/Hooks/useAdjustedWindowSize.js +1 -1
- package/src/Hooks/useWindowSize.js +14 -5
- package/src/Styles/ThemeOverrides.js +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onehat/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.55",
|
|
4
4
|
"description": "Base UI for OneHat apps",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -19,8 +19,9 @@
|
|
|
19
19
|
},
|
|
20
20
|
"license": "UNLICENSED",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@onehat/data": "^1.
|
|
22
|
+
"@onehat/data": "^1.17.0",
|
|
23
23
|
"@hookform/resolvers": "^2.9.11",
|
|
24
|
+
"@k-renwick/colour-mixer": "^1.2.1",
|
|
24
25
|
"ckeditor5-custom-build": "file:ckeditor5",
|
|
25
26
|
"js-cookie": "^3.0.1",
|
|
26
27
|
"native-base": "^3.4.25",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import IconButton from './IconButton.js';
|
|
2
|
+
import SquareCheck from '../Icons/SquareCheck.js';
|
|
3
|
+
import Square from '../Icons/Square.js';
|
|
4
|
+
|
|
5
|
+
export default function CheckboxButton(props) {
|
|
6
|
+
const {
|
|
7
|
+
isChecked,
|
|
8
|
+
} = props;
|
|
9
|
+
|
|
10
|
+
return <IconButton
|
|
11
|
+
icon={isChecked ? SquareCheck : Square }
|
|
12
|
+
{...props}
|
|
13
|
+
/>;
|
|
14
|
+
}
|
|
15
|
+
|
|
@@ -17,10 +17,14 @@ const IconButton = React.forwardRef((props, ref) => {
|
|
|
17
17
|
tooltipPlacement = 'bottom',
|
|
18
18
|
} = props;
|
|
19
19
|
const propsIcon = props._icon || {};
|
|
20
|
-
let icon = props.icon || <Icon {...propsIcon}
|
|
20
|
+
let icon = props.icon || <Icon {...propsIcon} />,
|
|
21
|
+
ret;
|
|
21
22
|
if (isLoading) {
|
|
22
23
|
icon = <Spinner {..._spinner} />;
|
|
23
24
|
}
|
|
25
|
+
if (!React.isValidElement(icon)) {
|
|
26
|
+
icon = <Icon as={icon} {...propsIcon} />;
|
|
27
|
+
}
|
|
24
28
|
const pressable = <Pressable
|
|
25
29
|
ref={ref}
|
|
26
30
|
borderRadius="md"
|
|
@@ -29,16 +33,23 @@ const IconButton = React.forwardRef((props, ref) => {
|
|
|
29
33
|
justifyContent="center"
|
|
30
34
|
alignItems="center"
|
|
31
35
|
p={2}
|
|
36
|
+
// bg={styles.ICON_BUTTON_BG}
|
|
37
|
+
_hover={{
|
|
38
|
+
bg: styles.ICON_BUTTON_BG_HOVER,
|
|
39
|
+
}}
|
|
32
40
|
_disabled={{
|
|
33
41
|
bg: styles.ICON_BUTTON_BG_DISABLED,
|
|
34
42
|
}}
|
|
43
|
+
_pressed={{
|
|
44
|
+
bg: styles.ICON_BUTTON_BG_PRESSED,
|
|
45
|
+
}}
|
|
35
46
|
{...props}
|
|
36
47
|
>
|
|
37
|
-
|
|
48
|
+
{icon}
|
|
38
49
|
</Pressable>;
|
|
39
|
-
|
|
50
|
+
ret = pressable;
|
|
40
51
|
if (tooltip) {
|
|
41
|
-
ret = <Tooltip label={tooltip} placement={tooltipPlacement}>{
|
|
52
|
+
ret = <Tooltip label={tooltip} placement={tooltipPlacement}>{ret}</Tooltip>;
|
|
42
53
|
}
|
|
43
54
|
return ret;
|
|
44
55
|
});
|
|
@@ -27,7 +27,7 @@ export default function Editor(props) {
|
|
|
27
27
|
onEditMode = () => {
|
|
28
28
|
setEditorMode(EDITOR_MODE__EDIT);
|
|
29
29
|
},
|
|
30
|
-
|
|
30
|
+
onViewMode = () => {
|
|
31
31
|
setEditorMode(EDITOR_MODE__VIEW);
|
|
32
32
|
};
|
|
33
33
|
|
|
@@ -49,7 +49,7 @@ export default function Editor(props) {
|
|
|
49
49
|
|
|
50
50
|
return <Form
|
|
51
51
|
record={selection}
|
|
52
|
-
|
|
52
|
+
onViewMode={onViewMode}
|
|
53
53
|
onCancel={onCancel}
|
|
54
54
|
onSave={onSave}
|
|
55
55
|
onClose={onClose}
|
|
@@ -147,16 +147,16 @@ function FileElement(props) {
|
|
|
147
147
|
setIsDropping(false);
|
|
148
148
|
};
|
|
149
149
|
|
|
150
|
-
useEffect(() => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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.');
|
|
@@ -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
|
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
DROP_POSITION_BEFORE,
|
|
22
22
|
DROP_POSITION_AFTER,
|
|
23
23
|
} from '../../Constants/Grid.js';
|
|
24
|
+
import * as colourMixer from '@k-renwick/colour-mixer'
|
|
24
25
|
import UiGlobals from '../../UiGlobals.js';
|
|
25
26
|
import useForceUpdate from '../../Hooks/useForceUpdate.js';
|
|
26
27
|
import withContextMenu from '../Hoc/withContextMenu.js';
|
|
@@ -35,6 +36,7 @@ import withSelection from '../Hoc/withSelection.js';
|
|
|
35
36
|
import withWindowedEditor from '../Hoc/withWindowedEditor.js';
|
|
36
37
|
import withInlineEditor from '../Hoc/withInlineEditor.js';
|
|
37
38
|
import testProps from '../../Functions/testProps.js';
|
|
39
|
+
import nbToRgb from '../../Functions/nbToRgb.js';
|
|
38
40
|
import GridHeaderRow from './GridHeaderRow.js';
|
|
39
41
|
import GridRow, { ReorderableGridRow } from './GridRow.js';
|
|
40
42
|
import IconButton from '../Buttons/IconButton.js';
|
|
@@ -45,35 +47,21 @@ import NoReorderRows from '../Icons/NoReorderRows.js';
|
|
|
45
47
|
import ReorderRows from '../Icons/ReorderRows.js';
|
|
46
48
|
import _ from 'lodash';
|
|
47
49
|
|
|
50
|
+
|
|
48
51
|
// Grid requires the use of HOC withSelection() whenever it's used.
|
|
49
52
|
// The default export is *with* the HOC. A separate *raw* component is
|
|
50
53
|
// exported which can be combined with many HOCs for various functionality.
|
|
51
54
|
|
|
52
|
-
// Desired features: ---------
|
|
53
|
-
// Rows
|
|
54
|
-
// Rows with ability to use multiple lines (I was thinking custom render fns on rows, could possibly already do this!)
|
|
55
|
-
// selection
|
|
56
|
-
// Draggable selection (not super important)
|
|
57
|
-
// editor
|
|
58
|
-
// [ ] Show inline editor for selected row
|
|
59
|
-
// Dragging of window (see withWindowedEditor)
|
|
60
|
-
// custom cell types
|
|
61
|
-
// Most would use text, and depend on @onehat/data for formatting
|
|
62
|
-
// Display tree data
|
|
63
|
-
|
|
64
55
|
export function Grid(props) {
|
|
65
56
|
const {
|
|
66
57
|
|
|
67
58
|
columnsConfig = [], // json configurations for each column
|
|
68
59
|
|
|
69
60
|
columnProps = {},
|
|
70
|
-
getRowProps = () => {
|
|
61
|
+
getRowProps = (item) => {
|
|
71
62
|
return {
|
|
72
63
|
borderBottomWidth: 1,
|
|
73
64
|
borderBottomColor: 'trueGray.500',
|
|
74
|
-
py: 2,
|
|
75
|
-
pl: 4,
|
|
76
|
-
pr: 2,
|
|
77
65
|
};
|
|
78
66
|
},
|
|
79
67
|
flatListProps = {},
|
|
@@ -348,19 +336,22 @@ export function Grid(props) {
|
|
|
348
336
|
/>;
|
|
349
337
|
}
|
|
350
338
|
|
|
351
|
-
let bg = styles.GRID_ROW_BG
|
|
339
|
+
let bg = rowProps.bg || styles.GRID_ROW_BG,
|
|
340
|
+
mixWith;
|
|
352
341
|
if (isSelected) {
|
|
353
342
|
if (showHovers && isHovered) {
|
|
354
|
-
|
|
355
|
-
} else {
|
|
356
|
-
bg = styles.GRID_ROW_SELECTED_BG;
|
|
357
|
-
}
|
|
358
|
-
} else {
|
|
359
|
-
if (showHovers && isHovered) {
|
|
360
|
-
bg = styles.GRID_ROW_HOVER_BG;
|
|
343
|
+
mixWith = styles.GRID_ROW_SELECTED_HOVER_BG;
|
|
361
344
|
} else {
|
|
362
|
-
|
|
345
|
+
mixWith = styles.GRID_ROW_SELECTED_BG;
|
|
363
346
|
}
|
|
347
|
+
} else if (showHovers && isHovered) {
|
|
348
|
+
mixWith = styles.GRID_ROW_HOVER_BG;
|
|
349
|
+
}
|
|
350
|
+
if (mixWith) {
|
|
351
|
+
const
|
|
352
|
+
mixWithObj = nbToRgb(mixWith),
|
|
353
|
+
ratio = mixWithObj.alpha ? 1 - mixWithObj.alpha : 0.5;
|
|
354
|
+
bg = colourMixer.blend(bg, ratio, mixWithObj.color);
|
|
364
355
|
}
|
|
365
356
|
let WhichGridRow = GridRow,
|
|
366
357
|
rowReorderProps = {};
|
|
@@ -672,6 +663,7 @@ export function Grid(props) {
|
|
|
672
663
|
sortable = true,
|
|
673
664
|
w,
|
|
674
665
|
flex,
|
|
666
|
+
...propsToPass
|
|
675
667
|
} = columnConfig,
|
|
676
668
|
|
|
677
669
|
config = {
|
|
@@ -689,6 +681,7 @@ export function Grid(props) {
|
|
|
689
681
|
w,
|
|
690
682
|
flex,
|
|
691
683
|
showDragHandles: false,
|
|
684
|
+
...propsToPass,
|
|
692
685
|
};
|
|
693
686
|
|
|
694
687
|
if (!config.w && !config.flex) {
|
|
@@ -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
|
-
|
|
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}
|
|
@@ -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);
|
|
@@ -12,6 +12,8 @@ import FormPanel from '../Panel/FormPanel.js';
|
|
|
12
12
|
import Ban from '../Icons/Ban.js';
|
|
13
13
|
import Gear from '../Icons/Gear.js';
|
|
14
14
|
import Toolbar from '../Toolbar/Toolbar.js';
|
|
15
|
+
import getSaved from '../../Functions/getSaved.js';
|
|
16
|
+
import setSaved from '../../Functions/setSaved.js';
|
|
15
17
|
import UiGlobals from '../../UiGlobals.js';
|
|
16
18
|
import _ from 'lodash';
|
|
17
19
|
|
|
@@ -34,8 +36,6 @@ export default function withFilters(WrappedComponent) {
|
|
|
34
36
|
customFilters = [], // of shape: { title, type, field, value, getRepoFilters(value) }
|
|
35
37
|
minFilters = 3,
|
|
36
38
|
maxFilters = 6,
|
|
37
|
-
getSaved,
|
|
38
|
-
setSaved,
|
|
39
39
|
|
|
40
40
|
// withData
|
|
41
41
|
Repository,
|
|
@@ -166,7 +166,7 @@ export default function withFilters(WrappedComponent) {
|
|
|
166
166
|
}
|
|
167
167
|
setSlots(newSlots);
|
|
168
168
|
}
|
|
169
|
-
if (save
|
|
169
|
+
if (save) {
|
|
170
170
|
setSaved(id + '-filters', filters);
|
|
171
171
|
}
|
|
172
172
|
},
|
|
@@ -204,9 +204,12 @@ export default function withFilters(WrappedComponent) {
|
|
|
204
204
|
const filter = getFilterByField(field);
|
|
205
205
|
return filter?.type;
|
|
206
206
|
},
|
|
207
|
-
getIsFilterRange = (
|
|
208
|
-
|
|
207
|
+
getIsFilterRange = (filter) => {
|
|
208
|
+
let field = _.isString(filter) ? filter : filter.field;
|
|
209
209
|
const filterType = getFilterType(field);
|
|
210
|
+
if (filterType?.type) {
|
|
211
|
+
return inArray(filterType.type, ['NumberRange', 'DateRange'])
|
|
212
|
+
}
|
|
210
213
|
return inArray(filterType, ['NumberRange', 'DateRange']);
|
|
211
214
|
},
|
|
212
215
|
renderFilters = () => {
|
|
@@ -272,7 +275,7 @@ export default function withFilters(WrappedComponent) {
|
|
|
272
275
|
const newRepoFilters = [];
|
|
273
276
|
let filtersToUse = filters
|
|
274
277
|
|
|
275
|
-
if (!isReady
|
|
278
|
+
if (!isReady) {
|
|
276
279
|
const savedFilters = await getSaved(id + '-filters');
|
|
277
280
|
if (!_.isEmpty(savedFilters)) {
|
|
278
281
|
// load saved filters
|
|
@@ -295,7 +298,7 @@ export default function withFilters(WrappedComponent) {
|
|
|
295
298
|
field,
|
|
296
299
|
value,
|
|
297
300
|
} = filter,
|
|
298
|
-
isFilterRange = getIsFilterRange(
|
|
301
|
+
isFilterRange = getIsFilterRange(filter);
|
|
299
302
|
if (isFilterRange) {
|
|
300
303
|
if (!!value) {
|
|
301
304
|
const
|
|
@@ -45,16 +45,14 @@ export default function TabPanel(props) {
|
|
|
45
45
|
if (onChangeIsCollapsed) {
|
|
46
46
|
onChangeIsCollapsed(isCollapsed);
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
setSaved(id + '-isCollapsed', isCollapsed);
|
|
50
|
-
}
|
|
48
|
+
setSaved(id + '-isCollapsed', isCollapsed);
|
|
51
49
|
},
|
|
52
50
|
setCurrentTab = (ix) => {
|
|
53
51
|
setCurrentTabRaw(ix);
|
|
54
52
|
if (onChangeCurrentTab) {
|
|
55
53
|
onChangeCurrentTab(ix);
|
|
56
54
|
}
|
|
57
|
-
if (
|
|
55
|
+
if (saveCurrentTab) {
|
|
58
56
|
setSaved(id + '-currentTab', ix);
|
|
59
57
|
}
|
|
60
58
|
},
|
|
@@ -12,6 +12,7 @@ export default function PaginationToolbar(props) {
|
|
|
12
12
|
} = props,
|
|
13
13
|
[minimize, setMinimize] = useState(false),
|
|
14
14
|
propsToPass = _.omit(props, 'toolbarItems'),
|
|
15
|
+
showPagination = props.Repository?.totalPages > 1,
|
|
15
16
|
onLayout = (e) => {
|
|
16
17
|
// Note to future self: this is using hard-coded values.
|
|
17
18
|
// Eventually might want to make it responsive to actual sizes
|
|
@@ -30,6 +31,16 @@ export default function PaginationToolbar(props) {
|
|
|
30
31
|
}
|
|
31
32
|
};
|
|
32
33
|
|
|
34
|
+
let toolbarProps = {};
|
|
35
|
+
if (showPagination) {
|
|
36
|
+
toolbarProps = {
|
|
37
|
+
borderLeftWidth: 1,
|
|
38
|
+
borderLeftColor: 'trueGray.400',
|
|
39
|
+
pl: 3,
|
|
40
|
+
ml: 3,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
33
44
|
return <Toolbar
|
|
34
45
|
bg="trueGray.200"
|
|
35
46
|
borderTopWidth={1}
|
|
@@ -37,7 +48,7 @@ export default function PaginationToolbar(props) {
|
|
|
37
48
|
w="100%"
|
|
38
49
|
onLayout={(e) => onLayout(e)}
|
|
39
50
|
>
|
|
40
|
-
<Pagination {...propsToPass} w={toolbarItems.length ? null : '100%'} minimize={minimize} />
|
|
41
|
-
{toolbarItems.length ? <Row flex={1}
|
|
51
|
+
{showPagination && <Pagination {...propsToPass} w={toolbarItems.length ? null : '100%'} minimize={minimize} />}
|
|
52
|
+
{toolbarItems.length ? <Row flex={1} {...toolbarProps}>{toolbarItems}</Row> : null}
|
|
42
53
|
</Toolbar>;
|
|
43
54
|
};
|
package/src/Constants/Styles.js
CHANGED
|
@@ -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: '
|
|
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,
|
|
@@ -61,7 +61,10 @@ const defaults = {
|
|
|
61
61
|
GRID_TOOLBAR_ITEMS_COLOR: 'trueGray.800',
|
|
62
62
|
GRID_TOOLBAR_ITEMS_DISABLED_COLOR: 'disabled',
|
|
63
63
|
GRID_TOOLBAR_ITEMS_ICON_SIZE: 'sm',
|
|
64
|
+
ICON_BUTTON_BG: 'trueGray.200:alpha.0',
|
|
64
65
|
ICON_BUTTON_BG_DISABLED: 'trueGray.200',
|
|
66
|
+
ICON_BUTTON_BG_HOVER: '#000:alpha.20',
|
|
67
|
+
ICON_BUTTON_BG_PRESSED: '#000:alpha.30',
|
|
65
68
|
PANEL_FOOTER_BG: 'primary.100', // :alpha.50
|
|
66
69
|
PANEL_HEADER_BG: 'primary.100',
|
|
67
70
|
PANEL_HEADER_BG_VERTICAL: 'primary.100',
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import UiGlobals from '../UiGlobals.js';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
|
|
4
|
+
function isRgb(color) {
|
|
5
|
+
const
|
|
6
|
+
regex = /^#[\w]{3,6}$/,
|
|
7
|
+
matches = color.match(regex);
|
|
8
|
+
return !!matches?.[0];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// 'color' might be in a format NativeBase uses, like '#000:alpha.20' or 'primary.200'
|
|
12
|
+
// Try to convert this to actual RGB colors.
|
|
13
|
+
export default function nbToRgb(color) {
|
|
14
|
+
|
|
15
|
+
let regex, alpha, matches;
|
|
16
|
+
|
|
17
|
+
if (isRgb(color)) {
|
|
18
|
+
// already in RGB format; simply return it
|
|
19
|
+
return {
|
|
20
|
+
color,
|
|
21
|
+
alpha,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const themeOverrideColors = UiGlobals?.ThemeOverrides?.colors || {};
|
|
26
|
+
if (themeOverrideColors[color]) {
|
|
27
|
+
color = themeOverrideColors[color];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Detect 'primary.100:alpha.20' format
|
|
31
|
+
regex = /^([\w#\.]+)(:alpha\.([\d]{1,2}))?$/;
|
|
32
|
+
matches = color.match(regex);
|
|
33
|
+
if (matches[3]) {
|
|
34
|
+
// alpha part exists. parse it
|
|
35
|
+
alpha = parseInt(matches[3], 10) / 100; // convert '20' to .2
|
|
36
|
+
}
|
|
37
|
+
if (matches[1]) {
|
|
38
|
+
// color part exists. parse it
|
|
39
|
+
color = matches[1];
|
|
40
|
+
regex = /^(.+)\.([\d]{3})$/;
|
|
41
|
+
matches = color.match(regex);
|
|
42
|
+
if (matches) {
|
|
43
|
+
// color is in dot notation, like 'primary.200'
|
|
44
|
+
color = matches[1];
|
|
45
|
+
const whichValue = parseInt(matches[2], 10);
|
|
46
|
+
if (themeOverrideColors[color]?.[whichValue]) {
|
|
47
|
+
color = themeOverrideColors[color][whichValue];
|
|
48
|
+
}
|
|
49
|
+
} else if (themeOverrideColors[color]) {
|
|
50
|
+
// color is of form 'hover'
|
|
51
|
+
color = themeOverrideColors[color];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!isRgb(color)) {
|
|
55
|
+
color = nbToRgb(color).color;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
color,
|
|
62
|
+
alpha,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -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 =
|
|
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({
|
|
8
|
+
const [windowSize, setWindowSize] = useState({
|
|
9
|
+
width: window.innerWidth,
|
|
10
|
+
height: window.innerHeight
|
|
11
|
+
});
|
|
8
12
|
|
|
9
13
|
const handleSize = () => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
const
|
|
15
|
+
existingSize = windowSize,
|
|
16
|
+
newSize = {
|
|
17
|
+
width: window.innerWidth,
|
|
18
|
+
height: window.innerHeight
|
|
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: '#
|
|
18
|
-
hover: '#
|
|
19
|
-
selectedHover: '#
|
|
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',
|