@onehat/ui 0.2.49 → 0.2.51
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 +1 -1
- package/src/Components/Buttons/IconButton.js +4 -0
- package/src/Components/Buttons/PlusMinusButton.js +40 -0
- package/src/Components/Filter/NumberRange.js +2 -0
- package/src/Components/Form/Field/Combo/Combo.js +27 -7
- package/src/Components/Form/Field/Date.js +1 -0
- package/src/Components/Form/Field/Number.js +1 -1
- package/src/Components/Form/Form.js +14 -3
- package/src/Components/Hoc/withFilters.js +398 -375
- package/src/Components/index.js +2 -0
- package/src/Constants/Styles.js +1 -0
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
Spinner,
|
|
6
6
|
Tooltip,
|
|
7
7
|
} from 'native-base';
|
|
8
|
+
import styles from '../../Constants/Styles.js';
|
|
8
9
|
|
|
9
10
|
const IconButton = React.forwardRef((props, ref) => {
|
|
10
11
|
const {
|
|
@@ -28,6 +29,9 @@ const IconButton = React.forwardRef((props, ref) => {
|
|
|
28
29
|
justifyContent="center"
|
|
29
30
|
alignItems="center"
|
|
30
31
|
p={2}
|
|
32
|
+
_disabled={{
|
|
33
|
+
bg: styles.ICON_BUTTON_BG_DISABLED,
|
|
34
|
+
}}
|
|
31
35
|
{...props}
|
|
32
36
|
>
|
|
33
37
|
{icon}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Row,
|
|
4
|
+
Text,
|
|
5
|
+
} from 'native-base';
|
|
6
|
+
import IconButton from './IconButton.js';
|
|
7
|
+
import Plus from '../Icons/Plus.js';
|
|
8
|
+
import Minus from '../Icons/Minus.js';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const PlusMinusButton = React.forwardRef((props, ref) => {
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
isPlusDisabled = false,
|
|
15
|
+
isMinusDisabled = false,
|
|
16
|
+
plusHandler = () => {},
|
|
17
|
+
minusHandler = () => {},
|
|
18
|
+
} = props;
|
|
19
|
+
|
|
20
|
+
return <Row {...props}>
|
|
21
|
+
<Row alignItems="center">
|
|
22
|
+
<IconButton
|
|
23
|
+
icon={<Minus color="#fff" />}
|
|
24
|
+
onPress={minusHandler}
|
|
25
|
+
bg="primary.200"
|
|
26
|
+
isDisabled={isMinusDisabled}
|
|
27
|
+
/>
|
|
28
|
+
<IconButton
|
|
29
|
+
icon={<Plus color="#fff" />}
|
|
30
|
+
onPress={plusHandler}
|
|
31
|
+
bg="primary.200"
|
|
32
|
+
isDisabled={isPlusDisabled}
|
|
33
|
+
ml={1}
|
|
34
|
+
/>
|
|
35
|
+
</Row>
|
|
36
|
+
</Row>;
|
|
37
|
+
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export default PlusMinusButton;
|
|
@@ -74,6 +74,7 @@ import _ from 'lodash';
|
|
|
74
74
|
minValue={minValue}
|
|
75
75
|
maxValue={maxValue}
|
|
76
76
|
tooltip={(tooltip ? tooltip + ' ' : '') + 'Low'}
|
|
77
|
+
maxWidth={120}
|
|
77
78
|
/>
|
|
78
79
|
<Text px={2} userSelect="none">to</Text>
|
|
79
80
|
<Number
|
|
@@ -83,6 +84,7 @@ import _ from 'lodash';
|
|
|
83
84
|
minValue={minValue}
|
|
84
85
|
maxValue={maxValue}
|
|
85
86
|
tooltip={(tooltip ? tooltip + ' ' : '') + 'High'}
|
|
87
|
+
maxWidth={120}
|
|
86
88
|
/>
|
|
87
89
|
</Row>;
|
|
88
90
|
},
|
|
@@ -178,17 +178,32 @@ export function Combo(props) {
|
|
|
178
178
|
const {
|
|
179
179
|
relatedTarget
|
|
180
180
|
} = e;
|
|
181
|
+
|
|
182
|
+
// If user focused on the trigger and text is blank, clear the selection and close the menu
|
|
183
|
+
if ((triggerRef.current === relatedTarget || triggerRef.current.contains(relatedTarget)) && (_.isEmpty(textValue) || _.isNil(textValue))) {
|
|
184
|
+
setSelection([]); // delete current selection
|
|
185
|
+
hideMenu();
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
181
188
|
|
|
182
|
-
// If user
|
|
183
|
-
if (
|
|
189
|
+
// If user focused on the menu or trigger, ignore this blur
|
|
190
|
+
if (triggerRef.current === relatedTarget ||
|
|
191
|
+
triggerRef.current.contains(relatedTarget) ||
|
|
192
|
+
menuRef.current=== relatedTarget ||
|
|
193
|
+
menuRef.current?.contains(relatedTarget)) {
|
|
184
194
|
return;
|
|
185
195
|
}
|
|
186
196
|
|
|
187
197
|
if (!relatedTarget ||
|
|
188
|
-
(
|
|
198
|
+
(
|
|
199
|
+
!inputRef.current.contains(relatedTarget) &&
|
|
200
|
+
triggerRef.current !== relatedTarget &&
|
|
201
|
+
(!menuRef.current || !menuRef.current.contains(relatedTarget))
|
|
202
|
+
)
|
|
203
|
+
) {
|
|
189
204
|
hideMenu();
|
|
190
205
|
}
|
|
191
|
-
if (textValue
|
|
206
|
+
if (_.isEmpty(textValue) || _.isNil(textValue)) {
|
|
192
207
|
setSelection([]); // delete current selection
|
|
193
208
|
|
|
194
209
|
} else if (isManuallyEnteringText) {
|
|
@@ -221,12 +236,17 @@ export function Combo(props) {
|
|
|
221
236
|
inputRef.current.focus();
|
|
222
237
|
},
|
|
223
238
|
onTriggerBlur = (e) => {
|
|
224
|
-
if (!isMenuShown) {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
239
|
const {
|
|
228
240
|
relatedTarget
|
|
229
241
|
} = e;
|
|
242
|
+
|
|
243
|
+
if (_.isEmpty(textValue) || _.isNil(textValue)) {
|
|
244
|
+
setSelection([]); // delete current selection
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (!isMenuShown) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
230
250
|
if (!relatedTarget ||
|
|
231
251
|
(!inputRef.current.contains(relatedTarget) && triggerRef.current !== relatedTarget && !menuRef.current.contains(relatedTarget))) {
|
|
232
252
|
hideMenu();
|
|
@@ -119,7 +119,7 @@ function NumberElement(props) {
|
|
|
119
119
|
isIncrementDisabled = typeof maxValue !== 'undefined' && value === maxValue,
|
|
120
120
|
isDecrementDisabled = typeof minValue !== 'undefined' && (value === minValue || (!value && minValue === 0));
|
|
121
121
|
|
|
122
|
-
return <Row flex={1} h="100%" p={0} borderWidth={1} borderColor="trueGray.400" borderRadius={6}>
|
|
122
|
+
return <Row flex={1} h="100%" p={0} borderWidth={1} borderColor="trueGray.400" borderRadius={6} {...props}>
|
|
123
123
|
<IconButton
|
|
124
124
|
icon={<Icon as={Minus} color={isDecrementDisabled ? 'disabled' : 'trueGray.500'} />}
|
|
125
125
|
onPress={onDecrement}
|
|
@@ -62,7 +62,8 @@ function Form(props) {
|
|
|
62
62
|
validator, // custom validator, mainly for EDITOR_TYPE__PLAIN
|
|
63
63
|
footerProps = {},
|
|
64
64
|
buttonGroupProps = {}, // buttons in footer
|
|
65
|
-
onBack,
|
|
65
|
+
onBack,
|
|
66
|
+
onReset,
|
|
66
67
|
onViewMode,
|
|
67
68
|
additionalButtons = [],
|
|
68
69
|
ancillaryComponents = [],
|
|
@@ -360,7 +361,12 @@ function Form(props) {
|
|
|
360
361
|
let element = <Element
|
|
361
362
|
name={name}
|
|
362
363
|
value={value}
|
|
363
|
-
onChangeValue={
|
|
364
|
+
onChangeValue={(value) => {
|
|
365
|
+
onChange(value); // form onChange handler
|
|
366
|
+
if (propsToPass.onChange) {
|
|
367
|
+
propsToPass.onChange(value); // item onChange handler
|
|
368
|
+
}
|
|
369
|
+
}}
|
|
364
370
|
onBlur={onBlur}
|
|
365
371
|
selectorId={selectorId}
|
|
366
372
|
selectorSelected={selectorSelected}
|
|
@@ -507,7 +513,12 @@ function Form(props) {
|
|
|
507
513
|
<Button.Group space={2} {...buttonGroupProps}>
|
|
508
514
|
{!isViewOnly && <IconButton
|
|
509
515
|
key="resetBtn"
|
|
510
|
-
onPress={() =>
|
|
516
|
+
onPress={() => {
|
|
517
|
+
if (onReset) {
|
|
518
|
+
onReset();
|
|
519
|
+
}
|
|
520
|
+
reset();
|
|
521
|
+
}}
|
|
511
522
|
icon={<Rotate color="#fff" />}
|
|
512
523
|
/>}
|
|
513
524
|
{!isViewOnly && onCancel && <Button
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, } from 'react';
|
|
1
|
+
import { useState, useEffect, useId, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Column,
|
|
4
4
|
Modal,
|
|
@@ -17,351 +17,425 @@ import _ from 'lodash';
|
|
|
17
17
|
|
|
18
18
|
// Filters only work with Repository; not data array
|
|
19
19
|
|
|
20
|
+
// Yet to do:
|
|
21
|
+
// - Save user choice in cookie for next time this component loads
|
|
22
|
+
//
|
|
23
|
+
// Model defaultFilters should adjust to this new arrangement
|
|
24
|
+
|
|
20
25
|
export default function withFilters(WrappedComponent) {
|
|
21
26
|
return (props) => {
|
|
22
27
|
const {
|
|
28
|
+
// config
|
|
23
29
|
useFilters = false,
|
|
24
30
|
searchAllText = true,
|
|
25
31
|
showLabels = true,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
filter3StartingValue = null,
|
|
34
|
-
filter4StartingValue = null,
|
|
35
|
-
filter5StartingValue = null,
|
|
32
|
+
showFilterSelector = true,
|
|
33
|
+
defaultFilters = [], // likely a list of field names, possibly could be of shape below
|
|
34
|
+
customFilters = [], // of shape: { title, type, field, value, getRepoFilters(value) }
|
|
35
|
+
minFilters = 3,
|
|
36
|
+
maxFilters = 6,
|
|
37
|
+
getSaved,
|
|
38
|
+
setSaved,
|
|
36
39
|
|
|
37
40
|
// withData
|
|
38
41
|
Repository,
|
|
39
|
-
} = props
|
|
40
|
-
styles = UiGlobals.styles;
|
|
42
|
+
} = props;
|
|
41
43
|
|
|
42
|
-
let modal,
|
|
44
|
+
let modal = null,
|
|
43
45
|
topToolbar = null;
|
|
44
46
|
|
|
45
47
|
if (useFilters && Repository) {
|
|
48
|
+
|
|
46
49
|
const
|
|
50
|
+
// aliases
|
|
51
|
+
{
|
|
52
|
+
defaultFilters: modelDefaultFilters,
|
|
53
|
+
filterTypes: modelFilterTypes,
|
|
54
|
+
titles: modelTitles,
|
|
55
|
+
virtualFields: modelVirtualFields,
|
|
56
|
+
excludeFields: modelExcludeFields,
|
|
57
|
+
filteringDisabled: modelFilteringDisabled,
|
|
58
|
+
} = Repository.getSchema().model,
|
|
59
|
+
id = useId(),
|
|
60
|
+
|
|
61
|
+
// determine the starting filters
|
|
62
|
+
startingFilters = !_.isEmpty(customFilters) ? customFilters : // custom filters override component filters
|
|
63
|
+
!_.isEmpty(defaultFilters) ? defaultFilters : // component filters override model filters
|
|
64
|
+
!_.isEmpty(modelDefaultFilters) ? modelDefaultFilters : [],
|
|
65
|
+
isUsingCustomFilters = startingFilters === customFilters,
|
|
47
66
|
[isReady, setIsReady] = useState(false),
|
|
48
67
|
[isFilterSelectorShown, setIsFilterSelectorShown] = useState(false),
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
[filter3Value, setFilter3Value] = useState(filter3StartingValue),
|
|
63
|
-
[filter4Value, setFilter4Value] = useState(filter4StartingValue),
|
|
64
|
-
[filter5Value, setFilter5Value] = useState(filter5StartingValue),
|
|
65
|
-
[filterFields, setFilterFields] = useState([]),
|
|
66
|
-
onFilterChange = (ix, value) => {
|
|
67
|
-
switch(ix) {
|
|
68
|
-
case 'q':
|
|
69
|
-
setFilterQValue(value);
|
|
70
|
-
break;
|
|
71
|
-
case 0:
|
|
72
|
-
setFilter1Value(value);
|
|
73
|
-
break;
|
|
74
|
-
case 1:
|
|
75
|
-
setFilter2Value(value);
|
|
76
|
-
break;
|
|
77
|
-
case 2:
|
|
78
|
-
setFilter3Value(value);
|
|
79
|
-
break;
|
|
80
|
-
case 3:
|
|
81
|
-
setFilter4Value(value);
|
|
82
|
-
break;
|
|
83
|
-
case 4:
|
|
84
|
-
setFilter5Value(value);
|
|
85
|
-
break;
|
|
86
|
-
default:
|
|
68
|
+
getFormattedFilter = (filter) => {
|
|
69
|
+
let formatted = null;
|
|
70
|
+
if (_.isString(filter)) {
|
|
71
|
+
const field = filter;
|
|
72
|
+
formatted = {
|
|
73
|
+
field,
|
|
74
|
+
title: modelTitles[field],
|
|
75
|
+
type: modelFilterTypes[field],
|
|
76
|
+
value: null, // value starts as null
|
|
77
|
+
};
|
|
78
|
+
} else if (_.isPlainObject(filter)) {
|
|
79
|
+
// already formatted
|
|
80
|
+
formatted = filter;
|
|
87
81
|
}
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
return formatted;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
let formattedStartingFilters = [],
|
|
86
|
+
startingSlots = [];
|
|
87
|
+
if (!isReady) {
|
|
88
|
+
// Generate initial starting state
|
|
89
|
+
if (searchAllText) {
|
|
90
|
+
formattedStartingFilters.push({ field: 'q', title: 'Search all text fields', type: 'Input', value: null, });
|
|
91
|
+
}
|
|
92
|
+
_.each(startingFilters, (filter) => {
|
|
90
93
|
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
94
|
+
formattedFilter = getFormattedFilter(filter),
|
|
95
|
+
field = formattedFilter.field;
|
|
96
|
+
formattedStartingFilters.push(formattedFilter);
|
|
97
|
+
if (!isUsingCustomFilters) {
|
|
98
|
+
startingSlots.push(field);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
if (startingSlots.length < minFilters) {
|
|
102
|
+
for (let i = startingSlots.length; i < minFilters; i++) {
|
|
103
|
+
startingSlots.push(null);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const
|
|
109
|
+
[filters, setFiltersRaw] = useState(formattedStartingFilters), // array of formatted filters
|
|
110
|
+
[slots, setSlots] = useState(startingSlots), // array of field names user is currently filtering on; blank slots have a null entry in array
|
|
111
|
+
[modalFilters, setModalFilters] = useState([]),
|
|
112
|
+
[modalSlots, setModalSlots] = useState([]),
|
|
113
|
+
[previousFilterNames, setPreviousFilterNames] = useState([]), // names of filters the repository used last query
|
|
114
|
+
canAddSlot = (() => {
|
|
115
|
+
let canAdd = true;
|
|
116
|
+
if (!!maxFilters && modalSlots.length >= maxFilters) {
|
|
117
|
+
canAdd = false; // maxFilters has been reached
|
|
118
|
+
}
|
|
119
|
+
if (canAdd) {
|
|
120
|
+
_.each(modalSlots, (field) => {
|
|
121
|
+
if (_.isNil(field)) {
|
|
122
|
+
canAdd = false; // at least one slot has no selected field to filter
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return canAdd;
|
|
128
|
+
})(),
|
|
129
|
+
canDeleteSlot = modalSlots.length > minFilters,
|
|
130
|
+
onAddSlot = () => {
|
|
131
|
+
if (!canAddSlot) {
|
|
132
|
+
return;
|
|
98
133
|
}
|
|
99
|
-
|
|
134
|
+
const newSlots = _.clone(modalSlots);
|
|
135
|
+
newSlots.push(null);
|
|
136
|
+
setModalSlots(newSlots);
|
|
100
137
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
case 0:
|
|
105
|
-
field = filter1Field;
|
|
106
|
-
break;
|
|
107
|
-
case 1:
|
|
108
|
-
field = filter2Field;
|
|
109
|
-
break;
|
|
110
|
-
case 2:
|
|
111
|
-
field = filter3Field;
|
|
112
|
-
break;
|
|
113
|
-
case 3:
|
|
114
|
-
field = filter4Field;
|
|
115
|
-
break;
|
|
116
|
-
case 4:
|
|
117
|
-
field = filter5Field;
|
|
118
|
-
break;
|
|
119
|
-
default:
|
|
138
|
+
onDeleteSlot = () => {
|
|
139
|
+
if (!canDeleteSlot) {
|
|
140
|
+
return;
|
|
120
141
|
}
|
|
121
|
-
|
|
142
|
+
const
|
|
143
|
+
newFilters = _.clone(modalFilters),
|
|
144
|
+
newSlots = _.clone(modalSlots);
|
|
145
|
+
newFilters.pop();
|
|
146
|
+
newSlots.pop();
|
|
147
|
+
setModalFilters(newFilters);
|
|
148
|
+
setModalSlots(newSlots);
|
|
122
149
|
},
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
default:
|
|
150
|
+
setFilters = (filters, doSetSlots = true, save = true) => {
|
|
151
|
+
setFiltersRaw(filters);
|
|
152
|
+
|
|
153
|
+
if (doSetSlots) {
|
|
154
|
+
const newSlots = [];
|
|
155
|
+
_.each(filters, (filter, ix) => {
|
|
156
|
+
if (searchAllText && ix === 0) {
|
|
157
|
+
return; // skip
|
|
158
|
+
}
|
|
159
|
+
newSlots.push(filter.field);
|
|
160
|
+
});
|
|
161
|
+
if (newSlots.length < minFilters) {
|
|
162
|
+
// Add more slots until we get to minFilters
|
|
163
|
+
for(let i = newSlots.length; i < minFilters; i++) {
|
|
164
|
+
newSlots.push(null);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
setSlots(newSlots);
|
|
168
|
+
}
|
|
169
|
+
if (save && setSaved) {
|
|
170
|
+
setSaved(id + '-filters', filters);
|
|
145
171
|
}
|
|
146
|
-
return value;
|
|
147
172
|
},
|
|
148
|
-
|
|
149
|
-
|
|
173
|
+
onFilterChangeValue = (field, value) => {
|
|
174
|
+
// handler for when a filter value changes
|
|
175
|
+
const newFilters = [];
|
|
176
|
+
_.each(filters, (filter) => {
|
|
177
|
+
if (filter.field === field) {
|
|
178
|
+
filter.value = value;
|
|
179
|
+
}
|
|
180
|
+
newFilters.push(filter);
|
|
181
|
+
});
|
|
182
|
+
setFilters(newFilters, false);
|
|
183
|
+
},
|
|
184
|
+
onClearFilters = () => {
|
|
185
|
+
// Clears values for all active filters
|
|
186
|
+
const newFilters = [];
|
|
187
|
+
_.each(filters, (filter) => {
|
|
188
|
+
filter.value = null;
|
|
189
|
+
newFilters.push(filter);
|
|
190
|
+
});
|
|
191
|
+
setFilters(newFilters, false);
|
|
192
|
+
},
|
|
193
|
+
getFilterByField = (field) => {
|
|
194
|
+
return _.find(filters, (filter) => {
|
|
195
|
+
return filter.field === field;
|
|
196
|
+
});
|
|
197
|
+
},
|
|
198
|
+
getFilterValue = (field) => {
|
|
199
|
+
const filter = getFilterByField(field);
|
|
200
|
+
return filter?.value;
|
|
201
|
+
},
|
|
202
|
+
getFilterType = (field) => {
|
|
203
|
+
// Finds filter type for the field name, from active filters
|
|
204
|
+
const filter = getFilterByField(field);
|
|
205
|
+
return filter?.type;
|
|
206
|
+
},
|
|
207
|
+
getIsFilterRange = (field) => {
|
|
208
|
+
// determines if filter is a "range" filter
|
|
209
|
+
const filterType = getFilterType(field);
|
|
150
210
|
return inArray(filterType, ['NumberRange', 'DateRange']);
|
|
151
211
|
},
|
|
152
212
|
renderFilters = () => {
|
|
153
|
-
if (!Repository) {
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
213
|
const
|
|
158
|
-
{
|
|
159
|
-
titles = [],
|
|
160
|
-
filterTypes = [],
|
|
161
|
-
virtualFields = [],
|
|
162
|
-
excludeFields = [],
|
|
163
|
-
} = Repository.getSchema().model,
|
|
164
214
|
filterProps = {
|
|
165
215
|
mx: 1,
|
|
166
216
|
},
|
|
167
|
-
filterElements = []
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
/>);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
if (inArray(fieldName, virtualFields) || inArray(fieldName, excludeFields)) {
|
|
184
|
-
return; // skip
|
|
185
|
-
}
|
|
186
|
-
const filterType = filterTypes[fieldName];
|
|
187
|
-
let Element,
|
|
188
|
-
modelProps = {};
|
|
189
|
-
if (_.isString(filterType)) {
|
|
190
|
-
Element = getComponentFromType(filterType);
|
|
191
|
-
} else if (_.isPlainObject(filterType)) {
|
|
192
|
-
const {
|
|
193
|
-
type,
|
|
194
|
-
...p
|
|
195
|
-
} = filterType;
|
|
196
|
-
modelProps = p;
|
|
197
|
-
Element = getComponentFromType(type);
|
|
198
|
-
}
|
|
199
|
-
if (!Element) {
|
|
200
|
-
debugger;
|
|
217
|
+
filterElements = [];
|
|
218
|
+
_.each(filters, (filter, ix) => {
|
|
219
|
+
let Element,
|
|
220
|
+
elementProps = {};
|
|
221
|
+
const {
|
|
222
|
+
field,
|
|
223
|
+
type: filterType,
|
|
224
|
+
} = filter;
|
|
225
|
+
|
|
226
|
+
if (_.isString(filterType)) {
|
|
227
|
+
Element = getComponentFromType(filterType);
|
|
228
|
+
if (filterType === 'Input') {
|
|
229
|
+
elementProps.autoSubmit = true;
|
|
201
230
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (showLabels) {
|
|
212
|
-
filterElement = <Row key={'label-' + ix} alignItems="center">
|
|
213
|
-
<Text ml={2} mr={1} fontSize={styles.FILTER_LABEL_FONTSIZE}>{titles[fieldName]}</Text>
|
|
214
|
-
{filterElement}
|
|
215
|
-
</Row>;
|
|
231
|
+
} else if (_.isPlainObject(filterType)) {
|
|
232
|
+
const {
|
|
233
|
+
type,
|
|
234
|
+
...p
|
|
235
|
+
} = filterType;
|
|
236
|
+
elementProps = p;
|
|
237
|
+
Element = getComponentFromType(type);
|
|
238
|
+
if (type === 'Input') {
|
|
239
|
+
elementProps.autoSubmit = true;
|
|
216
240
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
241
|
+
}
|
|
242
|
+
if (field === 'q') {
|
|
243
|
+
elementProps.flex = 1;
|
|
244
|
+
elementProps.minWidth = 100;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const tooltip = filter.tooltip || filter.title || modelTitles[filter.field];
|
|
248
|
+
let filterElement = <Element
|
|
249
|
+
key={'filter-' + field}
|
|
250
|
+
tooltip={tooltip}
|
|
251
|
+
placeholder={tooltip}
|
|
252
|
+
value={getFilterValue(field)}
|
|
253
|
+
onChangeValue={(value) => onFilterChangeValue(field, value)}
|
|
254
|
+
{...filterProps}
|
|
255
|
+
{...elementProps}
|
|
256
|
+
/>;
|
|
257
|
+
if (showLabels && field !== 'q') {
|
|
258
|
+
filterElement = <Row key={'label-' + ix} alignItems="center">
|
|
259
|
+
<Text ml={2} mr={1} fontSize={UiGlobals.styles.FILTER_LABEL_FONTSIZE}>{modelTitles[field]}</Text>
|
|
260
|
+
{filterElement}
|
|
261
|
+
</Row>;
|
|
262
|
+
}
|
|
263
|
+
filterElements.push(filterElement);
|
|
264
|
+
});
|
|
238
265
|
return filterElements;
|
|
239
|
-
},
|
|
240
|
-
setFiltersOn = (ix, filters, newFilterFields) => {
|
|
241
|
-
const
|
|
242
|
-
filterIxField = getFilterField(ix),
|
|
243
|
-
filterIxValue = getFilterValue(ix),
|
|
244
|
-
isFilterRange = getIsFilterRange(ix);
|
|
245
|
-
let highValue,
|
|
246
|
-
lowValue,
|
|
247
|
-
highField,
|
|
248
|
-
lowField;
|
|
249
|
-
if (isFilterRange && !!filterIxValue) {
|
|
250
|
-
highValue = filterIxValue.high;
|
|
251
|
-
lowValue = filterIxValue.low;
|
|
252
|
-
highField = filterIxField + ' <=';
|
|
253
|
-
lowField = filterIxField + ' >=';
|
|
254
|
-
|
|
255
|
-
newFilterFields.push(highField);
|
|
256
|
-
newFilterFields.push(lowField);
|
|
257
|
-
filters.push({ name: highField, value: highValue, });
|
|
258
|
-
filters.push({ name: lowField, value: lowValue, });
|
|
259
|
-
} else {
|
|
260
|
-
newFilterFields.push(filterIxField);
|
|
261
|
-
filters.push({ name: filterIxField, value: filterIxValue, });
|
|
262
|
-
}
|
|
263
|
-
},
|
|
264
|
-
onClearFilters = () => {
|
|
265
|
-
setFilterQValue(null);
|
|
266
|
-
setFilter1Value(null);
|
|
267
|
-
setFilter2Value(null);
|
|
268
|
-
setFilter3Value(null);
|
|
269
|
-
setFilter4Value(null);
|
|
270
|
-
setFilter5Value(null);
|
|
271
266
|
};
|
|
272
267
|
|
|
273
268
|
useEffect(() => {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
269
|
+
(async () => {
|
|
270
|
+
|
|
271
|
+
// Whenever the filters change in some way, make repository conform to these new filters
|
|
272
|
+
const newRepoFilters = [];
|
|
273
|
+
let filtersToUse = filters
|
|
277
274
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (filter3Field) {
|
|
286
|
-
setFiltersOn(2, filters, newFilterFields);
|
|
287
|
-
}
|
|
288
|
-
if (filter4Field) {
|
|
289
|
-
setFiltersOn(3, filters, newFilterFields);
|
|
290
|
-
}
|
|
291
|
-
if (filter5Field) {
|
|
292
|
-
setFiltersOn(4, filters, newFilterFields);
|
|
293
|
-
}
|
|
294
|
-
if (searchAllText && !_.isEmpty(filterQValue)) {
|
|
295
|
-
const q = 'q';
|
|
296
|
-
newFilterFields.push(q);
|
|
297
|
-
filters.push({ name: q, value: filterQValue, });
|
|
298
|
-
if (Repository.searchAncillary && !Repository.hasBaseParam('searchAncillary')) {
|
|
299
|
-
Repository.setBaseParam('searchAncillary', true);
|
|
275
|
+
if (!isReady && getSaved) {
|
|
276
|
+
const savedFilters = await getSaved(id + '-filters');
|
|
277
|
+
if (!_.isEmpty(savedFilters)) {
|
|
278
|
+
// load saved filters
|
|
279
|
+
filtersToUse = savedFilters;
|
|
280
|
+
setFilters(savedFilters, true, false); // false to skip save
|
|
281
|
+
}
|
|
300
282
|
}
|
|
301
|
-
}
|
|
302
|
-
setFilterFields(newFilterFields);
|
|
303
283
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
284
|
+
if (isUsingCustomFilters) {
|
|
285
|
+
_.each(filtersToUse, (filter) => {
|
|
286
|
+
const repoFiltersFromFilter = filter.getRepoFilters(value);
|
|
287
|
+
_.each(repoFiltersFromFilter, (repoFilter) => { // one custom filter might generate multiple filters for the repository
|
|
288
|
+
newRepoFilters.push(repoFilter);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
} else {
|
|
292
|
+
const newFilterNames = [];
|
|
293
|
+
_.each(filtersToUse, (filter) => {
|
|
294
|
+
const {
|
|
295
|
+
field,
|
|
296
|
+
value,
|
|
297
|
+
} = filter,
|
|
298
|
+
isFilterRange = getIsFilterRange(field);
|
|
299
|
+
if (isFilterRange) {
|
|
300
|
+
if (!!value) {
|
|
301
|
+
const
|
|
302
|
+
highField = field + ' <=',
|
|
303
|
+
lowField = field + ' >=',
|
|
304
|
+
highValue = value.high,
|
|
305
|
+
lowValue = value.low;
|
|
306
|
+
newFilterNames.push(highField);
|
|
307
|
+
newFilterNames.push(lowField);
|
|
308
|
+
newRepoFilters.push({ name: highField, value: highValue, });
|
|
309
|
+
newRepoFilters.push({ name: lowField, value: lowValue, });
|
|
310
|
+
}
|
|
311
|
+
} else {
|
|
312
|
+
newFilterNames.push(field);
|
|
313
|
+
newRepoFilters.push({ name: field, value, });
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// Go through previousFilterNames and see if any are no longer used.
|
|
318
|
+
_.each(previousFilterNames, (name) => {
|
|
319
|
+
if (!inArray(name, newFilterNames)) {
|
|
320
|
+
newRepoFilters.push({ name, value: null, }); // no longer used, so set it to null so it'll be deleted
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
setPreviousFilterNames(newFilterNames);
|
|
308
324
|
}
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
Repository.filter(filters, null, false); // false so other filters remain
|
|
312
325
|
|
|
313
|
-
|
|
314
|
-
setIsReady(true);
|
|
315
|
-
}
|
|
326
|
+
Repository.filter(newRepoFilters, null, false); // false so other filters remain
|
|
316
327
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
328
|
+
if (searchAllText && Repository.searchAncillary && !Repository.hasBaseParam('searchAncillary')) {
|
|
329
|
+
Repository.setBaseParam('searchAncillary', true);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (!isReady) {
|
|
333
|
+
setIsReady(true);
|
|
334
|
+
}
|
|
335
|
+
})();
|
|
336
|
+
}, [filters]);
|
|
320
337
|
|
|
321
338
|
if (!isReady) {
|
|
322
339
|
return null;
|
|
323
340
|
}
|
|
324
341
|
|
|
342
|
+
const
|
|
343
|
+
renderedFilters = renderFilters(),
|
|
344
|
+
hasFilters = !!renderedFilters.length;
|
|
345
|
+
topToolbar = <Toolbar justifyContent="space-between" alignItems="center">
|
|
346
|
+
<Text pr={2} userSelect="none">Filters:{hasFilters ? '' : ' None'}</Text>
|
|
347
|
+
{renderedFilters}
|
|
348
|
+
<Row flex={hasFilters ? null : 1} justifyContent="flex-end">
|
|
349
|
+
<IconButton
|
|
350
|
+
key="clear"
|
|
351
|
+
_icon={{
|
|
352
|
+
as: Ban,
|
|
353
|
+
}}
|
|
354
|
+
ml={1}
|
|
355
|
+
onPress={onClearFilters}
|
|
356
|
+
tooltip="Clear all filters"
|
|
357
|
+
/>
|
|
358
|
+
{showFilterSelector && !isUsingCustomFilters && <IconButton
|
|
359
|
+
key="gear"
|
|
360
|
+
_icon={{
|
|
361
|
+
as: Gear,
|
|
362
|
+
}}
|
|
363
|
+
ml={1}
|
|
364
|
+
onPress={() => {
|
|
365
|
+
const f = filters;
|
|
366
|
+
const s = slots;
|
|
367
|
+
setModalFilters(filters);
|
|
368
|
+
setModalSlots(slots);
|
|
369
|
+
setIsFilterSelectorShown(true);
|
|
370
|
+
}}
|
|
371
|
+
tooltip="Swap filters"
|
|
372
|
+
/>}
|
|
373
|
+
</Row>
|
|
374
|
+
</Toolbar>;
|
|
325
375
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
filterComboProps.data = [];
|
|
329
|
-
const schemaModel = Repository.getSchema().model;
|
|
330
|
-
_.each(schemaModel.titles, (title, fieldName) => {
|
|
331
|
-
if (!inArray(fieldName, schemaModel.virtualFields) && !inArray(fieldName, schemaModel.excludeFields) && !inArray(fieldName, schemaModel.filteringDisabled)) {
|
|
332
|
-
filterComboProps.data.push([fieldName, title]);
|
|
333
|
-
}
|
|
334
|
-
});
|
|
376
|
+
if (isFilterSelectorShown) { // this is always false when isUsingCustomFilters
|
|
377
|
+
// Build the modal to select the filters
|
|
335
378
|
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
379
|
+
modalFilterElements = [],
|
|
380
|
+
usedFields = _.filter(_.map(modalFilters, (filter) => {
|
|
381
|
+
return filter?.field;
|
|
382
|
+
}), el => !_.isNil(el)),
|
|
383
|
+
formStartingValues = {};
|
|
384
|
+
|
|
385
|
+
_.each(modalSlots, (field, ix) => {
|
|
386
|
+
|
|
387
|
+
// Create the data for the combobox.
|
|
388
|
+
const data = [];
|
|
389
|
+
_.each(modelFilterTypes, (filterType, filterField) => {
|
|
390
|
+
if (inArray(filterField, usedFields) && field !== filterField) { // Show all filters not yet applied, but include the current filter
|
|
391
|
+
return; // skip, since it's already been used
|
|
392
|
+
}
|
|
393
|
+
data.push([ filterField, modelTitles[filterField] ]);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
const
|
|
397
|
+
ixPlusOne = (ix +1),
|
|
398
|
+
filterName = 'filter' + ixPlusOne;
|
|
399
|
+
|
|
400
|
+
modalFilterElements.push({
|
|
401
|
+
key: filterName,
|
|
402
|
+
name: filterName,
|
|
403
|
+
type: 'Combo',
|
|
404
|
+
label: 'Filter ' + ixPlusOne,
|
|
405
|
+
data,
|
|
406
|
+
onChange: (value) => {
|
|
407
|
+
const
|
|
408
|
+
newFilters = _.clone(modalFilters),
|
|
409
|
+
newSlots = _.clone(modalSlots),
|
|
410
|
+
i = searchAllText ? ixPlusOne : ix; // compensate for 'q' filter's possible presence
|
|
411
|
+
|
|
412
|
+
if (newFilters[i]?.value) {
|
|
413
|
+
newFilters[i].value = value;
|
|
414
|
+
} else {
|
|
415
|
+
newFilters[i] = getFormattedFilter(value);
|
|
416
|
+
}
|
|
417
|
+
newSlots[ix] = value;
|
|
418
|
+
|
|
419
|
+
setModalFilters(newFilters);
|
|
420
|
+
setModalSlots(newSlots);
|
|
421
|
+
},
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
formStartingValues[filterName] = field;
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
if (canAddSlot || canDeleteSlot) {
|
|
428
|
+
modalFilterElements.push({
|
|
429
|
+
type: 'PlusMinusButton',
|
|
430
|
+
name: 'plusMinusButton',
|
|
431
|
+
plusHandler: onAddSlot,
|
|
432
|
+
minusHandler: onDeleteSlot,
|
|
433
|
+
isPlusDisabled: !canAddSlot,
|
|
434
|
+
isMinusDisabled: !canDeleteSlot,
|
|
435
|
+
justifyContent: 'flex-end',
|
|
436
|
+
});
|
|
437
|
+
}
|
|
363
438
|
|
|
364
|
-
if (isFilterSelectorShown) {
|
|
365
439
|
modal = <Modal
|
|
366
440
|
isOpen={true}
|
|
367
441
|
onClose={() => setIsFilterSelectorShown(false)}
|
|
@@ -369,99 +443,48 @@ export default function withFilters(WrappedComponent) {
|
|
|
369
443
|
<Column bg="#fff" w={500}>
|
|
370
444
|
<FormPanel
|
|
371
445
|
title="Filter Selector"
|
|
372
|
-
instructions="Please select which fields to filter by.
|
|
446
|
+
instructions="Please select which fields to filter by."
|
|
373
447
|
flex={1}
|
|
374
|
-
startingValues={
|
|
375
|
-
filter1: filter1Field,
|
|
376
|
-
filter2: filter2Field,
|
|
377
|
-
filter3: filter3Field,
|
|
378
|
-
filter4: filter4Field,
|
|
379
|
-
filter5: filter5Field,
|
|
380
|
-
}}
|
|
448
|
+
startingValues={formStartingValues}
|
|
381
449
|
items={[
|
|
382
450
|
{
|
|
383
451
|
type: 'Column',
|
|
384
452
|
flex: 1,
|
|
385
|
-
items:
|
|
386
|
-
|
|
387
|
-
type: 'Combo',
|
|
388
|
-
label: 'Filter 1',
|
|
389
|
-
name: 'filter1',
|
|
390
|
-
onChangeValue: (value) => {
|
|
391
|
-
setFilter1FieldForModal(value);
|
|
392
|
-
},
|
|
393
|
-
...filterComboProps,
|
|
394
|
-
},
|
|
395
|
-
{
|
|
396
|
-
type: 'Combo',
|
|
397
|
-
label: 'Filter 2',
|
|
398
|
-
name: 'filter2',
|
|
399
|
-
onChangeValue: (value) => {
|
|
400
|
-
setFilter2FieldForModal(value);
|
|
401
|
-
},
|
|
402
|
-
...filterComboProps,
|
|
403
|
-
},
|
|
404
|
-
{
|
|
405
|
-
type: 'Combo',
|
|
406
|
-
label: 'Filter 3',
|
|
407
|
-
name: 'filter3',
|
|
408
|
-
onChangeValue: (value) => {
|
|
409
|
-
setFilter3FieldForModal(value);
|
|
410
|
-
},
|
|
411
|
-
...filterComboProps,
|
|
412
|
-
},
|
|
413
|
-
{
|
|
414
|
-
type: 'Combo',
|
|
415
|
-
label: 'Filter 4',
|
|
416
|
-
name: 'filter4',
|
|
417
|
-
onChangeValue: (value) => {
|
|
418
|
-
setFilter4FieldForModal(value);
|
|
419
|
-
},
|
|
420
|
-
...filterComboProps,
|
|
421
|
-
},
|
|
422
|
-
{
|
|
423
|
-
type: 'Combo',
|
|
424
|
-
label: 'Filter 5',
|
|
425
|
-
name: 'filter5',
|
|
426
|
-
onChangeValue: (value) => {
|
|
427
|
-
setFilter5FieldForModal(value);
|
|
428
|
-
},
|
|
429
|
-
...filterComboProps,
|
|
430
|
-
},
|
|
431
|
-
],
|
|
432
|
-
}, // END Column
|
|
453
|
+
items: modalFilterElements,
|
|
454
|
+
},
|
|
433
455
|
]}
|
|
434
456
|
onCancel={(e) => {
|
|
435
|
-
|
|
436
|
-
setFilter2FieldForModal(filter2Field);
|
|
437
|
-
setFilter3FieldForModal(filter3Field);
|
|
438
|
-
setFilter4FieldForModal(filter4Field);
|
|
439
|
-
setFilter5FieldForModal(filter5Field);
|
|
457
|
+
// Just close the modal
|
|
440
458
|
setIsFilterSelectorShown(false);
|
|
441
459
|
}}
|
|
442
460
|
onSave={(data, e) => {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
if (
|
|
448
|
-
|
|
449
|
-
setFilter2Value(null);
|
|
450
|
-
}
|
|
451
|
-
if (filter3FieldForModal !== filter3Field) {
|
|
452
|
-
setFilter3Field(filter3FieldForModal);
|
|
453
|
-
setFilter3Value(null);
|
|
454
|
-
}
|
|
455
|
-
if (filter4FieldForModal !== filter4Field) {
|
|
456
|
-
setFilter4Field(filter4FieldForModal);
|
|
457
|
-
setFilter4Value(null);
|
|
458
|
-
}
|
|
459
|
-
if (filter5FieldForModal !== filter5Field) {
|
|
460
|
-
setFilter5Field(filter5FieldForModal);
|
|
461
|
-
setFilter5Value(null);
|
|
461
|
+
// Conform filters to this new choice of filters
|
|
462
|
+
|
|
463
|
+
const newFilters = [];
|
|
464
|
+
|
|
465
|
+
if (searchAllText) {
|
|
466
|
+
newFilters.push(filters[0]);
|
|
462
467
|
}
|
|
468
|
+
|
|
469
|
+
// Conform the filters to the modal selection
|
|
470
|
+
_.each(data, (field, ix) => {
|
|
471
|
+
if (_.isEmpty(field) || !ix.match(/^filter/)) {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const newFilter = getFormattedFilter(field);
|
|
476
|
+
newFilters.push(newFilter);
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
setFilters(newFilters);
|
|
480
|
+
|
|
481
|
+
// Close the modal
|
|
463
482
|
setIsFilterSelectorShown(false);
|
|
464
483
|
}}
|
|
484
|
+
onReset={() => {
|
|
485
|
+
setModalFilters(filters);
|
|
486
|
+
setModalSlots(slots);
|
|
487
|
+
}}
|
|
465
488
|
/>
|
|
466
489
|
</Column>
|
|
467
490
|
</Modal>;
|
package/src/Components/index.js
CHANGED
|
@@ -35,6 +35,7 @@ import Number from './Form/Field/Number.js';
|
|
|
35
35
|
import NumberRange from './Filter/NumberRange.js';
|
|
36
36
|
import Panel from './Panel/Panel.js';
|
|
37
37
|
// import Picker from '../Components/Panel/Picker.js';
|
|
38
|
+
import PlusMinusButton from './Buttons/PlusMinusButton.js';
|
|
38
39
|
import RadioGroup from './Form/Field/RadioGroup/RadioGroup.js';
|
|
39
40
|
import TabPanel from './Panel/TabPanel.js';
|
|
40
41
|
import Tag from './Form/Field/Combo/Tag.js';
|
|
@@ -82,6 +83,7 @@ const components = {
|
|
|
82
83
|
NumberRange,
|
|
83
84
|
Panel,
|
|
84
85
|
// Picker,
|
|
86
|
+
PlusMinusButton,
|
|
85
87
|
RadioGroup,
|
|
86
88
|
TabPanel,
|
|
87
89
|
Tag,
|
package/src/Constants/Styles.js
CHANGED
|
@@ -61,6 +61,7 @@ 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_DISABLED: 'trueGray.200',
|
|
64
65
|
PANEL_FOOTER_BG: 'primary.100', // :alpha.50
|
|
65
66
|
PANEL_HEADER_BG: 'primary.100',
|
|
66
67
|
PANEL_HEADER_BG_VERTICAL: 'primary.100',
|