d2-ui
Version:
163 lines (136 loc) • 4.08 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import MuiSelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
import CircularProgress from 'material-ui/CircularProgress';
import isString from 'lodash/fp/isString';
import { createClassName } from '../component-helpers/utils';
const getLoadingStyle = (loading) => {
let listStyle;
if (loading === true) {
listStyle = {
textAlign: 'center',
};
} else if (isString(loading)) {
listStyle = {
paddingLeft: 24,
lineHeight: '32px',
fontStyle: 'italic',
};
}
return listStyle;
};
const getLoadingIndicator = (loading) => {
let node;
if (loading === true) {
node = <CircularProgress size={30} />;
} else if (isString(loading)) {
node = <div>{loading}</div>;
}
return node;
};
const getMenuItems = (items, isLoading, isMultiple, value) => {
if (isLoading || !Array.isArray(items)) {
return null;
}
return items.map(item => (
<MenuItem
key={item.id}
value={item.id}
primaryText={item.name}
insetChildren={isMultiple}
checked={isMultiple && Array.isArray(value) && value.indexOf(item.id) > -1}
/>
));
};
const SelectField = (props) => {
const { label, items, multiple, value, onChange, style, selector, loading, errorText, children } = props;
const className = createClassName('d2-ui-selectfield', selector);
return (
<MuiSelectField
floatingLabelText={label}
value={value}
multiple={multiple}
onChange={onChange ? (event, index, val) => onChange(items[index] || val) : null}
className={className}
style={style}
listStyle={getLoadingStyle(loading)}
errorText={errorText}
>
{getLoadingIndicator(loading)}
{getMenuItems(items, loading, multiple, value)}
{!loading && children ? children : null}
</MuiSelectField>
);
};
SelectField.propTypes = {
/**
* The label of the select field
*/
label: PropTypes.string,
/**
* The select field items (rendered as MenuItems)
*/
items: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
name: PropTypes.string,
})),
/**
* If true, the select field will support multiple selection. A check mark will show before selected items.
*/
multiple: PropTypes.bool,
/**
* If true, a spinner will be shown in the select menu. If string, the loading text will be shown.
*/
loading: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.string,
]),
/**
* onChange callback, that is fired when the select field's value changes
*
* The onChange callback will receive one argument: The item selected (if items are provided) or the value selected
*/
onChange: PropTypes.func,
/**
* The value(s) of the select field
*/
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.arrayOf(PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
])),
]),
/**
* Override the inline-styles of the root element
*/
style: PropTypes.object,
/**
* If set, adds a class to the element in the format d2-ui-selectfield-selector
*/
selector: PropTypes.string,
/**
* If set, shows the error message below the SelectField
*/
errorText: PropTypes.string,
/**
* MenuItems to show in the dropdown
*/
children: PropTypes.node,
};
SelectField.defaultProps = {
errorText: null,
items: [],
loading: false,
label: null,
multiple: false,
onChange: null,
className: null,
selector: null,
style: null,
value: null,
children: null,
};
export default SelectField;