UNPKG

zarm-mobile

Version:
183 lines (158 loc) 4.98 kB
import React, { Component } from 'react'; import classNames from 'classnames'; import ZScroller from 'zscroller'; import { isChildrenEqual } from './utils'; function getChildMember(child, m) { return child[m]; } function toChildrenArray(children) { return children; } class Column extends Component { constructor(props) { super(props); let selectedValueState; const { selectedValue, defaultSelectedValue, children } = this.props; if (selectedValue !== undefined) { selectedValueState = selectedValue; } else if (defaultSelectedValue !== undefined) { selectedValueState = defaultSelectedValue; } else if (children && children.length) { selectedValueState = children[0][this.props.valueMember]; } this.state = { selectedValue: selectedValueState, }; } componentDidMount() { this.itemHeight = this.indicator.offsetHeight; // console.log('this.itemHeight -> ', this.indicator.offsetHeight); // compact this.content.style.padding = `${this.itemHeight * 3}px 0`; this.zscroller = new ZScroller(this.content, { scrollingX: false, snapping: true, penetrationDeceleration: 0.1, minVelocityToKeepDecelerating: 0.5, scrollingComplete: this.scrollingComplete.bind(this), }); this.zscroller.setDisabled(this.props.disabled); this.zscroller.scroller.setSnapSize(0, this.itemHeight); this.select(this.state.selectedValue); } componentWillReceiveProps(nextProps) { if ('selectedValue' in nextProps) { this.setState({ selectedValue: nextProps.selectedValue, }); } this.zscroller.setDisabled(nextProps.disabled); } shouldComponentUpdate(nextProps, nextState) { return this.state.selectedValue !== nextState.selectedValue || !isChildrenEqual(this.props.children, nextProps.children, this.props.pure); } componentDidUpdate() { this.zscroller.reflow(); this.select(this.state.selectedValue); } componentWillUnmount() { this.zscroller.destroy(); } getValue() { return this.props.selectedValue ? this.props.selectedValue : this.props.children && this.props.children[0] && this.props.children[0][this.props.valueMember]; } scrollingComplete() { const { top } = this.zscroller.scroller.getValues(); if (top >= 0) { this.doScrollingComplete(top); } } fireValueChange(selectedValue) { if (selectedValue !== this.state.selectedValue) { if (!('selectedValue' in this.props)) { this.setState({ selectedValue, }); } this.props.onValueChange(selectedValue); } } scrollTo(top) { this.zscroller.scroller.scrollTo(0, top); } select(value) { const children = toChildrenArray(this.props.children); for (let i = 0, len = children.length; i < len; i += 1) { if (getChildMember(children[i], this.props.valueMember) === value) { this.selectByIndex(i); return; } } this.selectByIndex(0); } selectByIndex(index) { if (index < 0 || index >= toChildrenArray(this.props.children).length || !this.itemHeight) { return; } this.scrollTo(index * this.itemHeight); } doScrollingComplete(top) { let index = top / this.itemHeight; const floor = Math.floor(index); if (index - floor > 0.5) { index = floor + 1; } else { index = floor; } const children = toChildrenArray(this.props.children); index = Math.min(index, children.length - 1); const child = children[index]; if (child) { this.fireValueChange(getChildMember(child, this.props.valueMember)); } else if (console.warn) { console.warn('child not found', children, index); } } render() { const { children, prefixCls, className, itemStyle, indicatorStyle, valueMember, } = this.props; const { selectedValue } = this.state; const itemClassName = `${prefixCls}-cascader-item`; const selectedItemClassName = `${itemClassName} ${prefixCls}-cascader-item-selected`; const items = children.map((item) => { return ( <div style={itemStyle} className={selectedValue === item[valueMember] ? selectedItemClassName : itemClassName} key={item.value} > {item.label} </div> ); }); const pickerCls = { [className]: !!className, [`${prefixCls}-cascader`]: true, }; return ( <div className={classNames(pickerCls)} > <div className={`${prefixCls}-cascader-indicator`} ref={(indicator) => { this.indicator = indicator; }} style={indicatorStyle} /> <div className={`${prefixCls}-cascader-content`} ref={(content) => { this.content = content; }}> {items} </div> </div> ); } } Column.defaultProps = { // prefixCls: 'za-cascaderpicker', prefixCls: 'za-picker', pure: true, onValueChange: () => {}, }; export default Column;