@6thquake/react-material
Version:
React components that implement Google's Material Design.
524 lines (485 loc) • 12.1 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import React from 'react';
import PropTypes from 'prop-types';
import withStyles from '../styles/withStyles';
import AppBar from '../AppBar';
import MenuItem from '../MenuItem';
import MenuList from '../MenuList';
import Typography from '../Typography';
import Paper from '../Paper';
import isEqual from 'lodash/isEqual';
import cloneDeep from 'lodash/cloneDeep';
import KeyboardArrowDown from '@material-ui/icons/KeyboardArrowDown';
import KeyboardArrowUp from '@material-ui/icons/KeyboardArrowUp';
import FilterList from '@material-ui/icons/FilterList';
import SwipeableDrawer from '../SwipeableDrawer';
import ActionFilter from './ActionFilter';
const dropDownStyle = theme => ({
root: {
position: 'absolute',
width: '100%',
top: 0,
backgroundColor: 'inherit',
boxSizing: 'content-box',
zIndex: theme.zIndex.appBar - 1
},
menuList: {
zIndex: theme.zIndex.appBar,
position: 'relative'
},
menuItem: {
backgroundColor: theme.palette.primary.main,
'& $primary, & $icon': {
color: theme.palette.common.white
}
},
mask: {
width: '100vh',
height: '100vh',
position: 'fixed',
opacity: 0,
background: 'black',
left: 0,
top: 0,
zIndex: theme.zIndex.appBar - 1
}
});
function DropDown({
theme,
onClose,
onChange,
classes,
value,
options = []
}) {
return React.createElement(Paper, {
square: true,
elevation: 1,
className: classes.root
}, React.createElement(MenuList, {
className: classes.menuList
}, options.map(item => {
const active = item.value === value;
return React.createElement(MenuItem, {
onClick: () => {
onChange(item.value);
},
key: item.value,
className: active ? classes.menuItem : ''
}, React.createElement(Typography, {
style: {
color: active ? theme.palette.common.white : ''
},
variant: 'body1'
}, item.label));
})), React.createElement("div", {
className: classes.mask,
onClick: onClose
}));
}
const StyledDropDown = withStyles(dropDownStyle, {
name: 'RMDropDown',
withTheme: true
})(DropDown);
export const styles = theme => ({
root: {
position: 'relative',
'box-sizing': 'border-box',
backgroundColor: theme.palette.background.paper
},
bar: {
display: 'flex',
flex: 1,
justifyContent: 'space-between',
alignItems: 'center',
padding: `${theme.spacing(1.5)}px ${theme.spacing(1)}px`,
zIndex: theme.zIndex.appBar
},
leftBox: {
display: 'flex'
},
left: {
display: 'flex',
alignItems: 'center',
paddingRight: theme.spacing(0.5)
},
label: {
paddingLeft: theme.spacing(1)
},
leftPriority: {
display: 'flex',
alignItems: 'center'
},
slots: {
display: 'flex',
flex: 1,
alignItems: 'center'
},
rightBox: {
display: 'flex',
alignItems: 'center',
paddingLeft: theme.spacing(0.5),
justifyContent: 'flex-end'
},
right: {
alignItems: 'center',
display: 'flex'
},
rightPriority: {
alignItems: 'center',
display: 'flex'
},
item: {
marginRight: theme.spacing(1)
},
menuBox: {
position: 'relative',
backgroundColor: 'inherit',
width: '100%'
}
});
class ActionBar extends React.Component {
constructor(_props) {
super(_props);
this.init = props => {
const {
filters,
sorts
} = props;
const _filters = cloneDeep(filters);
const _sorts = cloneDeep(sorts);
const priorityFilters = [];
const selectedFilters = [];
_filters.forEach((filter, i) => {
const {
label,
value,
data
} = filter;
const datas = [];
data.forEach((item, j) => {
if (item.priority) {
item.i = i;
item.j = j;
priorityFilters.push(item);
}
if (item.active) {
datas.push(item);
}
});
if (datas.length > 0) {
selectedFilters.push({
label,
value,
data: datas
});
}
});
const prioritySorts = [];
const normalSorts = [];
let value = '';
_sorts.forEach(item => {
if (item.priority) {
prioritySorts.push(item);
} else {
normalSorts.push(item);
}
if (item.active) {
value = item.value;
}
});
this.setState({
value,
prioritySorts,
normalSorts,
priorityFilters,
selectedFilters
});
};
this.filter = null;
this.refFilter = node => this.filter = node;
this.handleTitleClick = e => {
const {
expanded
} = this.state;
this.setState({
expanded: !expanded
});
};
this.handleChange = value => {
const {
normalSorts,
prioritySorts
} = this.state;
normalSorts.forEach(item => {
if (item.value === value) {
item.active = true;
} else {
item.active = false;
}
});
prioritySorts.forEach(item => {
item.active = false;
});
this.setState({
value,
expanded: false
}, () => {
this.onChange();
});
};
this.handleSiftingClick = () => {
this.setState({
open: true,
expanded: false
});
};
this.handleFilterChange = e => {
const priorityFilters = [];
e.forEach((filter, i) => {
filter.data.forEach((item, j) => {
if (item.priority) {
item.i = i;
item.j = j;
priorityFilters.push(item);
}
});
});
this.setState({
priorityFilters
});
};
this.handleFilterOk = e => {
this.setState({
selectedFilters: e,
open: false
}, () => {
this.onChange();
});
};
this.handleFilterReset = e => {
this.setState({
selectedFilters: e
}, () => {
this.onChange();
});
};
this.onChange = () => {
const {
onChange,
sorts
} = this.props;
const {
selectedFilters,
value
} = this.state;
const data = {
sort: sorts.filter(item => item.value === value)[0],
filters: selectedFilters
};
onChange(data);
};
this.handleDrawerClose = () => {
this.setState({
open: false
});
};
this.handleDropDownClose = () => {
this.setState({
expanded: false
});
};
this.handleDrawerClose = () => {
this.setState({
open: false
});
};
this.domRef = React.createRef();
this.state = {
expanded: false,
open: false,
value: ''
};
}
componentDidMount() {
this.init(this.props);
}
componentWillReceiveProps(nextProps) {
const {
filter,
sorts
} = this.props;
if (!isEqual(nextProps.filter, filter) || !isEqual(nextProps.sorts, sorts)) {
this.init(nextProps);
}
}
handlePriorities(index) {
const {
normalSorts,
prioritySorts
} = this.state;
let value = null;
prioritySorts.forEach((item, i) => {
if (i === index) {
item.active = true;
value = item.value;
} else {
item.active = false;
}
});
normalSorts.forEach(item => {
item.active = false;
});
this.setState({
value,
expanded: false
}, () => {
this.onChange();
});
}
handleFilters(i, j) {
this.filter.handleClick(i, j, true);
}
render() {
const {
classes,
theme,
filters,
AppBarProps,
children
} = this.props;
const iOS = process.browser && /iPad|iPhone|iPod/.test(navigator.userAgent);
const {
expanded,
value,
open
} = this.state;
const {
selectedFilters = [],
priorityFilters = [],
normalSorts = [],
prioritySorts = []
} = this.state;
const multiLength = selectedFilters.reduce((r, next) => r + next.data.length, 0);
const selectedSort = normalSorts.filter(item => item.value === value)[0] || {
label: '排序',
active: false,
value
};
const ArrowIcon = expanded ? KeyboardArrowDown : KeyboardArrowUp;
return React.createElement(AppBar, _extends({
elevation: 1,
position: "static",
color: "default",
className: classes.root
}, AppBarProps), React.createElement("div", {
className: classes.bar
}, React.createElement("div", {
className: classes.leftBox
}, React.createElement("div", {
onClick: this.handleTitleClick,
className: classes.left
}, React.createElement(Typography, {
style: {
color: selectedSort.active ? theme.palette.primary.main : ''
},
className: classes.label,
variant: "body1"
}, selectedSort.label), React.createElement(ArrowIcon, {
color: selectedSort.active ? 'primary' : 'inherit'
})), React.createElement("div", {
className: classes.leftPriority
}, prioritySorts.map((item, index) => {
const color = item.active ? theme.palette.primary.main : '';
const className = item.active ? 'body2' : 'body1';
return React.createElement("div", {
key: item.value,
className: classes.item,
onClick: this.handlePriorities.bind(this, index)
}, React.createElement(Typography, {
style: {
color
},
variant: className
}, item.label));
}))), React.createElement("div", {
className: classes.slots
}, children), React.createElement("div", {
className: classes.rightBox
}, React.createElement("div", {
className: classes.rightPriority
}, priorityFilters.map((item, index) => {
const color = item.active ? theme.palette.primary.main : '';
const className = item.active ? 'body2' : 'body1';
return React.createElement("div", {
key: item.value,
className: classes.item,
onClick: this.handleFilters.bind(this, item.i, item.j)
}, React.createElement(Typography, {
style: {
color
},
variant: className
}, item.label));
})), React.createElement("div", {
className: classes.right
}, React.createElement("div", {
onClick: this.handleSiftingClick,
className: classes.left
}, React.createElement(Typography, {
color: multiLength ? 'primary' : '',
className: classes.label,
variant: multiLength > 0 ? 'body2' : 'body1'
}, "\u7B5B\u9009", multiLength ? `(${multiLength})` : ''), React.createElement(FilterList, {
color: multiLength > 0 ? 'primary' : 'inherit'
}))))), expanded && React.createElement("div", {
className: classes.menuBox
}, React.createElement(StyledDropDown, {
onClose: this.handleDropDownClose,
onChange: this.handleChange,
options: normalSorts,
value: value
})), React.createElement(SwipeableDrawer, {
variant: "persistent",
disableBackdropTransition: !iOS,
disableDiscovery: iOS,
onClose: this.handleDrawerClose,
anchor: "right",
open: open
}, React.createElement(ActionFilter, {
data: filters,
onOk: this.handleFilterOk,
onReset: this.handleFilterReset,
onChange: this.handleFilterChange,
innerRef: this.refFilter
})));
}
}
process.env.NODE_ENV !== "production" ? ActionBar.propTypes = {
/**
* items of filters
*/
filters: PropTypes.array,
/**
* data of sort bar
*/
sorts: PropTypes.array,
/**
* Callback fired when the selected data to be changed.
*/
onChange: PropTypes.func,
/**
* Props of AppBar
*/
AppBarProps: PropTypes.object
} : void 0;
ActionBar.defaultProps = {
onChange: () => {},
filters: [],
sorts: [],
AppBarProps: {}
};
export default withStyles(styles, {
name: 'RMActionBar',
withTheme: true
})(ActionBar);