UNPKG

@6thquake/react-material

Version:

React components that implement Google's Material Design.

336 lines (310 loc) 7.41 kB
/** * @ignore - internal component. */ import PropTypes from 'prop-types'; import React from 'react'; import Button from '../Button'; import withStyles from '../styles/withStyles'; import Typography from '../Typography'; import cloneDeep from 'lodash/cloneDeep'; import { compose } from 'recompose'; const tagStyle = theme => { return { root: { display: 'flex', padding: `${theme.spacing(0.25)}px ${theme.spacing(1)}px`, justifyContent: 'center', alignItems: 'center' } }; }; let Tag = function ({ classes, color, theme, children }) { const paletteColor = theme.palette[color]; const c = paletteColor ? paletteColor.main : theme.palette.grey[200]; const style = { borderRadius: `${theme.shape.borderRadius / 2}px`, border: `1px solid ${c}` }; return React.createElement(Typography, { className: classes.root, color: color, style: style }, children); }; Tag = withStyles(tagStyle, { withTheme: true })(Tag); const styles = theme => ({ root: { display: 'flex', flexDirection: 'column', justifyContent: 'flex-start', alignItems: 'stretch', position: 'relative', height: '100vh', minHeight: '100vh', width: '100%', flex: 1, // paddingLeft: theme.spacing(2), // paddingRight: theme.spacing(2), boxSizing: 'border-box' }, filters: { display: 'flex', flexDirection: 'column', alignItems: 'stretch', overflow: 'auto', flex: 1, padding: `${theme.spacing(2)}px` }, options: { paddingBottom: theme.spacing(1.5), paddingTop: theme.spacing(1.5), '&:not(:first-child)': { borderTop: `1px solid ${theme.palette.grey[200]}` } }, tags: { display: 'flex', flexWrap: 'wrap', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingBottom: theme.spacing(1.5), paddingTop: theme.spacing(1.5) }, spacing: { flex: 1, minWidth: '31%', maxWidth: '31%' }, tag: { flex: 1, minWidth: '31%', maxWidth: '31%', paddingBottom: theme.spacing(1), paddingTop: theme.spacing(1) }, actions: { display: 'flex', justifyContent: 'flex-end', alignItems: 'center' }, buttonBox: { width: '50%', display: 'flex', flexDirection: 'column', alignItems: 'stretch', justifyContent: 'flex-end', '&.primary': { background: theme.palette.primary.main } }, button: { width: '100%', boxShadow: 'none', borderRadius: '0px', height: theme.spacing(6) } }); class ActionFilter extends React.Component { constructor(props) { super(props); this.state = { data: [] }; this.handleOkClick = () => { const { data: options } = this.state; const { onOk } = this.props; const selections = options.map(item => { const { label, value, data } = item; const activeTag = data.filter(d => d.active); return { label, value, data: cloneDeep(activeTag) }; }).filter(item => item.data.length > 0); onOk(selections); }; this.handleResetClick = () => { const { data, onReset, onChange } = this.props; const _data = cloneDeep(data); const selections = _data.map(item => { const { label, value } = item; const activeTag = item.data.filter(d => d.active); return { label, value, data: cloneDeep(activeTag) }; }).filter(item => item.data.length > 0); this.setState({ data: _data }, () => { onChange(cloneDeep(_data)); onReset(selections); }); }; this.state.data = props.data; } componentWillReceiveProps(nextProps) { const { data } = this.props; if (nextProps.data !== data) { this.setState({ data: nextProps.data }); } } handleClick(i, j, immediately) { const { onChange } = this.props; const { data } = this.state; const options = cloneDeep(data); const option = options[i]; if (option.single) { option.data.forEach((item, index) => { if (index !== j) { item.active = false; } }); } const tag = option.data[j]; tag.active = !tag.active; if (option.required) { const ops = option.data.filter(item => item.active); if (ops.length <= 0) { tag.active = true; } } this.setState({ data: options }, () => { onChange(cloneDeep(options)); immediately && this.handleOkClick(); }); } render() { const { classes, width } = this.props; const { data: options } = this.state; const filtersStyle = { width }; return React.createElement("div", { className: classes.root }, React.createElement("div", { style: filtersStyle, className: classes.filters }, React.createElement("div", { className: classes.box }, options && options.map((option, i) => { const { label, value, data } = option; return React.createElement("div", { key: value, className: classes.option }, React.createElement("div", { className: classes.title }, React.createElement(Typography, { variant: "body2" }, label)), React.createElement("div", { className: classes.tags }, data.map((item, j) => React.createElement("div", { onClick: this.handleClick.bind(this, i, j, false), key: item.value, className: classes.tag }, React.createElement(Tag, { color: item.active ? 'primary' : 'default' }, React.createElement(Typography, { color: "inherit", variant: "body1" }, item.label)))), React.createElement("div", { className: classes.spacing }))); }))), React.createElement("div", { className: classes.actions }, React.createElement("div", { className: classes.buttonBox }, React.createElement(Button, { className: classes.button, color: "default", variant: "text", onClick: this.handleResetClick, size: "normal" }, "\u91CD\u7F6E")), React.createElement("div", { className: classes.buttonBox }, React.createElement(Button, { className: classes.button, color: "primary", variant: "contained", onClick: this.handleOkClick, size: "normal" }, "\u786E\u5B9A")))); } } process.env.NODE_ENV !== "production" ? ActionFilter.propTypes = { /** * data of action filter */ data: PropTypes.array, /** * Callback fired when the selected value to be changed. */ onChange: PropTypes.func, /** * Callback fired when the confirm button to be clicked. */ onOk: PropTypes.func, /** * Callback fired when the reset button to be clicked. */ onReset: PropTypes.func, /** * the width of action filter. */ width: PropTypes.width } : void 0; ActionFilter.defaultProps = { onOk: () => {}, onChange: () => {}, onReset: () => {}, data: [], width: 300 }; export default compose(withStyles(styles, { name: 'RMActionFilter', withTheme: true }))(ActionFilter);