UNPKG

taro-material

Version:

Mini Program components that implement Google's Material Design.

328 lines (287 loc) 8.37 kB
import Nerv from "nervjs"; import Taro, { Component } from "@tarojs/taro-h5"; import { View } from '@tarojs/components'; import PropTypes from 'prop-types'; import RMIcon from "../Icon/index"; import RMTypography from "../Typography/index"; import RMDrawer from "../Drawer/index"; import RMActionFilter from "../ActionFilter/index"; import RMDropdown from "../Dropdown/index"; import theme from "../styles/theme"; import './ActionBar.scss'; const cloneDeep = o => JSON.parse(JSON.stringify(o)); const isEqual = (array1, array2) => { if (array1 === array2) { return true; } if (!(array1 && array2)) { return false; } if (array1.length !== array2.length) { return false; } for (let i = 0; i < array1.length; i++) { if (!(array1[i].label === array2[i].label && array1[i].value === array2[i].value)) { return false; } else if (!array1[i].data && array2[i].data || array1[i].data && !array2[i].data) { return false; } else if (Array.isArray(array1[i].data) && Array.isArray(array2[i].data)) { const r = isEqual(array1[i].data, array2[i].data); if (!r) { return false; } } } return true; }; class RMActionBar extends Component { state = { expanded: false, show: false, value: '' }; constructor(props) { super(props); this.init(props.filter, props.sorts); } init() { const { filters, sorts } = this.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 }); } refDrawer = node => this.drawer = node; refFilter = node => this.filter = node; componentWillReceiveProps(nextProps) { const { filter, sorts } = this.props; if (!isEqual(nextProps.filter, filter) || !isEqual(nextProps.sorts, sorts)) { this.init(nextProps.filter, nextProps.sorts); } } componentWillUnmount() {} componentDidShow() {} componentDidHide() {} handleTitleClick() { const { expanded } = this.state; this.setState({ expanded: !expanded }); } 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(); }); }; 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(); }); } handleSiftingClick() { this.setState({ show: true, expanded: false }); } 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 }); } handleFilterOk(e) { this.drawer.animHide(); this.setState({ selectedFilters: e }, () => { this.onChange(); }); } handleFilterReset(e) { this.setState({ selectedFilters: e }, () => { this.onChange(); }); } 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); } handleFilters(i, j) { this.filter.handleClick(i, j, true); } handleDrawerClose() { this.setState({ show: false }); } handleDropDownClose = () => { this.setState({ expanded: false }); }; render() { const { filters } = this.props; const { expanded, value, show } = 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 }; return <View className="root"> <View className="header"> <View onClick={this.handleTitleClick} className="title"> <View className="label"> <RMTypography color={selectedSort.active ? theme.palette.primary.main : 'default'} className="body2" block> {selectedSort.label} </RMTypography> </View> <RMIcon color={selectedSort.active ? 'primary' : 'inherit'} block fontSize="inherit"> {expanded ? 'keyboard_arrow_down' : 'keyboard_arrow_up'} </RMIcon> </View> {prioritySorts.map((item, index) => { const color = item.active ? theme.palette.primary.main : 'default'; const className = item.active ? 'body2' : 'body1'; return <View key={item.value} className="priorities" onClick={this.handlePriorities.bind(this, index)}> <RMTypography color={color} className={className} block> {item.label} </RMTypography> </View>; })} <View className="title">{this.props.renderTools}</View> {priorityFilters.map(item => { const color = item.active ? theme.palette.primary.main : 'default'; const className = item.active ? 'body2' : 'body1'; return <View key={item.value} className="priorities" onClick={this.handleFilters.bind(this, item.i, item.j)}> <RMTypography color={color} className={className} block> {item.label} </RMTypography> </View>; })} <View onClick={this.handleSiftingClick} className="title"> <View className="label"> <RMTypography color={multiLength > 0 ? theme.palette.primary.main : 'default'} className="body2" block> 筛选 {multiLength ? `(${multiLength})` : ''} </RMTypography> </View> <RMIcon color={multiLength > 0 ? 'primary' : 'inherit'} block fontSize="inherit"> {'filter_list'} </RMIcon> </View> </View> {<RMDropdown isOpened={expanded} options={normalSorts} onClose={this.handleDropDownClose} value={value} onChange={this.handleChange} />} <RMDrawer ref={this.refDrawer} show={show} width={320} right onClose={this.handleDrawerClose}> <RMActionFilter data={filters} onOk={this.handleFilterOk} onReset={this.handleFilterReset} onChange={this.handleFilterChange} ref={this.refFilter} /> </RMDrawer> </View>; } } RMActionBar.propTypes = { onChange: PropTypes.func, filters: PropTypes.array, sorts: PropTypes.array, renderTools: PropTypes.element }; RMActionBar.defaultProps = { onChange: () => {}, filters: [], sorts: [], renderTools: null }; export default RMActionBar;