diff --git a/packages/manager/src/components/EnhancedSelect/Select.styles.ts b/packages/manager/src/components/EnhancedSelect/Select.styles.ts
index 36eddbd1c2a..3dc88dd5a7b 100644
--- a/packages/manager/src/components/EnhancedSelect/Select.styles.ts
+++ b/packages/manager/src/components/EnhancedSelect/Select.styles.ts
@@ -1,345 +1,318 @@
-import { createStyles } from '@mui/styles';
+import { makeStyles } from '@mui/styles';
import { Theme } from '@mui/material/styles';
-export type ClassNames =
- | 'root'
- | 'input'
- | 'noOptionsMessage'
- | 'divider'
- | 'suggestionRoot'
- | 'highlight'
- | 'suggestionItem'
- | 'suggestionIcon'
- | 'suggestionTitle'
- | 'suggestionDescription'
- | 'resultContainer'
- | 'tagContainer'
- | 'selectedMenuItem'
- | 'medium'
- | 'small'
- | 'noMarginTop'
- | 'inline'
- | 'hideLabel'
- | 'algoliaRoot'
- | 'label'
- | 'source'
- | 'icon'
- | 'row'
- | 'finalLink';
-
-export const styles = (theme: Theme) =>
- createStyles({
- '@keyframes dash': {
- to: {
- 'stroke-dashoffset': 0,
- },
+export const useStyles = makeStyles((theme: Theme) => ({
+ '@keyframes dash': {
+ to: {
+ 'stroke-dashoffset': 0,
},
- root: {
- width: '100%',
- position: 'relative',
- '& .react-select__control': {
- borderRadius: 0,
- boxShadow: 'none',
- border: `1px solid transparent`,
- backgroundColor: theme.bg.white,
- minHeight: `calc(${theme.spacing(5)} - 2)`,
- '&:hover': {
- border: `1px dotted #ccc`,
- cursor: 'text',
- },
- '&--is-focused, &--is-focused:hover': {
- border: `1px dotted #999`,
- },
+ },
+ root: {
+ width: '100%',
+ position: 'relative',
+ '& .react-select__control': {
+ borderRadius: 0,
+ boxShadow: 'none',
+ border: `1px solid transparent`,
+ backgroundColor: theme.bg.white,
+ minHeight: `calc(${theme.spacing(5)} - 2)`,
+ '&:hover': {
+ border: `1px dotted #ccc`,
+ cursor: 'text',
},
- '& .react-select__value-container': {
- width: '100%',
- '& > div': {
- width: '100%',
- },
- '&.react-select__value-container--is-multi': {
- '& > div, & .react-select__input': {
- width: 'auto',
- },
- },
+ '&--is-focused, &--is-focused:hover': {
+ border: `1px dotted #999`,
},
- '& .react-select__input': {
+ },
+ '& .react-select__value-container': {
+ width: '100%',
+ '& > div': {
width: '100%',
- color: theme.palette.text.primary,
- },
- '& .react-select__menu': {
- margin: '-1px 0 0 0',
- borderRadius: 0,
- boxShadow: 'none',
- border: `1px solid ${theme.palette.primary.main}`,
- maxWidth: 415,
- zIndex: 100,
},
- '& .react-select__group': {
- width: '100%',
- '&:last-child': {
- paddingBottom: 0,
+ '&.react-select__value-container--is-multi': {
+ '& > div, & .react-select__input': {
+ width: 'auto',
},
},
- '& .react-select__group-heading': {
- textTransform: 'initial',
- fontSize: '1rem',
- color: theme.color.headline,
- fontFamily: theme.font.bold,
- paddingLeft: 10,
- paddingRight: 10,
- },
- '& .react-select__menu-list': {
- zIndex: 100,
- padding: theme.spacing(0.5),
- backgroundColor: theme.bg.white,
- height: '101%',
- overflow: 'auto',
- maxHeight: 285,
- '&::-webkit-scrollbar': {
- appearance: 'none',
- },
- '&::-webkit-scrollbar:vertical': {
- width: 8,
- },
- '&::-webkit-scrollbar-thumb': {
- borderRadius: 8,
- backgroundColor: '#ccc',
- },
- },
- '& .react-select__option': {
- transition: theme.transitions.create(['background-color', 'color']),
- color: theme.palette.text.primary,
- backgroundColor: theme.bg.white,
- cursor: 'pointer',
- padding: '10px',
- fontSize: '0.9rem',
- [theme.breakpoints.only('xs')]: {
- fontSize: '1rem',
- },
- '& svg': {
- marginTop: 2,
- },
- },
- '& .react-select__option--is-focused': {
- backgroundColor: theme.palette.primary.main,
- color: 'white',
- },
- '& .react-select__option--is-selected': {
- color: theme.palette.primary.main,
- '&.react-select__option--is-focused': {
- backgroundColor: theme.bg.white,
- },
- },
- '& .react-select__option--is-disabled': {
- opacity: 0.5,
- cursor: 'initial',
- },
- '& .react-select__single-value': {
- color: theme.palette.text.primary,
- overflow: 'hidden',
- },
- '& .react-select__indicator-separator': {
- display: 'none',
- },
- '& .react-select__multi-value': {
- borderRadius: 4,
- backgroundColor: theme.bg.lightBlue1,
- alignItems: 'center',
- },
- '& .react-select__multi-value__label': {
- color: theme.palette.text.primary,
- fontSize: '.8rem',
- height: 20,
- marginTop: 2,
- marginBottom: 2,
- marginRight: 4,
- paddingLeft: 6,
- paddingRight: 0,
+ },
+ '& .react-select__input': {
+ width: '100%',
+ color: theme.palette.text.primary,
+ },
+ '& .react-select__menu': {
+ margin: '-1px 0 0 0',
+ borderRadius: 0,
+ boxShadow: 'none',
+ border: `1px solid ${theme.palette.primary.main}`,
+ maxWidth: 415,
+ zIndex: 100,
+ },
+ '& .react-select__group': {
+ width: '100%',
+ '&:last-child': {
+ paddingBottom: 0,
},
- '& .react-select__clear-indicator': {
- padding: 0,
- '& svg': {
- color: theme.color.grey4,
- '&:hover': {
- color: theme.palette.primary.main,
- },
- },
+ },
+ '& .react-select__group-heading': {
+ textTransform: 'initial',
+ fontSize: '1rem',
+ color: theme.color.headline,
+ fontFamily: theme.font.bold,
+ paddingLeft: 10,
+ paddingRight: 10,
+ },
+ '& .react-select__menu-list': {
+ zIndex: 100,
+ padding: theme.spacing(0.5),
+ backgroundColor: theme.bg.white,
+ height: '101%',
+ overflow: 'auto',
+ maxHeight: 285,
+ '&::-webkit-scrollbar': {
+ appearance: 'none',
},
- '& .react-select__multi-value__remove': {
- backgroundColor: 'transparent',
- borderRadius: '50%',
- padding: 2,
- marginLeft: 4,
- marginRight: 4,
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'center',
- '& svg': {
- color: theme.palette.text.primary,
- width: 12,
- height: 12,
- },
- '&:hover': {
- backgroundColor: theme.palette.primary.main,
- '& svg': {
- color: 'white',
- },
- },
+ '&::-webkit-scrollbar:vertical': {
+ width: 8,
},
- '& .react-select__dropdown-indicator': {},
- '& [class*="MuiFormHelperText-error"]': {
- paddingBottom: theme.spacing(1),
+ '&::-webkit-scrollbar-thumb': {
+ borderRadius: 8,
+ backgroundColor: '#ccc',
},
},
- input: {
+ '& .react-select__option': {
+ transition: theme.transitions.create(['background-color', 'color']),
+ color: theme.palette.text.primary,
+ backgroundColor: theme.bg.white,
+ cursor: 'pointer',
+ padding: '10px',
fontSize: '0.9rem',
[theme.breakpoints.only('xs')]: {
fontSize: '1rem',
},
- padding: 0,
- display: 'flex',
- color: theme.palette.text.primary,
- cursor: 'pointer',
- minHeight: `calc(${theme.spacing(5)} - 6)`,
- // From the AutoSizeInput documentation: (https://github.com/JedWatson/react-input-autosize/blob/master/README.md#csp-and-the-ie-clear-indicator)
- // "The input will automatically inject a stylesheet that hides IE/Edge's "clear" indicator,
- // which otherwise breaks the UI. This has the downside of being incompatible with some CSP policies.
- // To work around this, you can pass the injectStyles={false} prop, but if you do this I strongly
- // recommend targeting the input element in your own stylesheet with the following rule:"
- '::-ms-clear': { display: 'none' },
- },
- noOptionsMessage: {
- padding: `${theme.spacing(1)} ${theme.spacing(2)}`,
+ '& svg': {
+ marginTop: 2,
+ },
},
- divider: {
- height: theme.spacing(2),
+ '& .react-select__option--is-focused': {
+ backgroundColor: theme.palette.primary.main,
+ color: 'white',
},
- suggestionRoot: {
- cursor: 'pointer',
- width: 'calc(100% + 2px)',
- alignItems: 'space-between',
- justifyContent: 'space-between',
- borderBottom: `1px solid ${theme.palette.divider}`,
- [theme.breakpoints.up('md')]: {
- display: 'flex',
- },
- '&:last-child': {
- borderBottom: 0,
+ '& .react-select__option--is-selected': {
+ color: theme.palette.primary.main,
+ '&.react-select__option--is-focused': {
+ backgroundColor: theme.bg.white,
},
},
- highlight: {
- color: theme.palette.primary.main,
+ '& .react-select__option--is-disabled': {
+ opacity: 0.5,
+ cursor: 'initial',
},
- suggestionItem: {
- padding: theme.spacing(),
+ '& .react-select__single-value': {
+ color: theme.palette.text.primary,
+ overflow: 'hidden',
},
- suggestionIcon: {
- display: 'flex',
+ '& .react-select__indicator-separator': {
+ display: 'none',
+ },
+ '& .react-select__multi-value': {
+ borderRadius: 4,
+ backgroundColor: theme.bg.lightBlue1,
alignItems: 'center',
- justifyContent: 'center',
- marginLeft: theme.spacing(1.5),
},
- suggestionTitle: {
- fontSize: '1rem',
+ '& .react-select__multi-value__label': {
color: theme.palette.text.primary,
- wordBreak: 'break-all',
- fontWeight: 600,
- },
- suggestionDescription: {
- color: theme.color.headline,
- fontSize: '.75rem',
+ fontSize: '.8rem',
+ height: 20,
marginTop: 2,
+ marginBottom: 2,
+ marginRight: 4,
+ paddingLeft: 6,
+ paddingRight: 0,
},
- resultContainer: {
- display: 'flex',
- flexFlow: 'row nowrap',
+ '& .react-select__clear-indicator': {
+ padding: 0,
+ '& svg': {
+ color: theme.color.grey4,
+ '&:hover': {
+ color: theme.palette.primary.main,
+ },
+ },
},
- tagContainer: {
+ '& .react-select__multi-value__remove': {
+ backgroundColor: 'transparent',
+ borderRadius: '50%',
+ padding: 2,
+ marginLeft: 4,
+ marginRight: 4,
display: 'flex',
- flexWrap: 'wrap',
- paddingRight: 8,
- justifyContent: 'flex-end',
alignItems: 'center',
- '& > div': {
- margin: '2px',
- },
- },
- selectedMenuItem: {
- backgroundColor: `${theme.bg.main} !important`,
- '& .tag': {
- backgroundColor: theme.bg.lightBlue1,
+ justifyContent: 'center',
+ '& svg': {
color: theme.palette.text.primary,
- '&:hover': {
- backgroundColor: theme.palette.primary.main,
+ width: 12,
+ height: 12,
+ },
+ '&:hover': {
+ backgroundColor: theme.palette.primary.main,
+ '& svg': {
color: 'white',
},
},
},
- medium: {
- minHeight: 40,
+ '& .react-select__dropdown-indicator': {},
+ '& [class*="MuiFormHelperText-error"]': {
+ paddingBottom: theme.spacing(1),
},
- small: {
- minHeight: 35,
- minWidth: 'auto',
+ },
+ input: {
+ fontSize: '0.9rem',
+ [theme.breakpoints.only('xs')]: {
+ fontSize: '1rem',
},
- inline: {
- display: 'inline-flex',
- flexDirection: 'row',
- alignItems: 'center',
- '& label': {
- marginRight: theme.spacing(1),
- whiteSpace: 'nowrap',
- position: 'relative',
- top: 1,
- },
+ padding: 0,
+ display: 'flex',
+ color: theme.palette.text.primary,
+ cursor: 'pointer',
+ minHeight: `calc(${theme.spacing(5)} - 6)`,
+ // From the AutoSizeInput documentation: (https://github.com/JedWatson/react-input-autosize/blob/master/README.md#csp-and-the-ie-clear-indicator)
+ // "The input will automatically inject a stylesheet that hides IE/Edge's "clear" indicator,
+ // which otherwise breaks the UI. This has the downside of being incompatible with some CSP policies.
+ // To work around this, you can pass the injectStyles={false} prop, but if you do this I strongly
+ // recommend targeting the input element in your own stylesheet with the following rule:"
+ '::-ms-clear': { display: 'none' },
+ },
+ noOptionsMessage: {
+ padding: `${theme.spacing(1)} ${theme.spacing(2)}`,
+ },
+ divider: {
+ height: theme.spacing(2),
+ },
+ suggestionRoot: {
+ cursor: 'pointer',
+ width: 'calc(100% + 2px)',
+ alignItems: 'space-between',
+ justifyContent: 'space-between',
+ borderBottom: `1px solid ${theme.palette.divider}`,
+ [theme.breakpoints.up('md')]: {
+ display: 'flex',
},
- hideLabel: {
- '& label': { ...theme.visually.hidden },
+ '&:last-child': {
+ borderBottom: 0,
},
- algoliaRoot: {
- width: '100%',
- cursor: 'pointer',
- padding: `calc(${theme.spacing(1)} / 2 + 2)`,
- '& em': {
- fontStyle: 'normal',
- color: theme.color.blueDTwhite,
- },
+ },
+ highlight: {
+ color: theme.palette.primary.main,
+ },
+ suggestionItem: {
+ padding: theme.spacing(),
+ },
+ suggestionIcon: {
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginLeft: theme.spacing(1.5),
+ },
+ suggestionTitle: {
+ fontSize: '1rem',
+ color: theme.palette.text.primary,
+ wordBreak: 'break-all',
+ fontWeight: 600,
+ },
+ suggestionDescription: {
+ color: theme.color.headline,
+ fontSize: '.75rem',
+ marginTop: 2,
+ },
+ resultContainer: {
+ display: 'flex',
+ flexFlow: 'row nowrap',
+ },
+ tagContainer: {
+ display: 'flex',
+ flexWrap: 'wrap',
+ paddingRight: 8,
+ justifyContent: 'flex-end',
+ alignItems: 'center',
+ '& > div': {
+ margin: '2px',
},
- label: {
- display: 'inline',
+ },
+ selectedMenuItem: {
+ backgroundColor: `${theme.bg.main} !important`,
+ '& .tag': {
+ backgroundColor: theme.bg.lightBlue1,
color: theme.palette.text.primary,
- maxWidth: '95%',
+ '&:hover': {
+ backgroundColor: theme.palette.primary.main,
+ color: 'white',
+ },
},
- icon: {
- display: 'inline-block',
- width: 12,
- height: 12,
+ },
+ medium: {
+ minHeight: 40,
+ },
+ small: {
+ minHeight: 35,
+ minWidth: 'auto',
+ },
+ inline: {
+ display: 'inline-flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+ '& label': {
+ marginRight: theme.spacing(1),
+ whiteSpace: 'nowrap',
position: 'relative',
- top: 5,
- marginLeft: theme.spacing(0.5),
- marginRight: theme.spacing(0.5),
- color: theme.palette.primary.main,
- },
- source: {
- marginTop: `calc(${theme.spacing(1)} / 4)`,
- color: theme.color.headline,
- paddingLeft: theme.spacing(1),
- margin: 0,
- },
- row: {
- display: 'flex',
- width: '100%',
- alignItems: 'center',
- justifyContent: 'space-between',
- paddingLeft: theme.spacing(1),
+ top: 1,
},
- finalLink: {
- display: 'flex',
- alignItems: 'center',
- fontSize: '1.2em',
- paddingLeft: theme.spacing(1),
+ },
+ hideLabel: {
+ '& label': { ...theme.visually.hidden },
+ },
+ algoliaRoot: {
+ width: '100%',
+ cursor: 'pointer',
+ padding: `calc(${theme.spacing(1)} / 2 + 2)`,
+ '& em': {
+ fontStyle: 'normal',
+ color: theme.color.blueDTwhite,
},
- });
+ },
+ label: {
+ display: 'inline',
+ color: theme.palette.text.primary,
+ maxWidth: '95%',
+ },
+ icon: {
+ display: 'inline-block',
+ width: 12,
+ height: 12,
+ position: 'relative',
+ top: 5,
+ marginLeft: theme.spacing(0.5),
+ marginRight: theme.spacing(0.5),
+ color: theme.palette.primary.main,
+ },
+ source: {
+ marginTop: `calc(${theme.spacing(1)} / 4)`,
+ color: theme.color.headline,
+ paddingLeft: theme.spacing(1),
+ margin: 0,
+ },
+ row: {
+ display: 'flex',
+ width: '100%',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ paddingLeft: theme.spacing(1),
+ },
+ finalLink: {
+ display: 'flex',
+ alignItems: 'center',
+ fontSize: '1.2em',
+ paddingLeft: theme.spacing(1),
+ },
+}));
// @todo @tdt: Replace the class name based styles above with these. They're (mostly) copied over,
// as they're needed for one specific case: where a Select component appears on a Dialog. To reduce
diff --git a/packages/manager/src/components/EnhancedSelect/Select.tsx b/packages/manager/src/components/EnhancedSelect/Select.tsx
index 3e4d3a4a7e2..1cc43122ae1 100644
--- a/packages/manager/src/components/EnhancedSelect/Select.tsx
+++ b/packages/manager/src/components/EnhancedSelect/Select.tsx
@@ -1,14 +1,15 @@
-import classNames from 'classnames';
import * as React from 'react';
-import ReactSelect, { Props as SelectProps } from 'react-select';
+import classNames from 'classnames';
+import ReactSelect, {
+ ActionMeta,
+ NamedProps as SelectProps,
+ ValueType,
+} from 'react-select';
import CreatableSelect, {
- Props as CreatableSelectProps,
+ CreatableProps as CreatableSelectProps,
} from 'react-select/creatable';
-import { withStyles, WithStyles, withTheme, WithTheme } from '@mui/styles';
import { Props as TextFieldProps } from 'src/components/TextField';
import { convertToKebabCase } from 'src/utilities/convertToKebobCase';
-/* TODO will be refactoring enhanced select to be an abstraction.
-Styles added in this file and the below imports will be utilized for the abstraction. */
import DropdownIndicator from './components/DropdownIndicator';
import Input from './components/Input';
import LoadingIndicator from './components/LoadingIndicator';
@@ -19,7 +20,8 @@ import NoOptionsMessage from './components/NoOptionsMessage';
import Option from './components/Option';
import Control from './components/SelectControl';
import Placeholder from './components/SelectPlaceholder';
-import { ClassNames, styles, reactSelectStyles } from './Select.styles';
+import { reactSelectStyles, useStyles } from './Select.styles';
+import { Theme, useTheme } from '@mui/material';
export interface Item
{
value: T;
@@ -32,17 +34,6 @@ export interface GroupType {
options: Item[];
}
-export interface SelectState {
- data: any;
- isDisabled: boolean;
- isFocused: boolean;
- isSelected: boolean;
-}
-
-interface ActionMeta {
- action: string;
-}
-
export interface NoOptionsMessageProps {
inputValue: string;
}
@@ -62,26 +53,18 @@ const _components = {
Input,
};
-interface OwnProps {
- // Set this prop to `true` when using a on a modal. It attaches the to the
- // document body directly, so the overflow is visible over the edge of the modal.
- overflowPortal?: boolean;
-}
-
-type CombinedProps = OwnProps &
- WithStyles &
- BaseSelectProps &
- CreatableProps &
- WithTheme;
-
// We extend TexFieldProps to still be able to pass
// the required label to Select and not duplicated it to TextFieldProps
interface ModifiedTextFieldProps extends Omit {
label?: string;
}
-export interface BaseSelectProps
- extends Omit, 'onChange' | 'value' | 'onFocus'> {
+export interface BaseSelectProps<
+ I extends Item,
+ IsMulti extends boolean = false,
+ Clearable extends boolean = false
+> extends Omit, 'onChange'>,
+ CreatableSelectProps {
classes?: any;
/*
textFieldProps isn't native to react-select
@@ -97,18 +80,18 @@ export interface BaseSelectProps
/**
* We require label for accessibility purpose
*/
- label: string;
- /** alias for isDisabled */
- disabled?: boolean;
- /** retyped this */
- value?: Item | Item[] | null;
- /** making this required */
- onChange: (selected: Item | Item[] | null, actionMeta?: ActionMeta) => void;
- /** alias for onCreateOption */
- createNew?: (inputValue: string) => void;
- loadOptions?: (inputValue: string) => Promise- | undefined;
- onFocus?: any;
+ label?: string;
+
+ /** onChange is called when the user selectes a new value / new values */
+ onChange: Clearable extends true // if the Select is NOT clearable, the value passed in the onChange function must be defined
+ ? Exclude['onChange'], undefined>
+ : (
+ value: Exclude, null | undefined>,
+ action: ActionMeta
+ ) => void;
+
/** the rest are props we've added ourselves */
+ disabled?: boolean;
medium?: boolean;
small?: boolean;
noMarginTop?: boolean;
@@ -120,11 +103,54 @@ export interface BaseSelectProps
required?: boolean;
creatable?: boolean;
variant?: 'creatable';
+ isClearable?: Clearable;
+ // Set this prop to `true` when using a on a modal. It attaches the to the
+ // document body directly, so the overflow is visible over the edge of the modal.
+ overflowPortal?: boolean;
}
-interface CreatableProps extends CreatableSelectProps {}
+const Select = <
+ I extends Item,
+ IsMulti extends boolean = false,
+ Clearable extends boolean = false
+>(
+ props: BaseSelectProps
+) => {
+ const theme = useTheme();
+ const classes = useStyles();
+ const {
+ className,
+ components,
+ errorText,
+ filterOption,
+ label,
+ isClearable,
+ isMulti,
+ isLoading,
+ placeholder,
+ onChange,
+ onInputChange,
+ options,
+ value,
+ noOptionsMessage,
+ onMenuClose,
+ onBlur,
+ blurInputOnSelect,
+ medium,
+ small,
+ noMarginTop,
+ textFieldProps,
+ inline,
+ hideLabel,
+ errorGroup,
+ onFocus,
+ inputId,
+ overflowPortal,
+ required,
+ creatable,
+ ...restOfProps
+ } = props;
-class Select extends React.PureComponent {
// React-Select changed the behavior of clearing isMulti Selects in v3.
// Previously, once the Select was empty, the value was `[]`. Now, it is `null`.
// This breaks many of our components, which rely on e.g. mapping through the value (which is
@@ -132,157 +158,112 @@ class Select extends React.PureComponent {
//
// This essentially reverts the behavior of the v3 React-Select update. Long term, we should
// probably re-write our component handlers to expect EITHER an array OR `null`.
- _onChange = (selected: Item | Item[] | null, actionMeta?: ActionMeta) => {
- const { isMulti, onChange } = this.props;
-
+ const _onChange = (
+ selected: ValueType,
+ actionMeta: ActionMeta
+ ) => {
if (isMulti && !selected) {
- return onChange([], actionMeta);
+ // @ts-expect-error I'm sorry, but trust me I made this component much better
+ onChange([], actionMeta);
+ } else {
+ // @ts-expect-error I'm sorry, but trust me I made this component much better
+ onChange(selected, actionMeta);
}
-
- onChange(selected, actionMeta);
};
- render() {
- const {
- classes,
- className,
- components,
- createNew,
- disabled,
- errorText,
- filterOption,
- label,
- loadOptions,
- isClearable,
- isMulti,
- isLoading,
- placeholder,
- onChange,
- onInputChange,
- options,
- value,
- noOptionsMessage,
- onMenuClose,
- onBlur,
- blurInputOnSelect,
- medium,
- small,
- noMarginTop,
- textFieldProps,
- inline,
- hideLabel,
- errorGroup,
- onFocus,
- inputId,
- overflowPortal,
- theme,
- required,
- creatable,
- ...restOfProps
- } = this.props;
-
- /*
- * By default, we use the built-in Option component from React-Select, along with several Material-UI based
- * components (listed in the _components variable above). To customize the select in a particular instance
- * (for example, to render more complicated options for search bars), provide the component to use in a prop
- * Object. Specify the name of the component to override as the object key, with the component to use in its
- * place as the value. Full list of available components to override is available at
- * http://react-select.com/components#replaceable-components. As an example, to provide a custom option component, use:
- *