orc-shared 5.99.0-dev.4 → 5.99.0-dev.6
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/dist/components/Form/Inputs/MultiSelector.js +67 -12
- package/dist/components/Form/Inputs/Selector.js +13 -10
- package/dist/components/MaterialUI/Inputs/Select.js +164 -114
- package/dist/components/MaterialUI/Inputs/SelectProps.js +10 -2
- package/dist/hocs/withScrollBox.js +3 -8
- package/dist/hooks/useWindowSize.js +88 -0
- package/dist/sharedMessages.js +8 -0
- package/package.json +1 -1
- package/src/components/Form/Inputs/MultiSelector.js +55 -5
- package/src/components/Form/Inputs/MultiSelector.test.js +259 -39
- package/src/components/Form/Inputs/Selector.js +12 -4
- package/src/components/Form/Inputs/Selector.test.js +27 -12
- package/src/components/MaterialUI/Inputs/Select.js +134 -87
- package/src/components/MaterialUI/Inputs/Select.test.js +170 -30
- package/src/components/MaterialUI/Inputs/SelectProps.js +9 -1
- package/src/components/MaterialUI/Inputs/SelectProps.test.js +8 -0
- package/src/hocs/withScrollBox.js +2 -8
- package/src/hooks/useMultipleFieldEditState.test.js +0 -1
- package/src/hooks/useWindowSize.js +39 -0
- package/src/hooks/useWindowSize.test.js +68 -0
- package/src/sharedMessages.js +8 -0
- package/src/translations/en-US.json +2 -0
- package/src/translations/fr-CA.json +2 -0
|
@@ -8,11 +8,13 @@ import TooltippedTypography from "./../DataDisplay/TooltippedElements/Tooltipped
|
|
|
8
8
|
import Icon from "./../DataDisplay/Icon";
|
|
9
9
|
import IconButton from "@material-ui/core/IconButton";
|
|
10
10
|
import { ListSubheader } from "@material-ui/core";
|
|
11
|
+
import FormControl from "@material-ui/core/FormControl";
|
|
12
|
+
import useWindowSize from "../../../hooks/useWindowSize";
|
|
11
13
|
|
|
12
14
|
const useStyles = makeStyles(theme => ({
|
|
13
|
-
baseItem: {
|
|
14
|
-
maxWidth: theme.spacing(35),
|
|
15
|
-
},
|
|
15
|
+
baseItem: props => ({
|
|
16
|
+
...(props.autoWidth ? { maxWidth: theme.spacing(35) } : { maxWidth: theme.spacing(props.multipleWidthSpacing) }),
|
|
17
|
+
}),
|
|
16
18
|
level0: {},
|
|
17
19
|
level1: {
|
|
18
20
|
paddingLeft: theme.spacing(theme.indent),
|
|
@@ -42,10 +44,8 @@ const useStyles = makeStyles(theme => ({
|
|
|
42
44
|
display: "flex",
|
|
43
45
|
flexDirection: "column",
|
|
44
46
|
},
|
|
45
|
-
selectPaper: {
|
|
47
|
+
selectPaper: props => ({
|
|
46
48
|
border: `1px solid ${theme.palette.grey.borders}`,
|
|
47
|
-
minWidth: `auto !important`,
|
|
48
|
-
width: `auto !important`,
|
|
49
49
|
"& ul": {
|
|
50
50
|
minWidth: theme.spacing(17.5),
|
|
51
51
|
maxHeight: theme.spacing(30),
|
|
@@ -62,16 +62,23 @@ const useStyles = makeStyles(theme => ({
|
|
|
62
62
|
borderRadius: 0,
|
|
63
63
|
whiteSpace: "normal",
|
|
64
64
|
"&:hover": {
|
|
65
|
-
backgroundColor: theme.palette.primary.
|
|
65
|
+
backgroundColor: theme.palette.primary.main,
|
|
66
66
|
},
|
|
67
67
|
"&:focus, &:active": {
|
|
68
68
|
borderRadius: 0,
|
|
69
|
+
boxShadow: props.multiple ? "none" : `0 0 ${theme.spacing(0.4)} #4fa1f0`,
|
|
69
70
|
"&:hover": {
|
|
70
|
-
backgroundColor: theme.palette.primary.
|
|
71
|
+
backgroundColor: theme.palette.primary.main,
|
|
71
72
|
},
|
|
72
73
|
},
|
|
73
74
|
},
|
|
74
|
-
|
|
75
|
+
...(props.autoWidth
|
|
76
|
+
? {
|
|
77
|
+
minWidth: `auto !important`,
|
|
78
|
+
width: `auto !important`,
|
|
79
|
+
}
|
|
80
|
+
: {}),
|
|
81
|
+
}),
|
|
75
82
|
label: {
|
|
76
83
|
fontSize: theme.typography.fontSize,
|
|
77
84
|
color: theme.palette.grey.dark,
|
|
@@ -104,6 +111,10 @@ const useStyles = makeStyles(theme => ({
|
|
|
104
111
|
backgroundColor: theme.palette.grey.light,
|
|
105
112
|
border: 0,
|
|
106
113
|
},
|
|
114
|
+
formControl: props => ({
|
|
115
|
+
maxWidth: theme.spacing(props.multipleWidthSpacing),
|
|
116
|
+
minWidth: theme.spacing(props.multipleWidthSpacing),
|
|
117
|
+
}),
|
|
107
118
|
}));
|
|
108
119
|
|
|
109
120
|
const MenuProps = {
|
|
@@ -145,11 +156,16 @@ export const SelectIconButton = props => {
|
|
|
145
156
|
);
|
|
146
157
|
};
|
|
147
158
|
|
|
148
|
-
const renderMultipleValues =
|
|
159
|
+
export const renderMultipleValues = (value, options) => {
|
|
160
|
+
return options
|
|
161
|
+
.filter(x => value.indexOf(x.value) !== -1)
|
|
162
|
+
.map(x => x.label)
|
|
163
|
+
.join(", ");
|
|
164
|
+
};
|
|
149
165
|
|
|
150
166
|
const selectEmptyValue = "~~#~~";
|
|
151
167
|
|
|
152
|
-
const Select = ({ options, selectProps, children }) => {
|
|
168
|
+
const Select = ({ options = [], selectProps, children }) => {
|
|
153
169
|
if (isSelectProps(selectProps) === false) {
|
|
154
170
|
throw new TypeError("selectProps property is not of type SelectProps");
|
|
155
171
|
}
|
|
@@ -157,8 +173,6 @@ const Select = ({ options, selectProps, children }) => {
|
|
|
157
173
|
const [open, setOpen] = useState(false);
|
|
158
174
|
const ref = useRef(null);
|
|
159
175
|
|
|
160
|
-
const classes = useStyles();
|
|
161
|
-
|
|
162
176
|
const update = selectProps?.get(SelectProps.propNames.update);
|
|
163
177
|
const value = selectProps?.get(SelectProps.propNames.value) ?? "";
|
|
164
178
|
const sortType = selectProps?.get(SelectProps.propNames.sortType) || sortTypeEnum.none;
|
|
@@ -171,36 +185,86 @@ const Select = ({ options, selectProps, children }) => {
|
|
|
171
185
|
const native = selectProps?.get(SelectProps.propNames.native);
|
|
172
186
|
const onClose = selectProps?.get(SelectProps.propNames.onClose);
|
|
173
187
|
const inputProps = selectProps?.get(SelectProps.propNames.inputProps);
|
|
174
|
-
const multiple = selectProps?.get(SelectProps.propNames.multiple);
|
|
188
|
+
const multiple = selectProps?.get(SelectProps.propNames.multiple) || false;
|
|
189
|
+
const renderValue = selectProps?.get(SelectProps.propNames.renderValue);
|
|
190
|
+
const autoWidth = selectProps?.get(SelectProps.propNames.autoWidth);
|
|
191
|
+
const autoFocus = selectProps?.get(SelectProps.propNames.autoFocus);
|
|
192
|
+
const multipleSelectWidth = selectProps?.get(SelectProps.propNames.multipleSelectWidth);
|
|
175
193
|
const hasError = !!error;
|
|
176
194
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
195
|
+
const windowSize = useWindowSize();
|
|
196
|
+
|
|
197
|
+
// When too many elements are selected from the list, the component can be longer than the screen, not very convenient
|
|
198
|
+
// We need a fix length unfortunately, for large screen, we use 100% of the multipleSelectWidth, for medium length, 75%
|
|
199
|
+
// But for very small width, we use the inner width of the browser minus 150px (completely arbitrary value), otherwise
|
|
200
|
+
// the drop-down is too large and hard to read
|
|
201
|
+
const multipleSelectWidthFactor = windowSize.innerWidth > 1200 ? 1 : 0.75;
|
|
202
|
+
const multipleWidthSpacing =
|
|
203
|
+
windowSize.innerWidth > 750
|
|
204
|
+
? (multipleSelectWidth / 10) * multipleSelectWidthFactor
|
|
205
|
+
: (windowSize.innerWidth - 150) / 10;
|
|
206
|
+
const classes = useStyles({
|
|
207
|
+
multiple,
|
|
208
|
+
autoWidth,
|
|
209
|
+
multipleWidthSpacing,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const buildOptionsItems = () => {
|
|
213
|
+
const allOptions = [...options];
|
|
197
214
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
215
|
+
if (sortType === sortTypeEnum.numeric) {
|
|
216
|
+
allOptions.sort((a, b) =>
|
|
217
|
+
a.sortOrder.localeCompare(b.sortOrder, undefined, {
|
|
218
|
+
numeric: true,
|
|
219
|
+
sensitivity: "base",
|
|
220
|
+
}),
|
|
221
|
+
);
|
|
222
|
+
} else if (sortType === sortTypeEnum.default) {
|
|
223
|
+
allOptions.sort((a, b) => (a.sortOrder > b.sortOrder ? 1 : -1));
|
|
224
|
+
} else if (sortType === sortTypeEnum.alphabetical) {
|
|
225
|
+
allOptions.sort((a, b) => {
|
|
226
|
+
if (a.value === selectEmptyValue) {
|
|
227
|
+
return -1;
|
|
228
|
+
}
|
|
229
|
+
if (b.value === selectEmptyValue) {
|
|
230
|
+
return 1;
|
|
231
|
+
}
|
|
232
|
+
return a.label.localeCompare(b.label);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (showAllValue && showAllLabel) {
|
|
237
|
+
allOptions.unshift({
|
|
238
|
+
value: showAllValue,
|
|
239
|
+
label: showAllLabel,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return allOptions.map(option => {
|
|
244
|
+
const clss = option?.level ? classes["level" + option.level] : "";
|
|
245
|
+
const appliedClasses = classNames(classes.baseItem, clss);
|
|
246
|
+
const labelClss = classNames({
|
|
247
|
+
[classes.label]: true,
|
|
248
|
+
[classes.emptyLabel]: option.value === "" || option.value === selectEmptyValue,
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const disabled = !!option.disabled;
|
|
252
|
+
const groupHeader = !!option.isGroupHeader;
|
|
253
|
+
if (groupHeader) {
|
|
254
|
+
return (
|
|
255
|
+
<ListSubheader key={option.value} className={appliedClasses}>
|
|
256
|
+
{option.label}
|
|
257
|
+
</ListSubheader>
|
|
258
|
+
);
|
|
259
|
+
} else {
|
|
260
|
+
return (
|
|
261
|
+
<MenuItem key={option.value} value={option.value} className={appliedClasses} disabled={disabled}>
|
|
262
|
+
<TooltippedTypography noWrap className={labelClss} children={option.label} titleValue={option.label} />
|
|
263
|
+
</MenuItem>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
202
266
|
});
|
|
203
|
-
}
|
|
267
|
+
};
|
|
204
268
|
|
|
205
269
|
const handleChange = event => {
|
|
206
270
|
update(event.target.value);
|
|
@@ -208,102 +272,85 @@ const Select = ({ options, selectProps, children }) => {
|
|
|
208
272
|
|
|
209
273
|
const defaultMenuProps = {
|
|
210
274
|
classes: { paper: classNames(classes.selectPaper, selectProps?.getStyle(SelectProps.ruleNames.paper)) },
|
|
275
|
+
autoFocus,
|
|
211
276
|
...MenuProps,
|
|
212
277
|
...positionOverride,
|
|
213
278
|
};
|
|
214
279
|
|
|
215
280
|
const iconSelectMenuProps = {
|
|
216
281
|
classes: { paper: classNames(classes.selectPaper, selectProps?.getStyle(SelectProps.ruleNames.paper)) },
|
|
282
|
+
autoFocus,
|
|
217
283
|
...positionOverride,
|
|
218
284
|
...getIconButtonMenuProps(ref.current),
|
|
219
285
|
};
|
|
220
286
|
|
|
221
|
-
const items =
|
|
222
|
-
let clss = option?.level ? classes["level" + option.level] : "";
|
|
223
|
-
const appliedClasses = classNames(classes.baseItem, clss);
|
|
224
|
-
const labelClss = classNames({
|
|
225
|
-
[classes.label]: true,
|
|
226
|
-
[classes.emptyLabel]: option.value === "" || option.value === selectEmptyValue,
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
const disabled = !!option.disabled;
|
|
230
|
-
const groupHeader = !!option.isGroupHeader;
|
|
231
|
-
if (groupHeader) {
|
|
232
|
-
return (
|
|
233
|
-
<ListSubheader key={option.value} className={appliedClasses}>
|
|
234
|
-
{option.label}
|
|
235
|
-
</ListSubheader>
|
|
236
|
-
);
|
|
237
|
-
} else {
|
|
238
|
-
return (
|
|
239
|
-
<MenuItem key={option.value} value={option.value} className={appliedClasses} disabled={disabled}>
|
|
240
|
-
<TooltippedTypography noWrap className={labelClss} children={option.label} titleValue={option.label} />
|
|
241
|
-
</MenuItem>
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
});
|
|
287
|
+
const items = native ? null : buildOptionsItems();
|
|
245
288
|
|
|
246
|
-
const
|
|
289
|
+
const iconSelect = isIconSelect && (
|
|
247
290
|
<SelectMUI
|
|
291
|
+
open={open}
|
|
248
292
|
value={value}
|
|
293
|
+
ref={ref}
|
|
249
294
|
onChange={handleChange}
|
|
250
|
-
onClose={onClose}
|
|
251
295
|
disableUnderline={true}
|
|
252
|
-
IconComponent={
|
|
253
|
-
MenuProps={
|
|
296
|
+
IconComponent={SelectIconButton}
|
|
297
|
+
MenuProps={iconSelectMenuProps}
|
|
254
298
|
disabled={disabled}
|
|
255
299
|
error={hasError}
|
|
256
300
|
native={native}
|
|
257
301
|
inputProps={inputProps}
|
|
258
302
|
multiple={multiple}
|
|
259
|
-
renderValue={multiple ? renderMultipleValues : undefined}
|
|
260
303
|
classes={{
|
|
261
304
|
icon: classes.icon,
|
|
262
305
|
root: selectProps?.getStyle(SelectProps.ruleNames.root),
|
|
306
|
+
select: classes.displayNone,
|
|
263
307
|
disabled: classes.disabled,
|
|
264
308
|
}}
|
|
309
|
+
onClick={() => setOpen(!open)}
|
|
265
310
|
>
|
|
266
|
-
{
|
|
311
|
+
{items ?? children}
|
|
267
312
|
</SelectMUI>
|
|
268
313
|
);
|
|
269
314
|
|
|
270
|
-
|
|
315
|
+
// Render the normal select is the icon one is NULL
|
|
316
|
+
const selectToRender = iconSelect || (
|
|
271
317
|
<SelectMUI
|
|
272
|
-
open={open}
|
|
273
318
|
value={value}
|
|
274
|
-
ref={ref}
|
|
275
319
|
onChange={handleChange}
|
|
320
|
+
onClose={onClose}
|
|
276
321
|
disableUnderline={true}
|
|
277
|
-
IconComponent={
|
|
278
|
-
|
|
322
|
+
IconComponent={SelectIcon}
|
|
323
|
+
autoWidth={autoWidth}
|
|
324
|
+
MenuProps={defaultMenuProps}
|
|
279
325
|
disabled={disabled}
|
|
280
326
|
error={hasError}
|
|
281
327
|
native={native}
|
|
282
328
|
inputProps={inputProps}
|
|
283
329
|
multiple={multiple}
|
|
284
|
-
renderValue={multiple ? renderMultipleValues : undefined}
|
|
330
|
+
renderValue={renderValue ?? (multiple ? value => renderMultipleValues(value, options) : undefined)}
|
|
285
331
|
classes={{
|
|
286
332
|
icon: classes.icon,
|
|
287
333
|
root: selectProps?.getStyle(SelectProps.ruleNames.root),
|
|
288
|
-
select: classes.displayNone,
|
|
289
334
|
disabled: classes.disabled,
|
|
290
335
|
}}
|
|
291
|
-
onClick={() => setOpen(!open)}
|
|
292
336
|
>
|
|
293
|
-
{
|
|
337
|
+
{items ?? children}
|
|
294
338
|
</SelectMUI>
|
|
295
339
|
);
|
|
296
340
|
|
|
297
|
-
const
|
|
341
|
+
const selectToRenderWithError = hasError && (
|
|
342
|
+
<div className={classes.container}>
|
|
343
|
+
{selectToRender}
|
|
344
|
+
<div className={classNames(classes.errorText)}>{error}</div>
|
|
345
|
+
</div>
|
|
346
|
+
);
|
|
298
347
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
)) ||
|
|
306
|
-
select
|
|
348
|
+
const selectControl = selectToRenderWithError || selectToRender;
|
|
349
|
+
|
|
350
|
+
return multiple === false ? (
|
|
351
|
+
selectControl
|
|
352
|
+
) : (
|
|
353
|
+
<FormControl className={classes.formControl}>{selectControl}</FormControl>
|
|
307
354
|
);
|
|
308
355
|
};
|
|
309
356
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { mount } from "enzyme";
|
|
3
|
-
import Select, { SelectIconButton } from "./Select";
|
|
3
|
+
import Select, { renderMultipleValues, SelectIconButton } from "./Select";
|
|
4
4
|
import SelectMUI from "@material-ui/core/Select";
|
|
5
5
|
import sinon from "sinon";
|
|
6
6
|
import { ignoreConsoleError, createMuiTheme, TestWrapper } from "../../../utils/testUtils";
|
|
@@ -9,6 +9,7 @@ import TooltippedTypography from "./../DataDisplay/TooltippedElements/Tooltipped
|
|
|
9
9
|
import { ListSubheader, MuiThemeProvider } from "@material-ui/core";
|
|
10
10
|
import MenuItem from "@material-ui/core/MenuItem";
|
|
11
11
|
import Icon from "./../DataDisplay/Icon";
|
|
12
|
+
import FormControl from "@material-ui/core/FormControl";
|
|
12
13
|
|
|
13
14
|
describe("Select Component", () => {
|
|
14
15
|
let update, container;
|
|
@@ -75,13 +76,14 @@ describe("Select Component", () => {
|
|
|
75
76
|
expect(component, "when mounted", "to satisfy", expected);
|
|
76
77
|
});
|
|
77
78
|
|
|
78
|
-
it("Renders Select component with
|
|
79
|
+
it("Renders Select component without errors with a larger width", () => {
|
|
79
80
|
const options = [
|
|
80
|
-
{ value: "aValue", label: "aLabel"
|
|
81
|
-
{ value: "anotherValue", label: "anotherLabel"
|
|
82
|
-
{ value: "aThirdValue", label: "aThirdLabel", level: 2 },
|
|
81
|
+
{ value: "aValue", label: "aLabel" },
|
|
82
|
+
{ value: "anotherValue", label: "anotherLabel" },
|
|
83
83
|
];
|
|
84
84
|
|
|
85
|
+
Object.defineProperty(window, "innerWidth", { configurable: true, value: 1800 });
|
|
86
|
+
|
|
85
87
|
const selectProps = new SelectProps();
|
|
86
88
|
|
|
87
89
|
selectProps.set(SelectProps.propNames.update, update);
|
|
@@ -103,12 +105,49 @@ describe("Select Component", () => {
|
|
|
103
105
|
<MenuItem key="aValue" value="aValue">
|
|
104
106
|
<TooltippedTypography children="aLabel" titleValue="aLabel" />
|
|
105
107
|
</MenuItem>
|
|
106
|
-
<MenuItem key="anotherValue" value="anotherValue"
|
|
108
|
+
<MenuItem key="anotherValue" value="anotherValue">
|
|
107
109
|
<TooltippedTypography noWrap children="anotherLabel" titleValue="anotherLabel" />
|
|
108
110
|
</MenuItem>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
111
|
+
</SelectMUI>
|
|
112
|
+
</TestWrapper>
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
expect(component, "when mounted", "to satisfy", expected);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("Renders Select component using native mode", () => {
|
|
119
|
+
const options = [
|
|
120
|
+
{ value: "aValue", label: "aLabel", level: 0 },
|
|
121
|
+
{ value: "anotherValue", label: "anotherLabel", level: 1 },
|
|
122
|
+
{ value: "aThirdValue", label: "aThirdLabel", level: 2 },
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
const selectProps = new SelectProps();
|
|
126
|
+
|
|
127
|
+
selectProps.set(SelectProps.propNames.update, update);
|
|
128
|
+
selectProps.set(SelectProps.propNames.native, true);
|
|
129
|
+
selectProps.set(SelectProps.propNames.value, "aValue");
|
|
130
|
+
|
|
131
|
+
const component = (
|
|
132
|
+
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
133
|
+
<Select options={options} selectProps={selectProps}>
|
|
134
|
+
<div>French Fries</div>
|
|
135
|
+
<div>Smashed Potatoes</div>
|
|
136
|
+
<div>Fried Green Tomatoes</div>
|
|
137
|
+
</Select>
|
|
138
|
+
</TestWrapper>
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
const ChevronDown = props => {
|
|
142
|
+
return <Icon id="dropdown-chevron-down" {...props} />;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const expected = (
|
|
146
|
+
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
147
|
+
<SelectMUI native value="aValue" disableUnderline={true} IconComponent={ChevronDown} error={false}>
|
|
148
|
+
<div>French Fries</div>
|
|
149
|
+
<div>Smashed Potatoes</div>
|
|
150
|
+
<div>Fried Green Tomatoes</div>
|
|
112
151
|
</SelectMUI>
|
|
113
152
|
</TestWrapper>
|
|
114
153
|
);
|
|
@@ -262,8 +301,8 @@ describe("Select Component", () => {
|
|
|
262
301
|
};
|
|
263
302
|
|
|
264
303
|
const expected = (
|
|
265
|
-
<
|
|
266
|
-
<
|
|
304
|
+
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
305
|
+
<div>
|
|
267
306
|
<SelectMUI value="aValue" disableUnderline={true} IconComponent={ChevronDown} error={true}>
|
|
268
307
|
<MenuItem key="aValue" value="aValue">
|
|
269
308
|
<TooltippedTypography children="aLabel" titleValue="aLabel" />
|
|
@@ -272,9 +311,9 @@ describe("Select Component", () => {
|
|
|
272
311
|
<TooltippedTypography noWrap children="anotherLabel" titleValue="anotherLabel" />
|
|
273
312
|
</MenuItem>
|
|
274
313
|
</SelectMUI>
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
</
|
|
314
|
+
<div>an error message</div>
|
|
315
|
+
</div>
|
|
316
|
+
</TestWrapper>
|
|
278
317
|
);
|
|
279
318
|
|
|
280
319
|
expect(component, "when mounted", "to satisfy", expected);
|
|
@@ -637,6 +676,51 @@ describe("Select Component", () => {
|
|
|
637
676
|
expect(component, "when mounted", "to satisfy", expected);
|
|
638
677
|
});
|
|
639
678
|
|
|
679
|
+
it("Renders Icon Select component correctly using native mode", () => {
|
|
680
|
+
const options = [
|
|
681
|
+
{ value: "aValue", label: "aLabel" },
|
|
682
|
+
{ value: "anotherValue", label: "anotherLabel" },
|
|
683
|
+
];
|
|
684
|
+
|
|
685
|
+
const selectProps = new SelectProps();
|
|
686
|
+
|
|
687
|
+
selectProps.set(SelectProps.propNames.update, update);
|
|
688
|
+
selectProps.set(SelectProps.propNames.value, "aValue");
|
|
689
|
+
selectProps.set(SelectProps.propNames.iconSelect, true);
|
|
690
|
+
selectProps.set(SelectProps.propNames.native, true);
|
|
691
|
+
|
|
692
|
+
const theme = createMuiTheme();
|
|
693
|
+
|
|
694
|
+
const component = (
|
|
695
|
+
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
696
|
+
<Select options={options} selectProps={selectProps}>
|
|
697
|
+
<div>French Fries</div>
|
|
698
|
+
<div>Smashed Potatoes</div>
|
|
699
|
+
<div>Fried Green Tomatoes</div>
|
|
700
|
+
</Select>
|
|
701
|
+
</TestWrapper>
|
|
702
|
+
);
|
|
703
|
+
|
|
704
|
+
const expected = (
|
|
705
|
+
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
706
|
+
<SelectMUI
|
|
707
|
+
native
|
|
708
|
+
open={false}
|
|
709
|
+
value="aValue"
|
|
710
|
+
disableUnderline={true}
|
|
711
|
+
IconComponent={SelectIconButton}
|
|
712
|
+
error={false}
|
|
713
|
+
>
|
|
714
|
+
<div>French Fries</div>
|
|
715
|
+
<div>Smashed Potatoes</div>
|
|
716
|
+
<div>Fried Green Tomatoes</div>
|
|
717
|
+
</SelectMUI>
|
|
718
|
+
</TestWrapper>
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
expect(component, "when mounted", "to satisfy", expected);
|
|
722
|
+
});
|
|
723
|
+
|
|
640
724
|
it("Changes Icon Select open state on click", () => {
|
|
641
725
|
const options = [
|
|
642
726
|
{ value: "aValue", label: "aLabel" },
|
|
@@ -674,13 +758,14 @@ describe("Select Component", () => {
|
|
|
674
758
|
const options = [
|
|
675
759
|
{ value: "aValue", label: "aLabel" },
|
|
676
760
|
{ value: "anotherValue", label: "anotherLabel" },
|
|
761
|
+
{ value: "thirdValue", label: "thirdLabel" },
|
|
677
762
|
];
|
|
678
763
|
|
|
679
764
|
const selectProps = new SelectProps();
|
|
680
765
|
|
|
681
766
|
selectProps.set(SelectProps.propNames.update, update);
|
|
682
767
|
selectProps.set(SelectProps.propNames.multiple, true);
|
|
683
|
-
selectProps.set(SelectProps.propNames.value, ["aValue"]);
|
|
768
|
+
selectProps.set(SelectProps.propNames.value, ["aValue", "thirdValue"]);
|
|
684
769
|
|
|
685
770
|
const component = (
|
|
686
771
|
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
@@ -694,21 +779,76 @@ describe("Select Component", () => {
|
|
|
694
779
|
|
|
695
780
|
const expected = (
|
|
696
781
|
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
697
|
-
<
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
<
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
<
|
|
710
|
-
|
|
711
|
-
|
|
782
|
+
<FormControl>
|
|
783
|
+
<SelectMUI
|
|
784
|
+
value={["aValue", "thirdValue"]}
|
|
785
|
+
disableUnderline={true}
|
|
786
|
+
IconComponent={ChevronDown}
|
|
787
|
+
error={false}
|
|
788
|
+
multiple={true}
|
|
789
|
+
renderValue={value => renderMultipleValues(value, options)}
|
|
790
|
+
>
|
|
791
|
+
<MenuItem key="aValue" value="aValue">
|
|
792
|
+
<TooltippedTypography children="aLabel" titleValue="aLabel" />
|
|
793
|
+
</MenuItem>
|
|
794
|
+
<MenuItem key="anotherValue" value="anotherValue">
|
|
795
|
+
<TooltippedTypography noWrap children="anotherLabel" titleValue="anotherLabel" />
|
|
796
|
+
</MenuItem>
|
|
797
|
+
</SelectMUI>
|
|
798
|
+
</FormControl>
|
|
799
|
+
</TestWrapper>
|
|
800
|
+
);
|
|
801
|
+
|
|
802
|
+
expect(component, "when mounted", "to satisfy", expected);
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
it("Renders Icon Select component correctly using multiple mode and render value", () => {
|
|
806
|
+
const options = [
|
|
807
|
+
{ value: "aValue", label: "aLabel" },
|
|
808
|
+
{ value: "anotherValue", label: "anotherLabel" },
|
|
809
|
+
{ value: "thirdValue", label: "thirdLabel" },
|
|
810
|
+
];
|
|
811
|
+
|
|
812
|
+
const selectProps = new SelectProps();
|
|
813
|
+
|
|
814
|
+
const renderValues = values => values.join("#,#");
|
|
815
|
+
|
|
816
|
+
selectProps.set(SelectProps.propNames.update, update);
|
|
817
|
+
selectProps.set(SelectProps.propNames.multiple, true);
|
|
818
|
+
selectProps.set(SelectProps.propNames.value, ["aValue", "thirdValue"]);
|
|
819
|
+
selectProps.set(SelectProps.propNames.renderValue, renderValues);
|
|
820
|
+
|
|
821
|
+
const theme = createMuiTheme();
|
|
822
|
+
|
|
823
|
+
const component = (
|
|
824
|
+
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
825
|
+
<Select options={options} selectProps={selectProps} />
|
|
826
|
+
</TestWrapper>
|
|
827
|
+
);
|
|
828
|
+
|
|
829
|
+
const ChevronDown = props => {
|
|
830
|
+
return <Icon id="dropdown-chevron-down" {...props} />;
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
const expected = (
|
|
834
|
+
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
835
|
+
<FormControl>
|
|
836
|
+
<SelectMUI
|
|
837
|
+
value={["aValue", "thirdValue"]}
|
|
838
|
+
disableUnderline={true}
|
|
839
|
+
IconComponent={ChevronDown}
|
|
840
|
+
error={false}
|
|
841
|
+
multiple={true}
|
|
842
|
+
renderValue={renderValues}
|
|
843
|
+
>
|
|
844
|
+
<MenuItem key="aValue" value="aValue">
|
|
845
|
+
<TooltippedTypography children="aLabel" titleValue="aLabel" />
|
|
846
|
+
</MenuItem>
|
|
847
|
+
<MenuItem key="anotherValue" value="anotherValue">
|
|
848
|
+
<TooltippedTypography noWrap children="anotherLabel" titleValue="anotherLabel" />
|
|
849
|
+
</MenuItem>
|
|
850
|
+
</SelectMUI>
|
|
851
|
+
</FormControl>
|
|
712
852
|
</TestWrapper>
|
|
713
853
|
);
|
|
714
854
|
|
|
@@ -22,6 +22,10 @@ class SelectProps extends ComponentProps {
|
|
|
22
22
|
native: "native",
|
|
23
23
|
inputProps: "inputProps",
|
|
24
24
|
multiple: "multiple",
|
|
25
|
+
autoWidth: "autoWidth",
|
|
26
|
+
autoFocus: "autoFocus",
|
|
27
|
+
renderValue: "renderValue",
|
|
28
|
+
multipleSelectWidth: "multipleSelectWidth",
|
|
25
29
|
};
|
|
26
30
|
|
|
27
31
|
static ruleNames = {
|
|
@@ -43,7 +47,11 @@ class SelectProps extends ComponentProps {
|
|
|
43
47
|
this.componentProps.set(this.constructor.propNames.onClose, null);
|
|
44
48
|
this.componentProps.set(this.constructor.propNames.native, null);
|
|
45
49
|
this.componentProps.set(this.constructor.propNames.inputProps, null);
|
|
46
|
-
this.componentProps.set(this.constructor.propNames.multiple,
|
|
50
|
+
this.componentProps.set(this.constructor.propNames.multiple, false);
|
|
51
|
+
this.componentProps.set(this.constructor.propNames.autoWidth, true);
|
|
52
|
+
this.componentProps.set(this.constructor.propNames.autoFocus, true);
|
|
53
|
+
this.componentProps.set(this.constructor.propNames.renderValue, null);
|
|
54
|
+
this.componentProps.set(this.constructor.propNames.multipleSelectWidth, 700);
|
|
47
55
|
|
|
48
56
|
this.componentClasses.set(this.constructor.ruleNames.root, null);
|
|
49
57
|
this.componentClasses.set(this.constructor.ruleNames.paper, null);
|
|
@@ -16,6 +16,10 @@ describe("Select Props", () => {
|
|
|
16
16
|
"native",
|
|
17
17
|
"inputProps",
|
|
18
18
|
"multiple",
|
|
19
|
+
"autoWidth",
|
|
20
|
+
"autoFocus",
|
|
21
|
+
"renderValue",
|
|
22
|
+
"multipleSelectWidth",
|
|
19
23
|
];
|
|
20
24
|
|
|
21
25
|
expect(SelectProps.propNames, "to have keys", propNames);
|
|
@@ -36,6 +40,10 @@ describe("Select Props", () => {
|
|
|
36
40
|
"native",
|
|
37
41
|
"inputProps",
|
|
38
42
|
"multiple",
|
|
43
|
+
"autoWidth",
|
|
44
|
+
"autoFocus",
|
|
45
|
+
"renderValue",
|
|
46
|
+
"multipleSelectWidth",
|
|
39
47
|
];
|
|
40
48
|
|
|
41
49
|
const selectProps = new SelectProps();
|
|
@@ -15,16 +15,10 @@ const withScrollBox = WrappedComp =>
|
|
|
15
15
|
React.forwardRef(({ onScroll, ...otherProps }, externalRef) => {
|
|
16
16
|
const classes = useStyles();
|
|
17
17
|
|
|
18
|
-
const mergeRef = (node, measureRef) => {
|
|
19
|
-
measureRef(node);
|
|
20
|
-
|
|
21
|
-
if (externalRef) externalRef.current = node;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
18
|
return (
|
|
25
|
-
<Measure bounds>
|
|
19
|
+
<Measure bounds innerRef={externalRef}>
|
|
26
20
|
{({ measureRef, contentRect }) => (
|
|
27
|
-
<div className={classes.scrollbox} onScroll={onScroll} ref={
|
|
21
|
+
<div className={classes.scrollbox} onScroll={onScroll} ref={measureRef}>
|
|
28
22
|
<WrappedComp
|
|
29
23
|
{...otherProps}
|
|
30
24
|
height={safeGet(contentRect, "bounds", "height")}
|