UNPKG

element-react-codish

Version:
261 lines (232 loc) 7.18 kB
/* @flow */ import React from 'react'; import { Component, PropTypes, View } from '../../libs'; import Input from '../input'; import Checkbox from '../checkbox'; import i18n from '../locale'; type Props = { data: Array<Object>, renderContent?: Function, placeholder?: string, title?: string, filterable?: boolean, footerFormat: Object, filterMethod?: Function, propsAlias: Object, onChange: Function, disableFilter: boolean, onKeyPress: Function, checked: Array<Object>, hasChecked?: boolean, noChecked?: boolean, children: React.Element<any> }; type defaultProps = { data: Array<Object>, footerFormat: Object, onChange: Function, } type State = { query: string, inputHover: boolean, }; export default class TransferPanel extends Component { props: Props; state: State; static propTypes = { data: PropTypes.array, renderContent: PropTypes.func, placeholder: PropTypes.string, title: PropTypes.string, filterable: PropTypes.bool, footerFormat: PropTypes.object, filterMethod: PropTypes.func, propsAlias: PropTypes.object, onChange: PropTypes.func, checked: PropTypes.array, disableFilter: PropTypes.bool, onKeyPress: PropTypes.func, }; static defaultProps: defaultProps = { data: [], footerFormat: {}, propsAlias: {}, onChange() {} }; constructor(props: Props) { super(props); this.state = { query: '', inputHover: false, }; } handleMouseEnter = () => this.setState({ inputHover: true }); handleMouseLeave = () => this.setState({ inputHover: false }); clearQuery = () => { if (this.inputIcon === 'circle-close') { this.setState({ query: '' }); } }; handleAllCheckedChange = (ischecked: boolean) => { const checked = ischecked ? this.checkableData.map(item => item[this.keyProp]) : []; this.props.onChange(checked); }; handleCheckedChange = (value: Array<Object>) => { this.props.onChange(value); }; handleInputChange = (value: string) => { this.setState({ query: value }); }; get allChecked(): boolean { const checkableDataKeys = this.checkableData.map( item => item[this.keyProp] ); return checkableDataKeys.length > 0 && checkableDataKeys.every(item => this.props.checked.includes(item)); } get filteredData(): Array<Object> { if (this.props.disableFilter) return this.props.data; return this.props.data.filter(item => { if (typeof this.props.filterMethod === 'function') { return this.props.filterMethod(this.state.query, item); } else { const label = item[this.labelProp] || item[this.keyProp].toString(); return label.toLowerCase().includes(this.state.query.toLowerCase()); } }); } get checkableData(): Array<Object> { return this.filteredData.filter(item => !item[this.disabledProp]); } get checkedSummary(): string { const checkedLength = this.props.checked.length; const dataLength = this.props.data.length; const { noChecked, hasChecked } = this.props.footerFormat; if (noChecked && hasChecked) { return checkedLength > 0 ? hasChecked .replace(/\${checked}/g, checkedLength) .replace(/\${total}/g, dataLength) : noChecked.replace(/\${total}/g, dataLength); } else { return checkedLength > 0 ? i18n.t('el.transfer.hasCheckedFormat', { total: dataLength, checked: checkedLength }) : i18n.t('el.transfer.noCheckedFormat', { total: dataLength }); } } get isIndeterminate(): boolean { const checkedLength = this.props.checked.length; return checkedLength > 0 && checkedLength < this.checkableData.length; } get hasNoMatch(): boolean { const { query } = this.state; return query.length > 0 && this.filteredData.length === 0; } get inputIcon(): 'circle-close' | 'search' { const { query, inputHover } = this.state; return query.length > 0 && inputHover ? 'circle-close' : 'search'; } get labelProp(): string { return this.props.propsAlias.label; } get keyProp(): string { return this.props.propsAlias.key; } get disabledProp(): string { return this.props.propsAlias.disabled; } handleKeyPress = (e) => { if (this.props.onKeyPress) { this.props.onKeyPress(e); } } render(): React.Element<any> { const { filterable, title, data, renderContent, checked, placeholder } = this.props; const { query } = this.state; return ( <div className="el-transfer-panel"> <p className="el-transfer-panel__header">{title}</p> <div className="el-transfer-panel__body"> {filterable && <Input className="el-transfer-panel__filter" value={query} size="small" placeholder={placeholder} icon={this.inputIcon} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} onIconClick={this.clearQuery} onChange={this.handleInputChange} onKeyPress={this.handleKeyPress} />} <View show={!this.hasNoMatch && data.length > 0}> <Checkbox.Group value={checked} v-show="" className={this.classNames({ 'is-filterable': filterable, 'el-transfer-panel__list': true })} onChange={this.handleCheckedChange} > {this.filteredData.map((item, index) => ( <Checkbox className="el-transfer-panel__item" label={item[this.labelProp]} disabled={item[this.disabledProp]} value={item[this.keyProp]} key={index} > <OptionContent option={item} renderContent={renderContent} labelProp={this.labelProp} keyProp={this.keyProp} /> </Checkbox> ))} </Checkbox.Group> </View> <View show={this.hasNoMatch}> <p className="el-transfer-panel__empty"> {i18n.t('el.transfer.noMatch')} </p> </View> <View show={data.length === 0 && !this.hasNoMatch}> <p className="el-transfer-panel__empty"> {i18n.t('el.transfer.noData')} </p> </View> </div> <p className="el-transfer-panel__footer"> <Checkbox checked={this.allChecked} onChange={this.handleAllCheckedChange} indeterminate={this.isIndeterminate} > {this.checkedSummary} </Checkbox> {this.props.children} </p> </div> ); } } const OptionContent = ({ option, renderContent, labelProp, keyProp }) => { return renderContent ? renderContent(option) : <span>{option[labelProp] || option[keyProp]}</span>; };