Home Reference Source Repository

src/tree/TreeNode.js

/**
 * @file melon/Tree
 * @author cxtom<[email protected]>
 */

import React, {Component, PropTypes, Children} from 'react';
import {create} from 'melon-core/classname/cxBuilder';
import Icon from '../Icon';

const cx = create('TreeNode');

export default class TreeNode extends Component {

    constructor(props) {

        super(props);

        this.onClick = this.onClick.bind(this);

        this.state = {
            expand: props.expand || false
        };

    }

    shouldComponentUpdate(nextProps, nextState) {
        return nextState.expand !== this.state.expand;
    }

    componentWillReceiveProps(props) {

        if (props.expand === this.props.expand) {
            return;
        }

        this.setState({expand: props.expand});
    }

    onClick(e) {
        this.setState({expand: !this.state.expand});
    }

    render() {

        const props = this.props;
        /* eslint-disable fecs-min-vars-per-destructure */
        const {label, ...others} = props;
        /* eslint-enable fecs-min-vars-per-destructure */
        const expand = this.state.expand;

        const icon = expand
            ? (props.expandIcon || TreeNode.ICON[1])
            : (props.unexpandIcon || TreeNode.ICON[0]);

        let children = props.children;

        let iconStyle;
        let labelStyle;

        if (props.level) {
            const level = props.level - 0;
            labelStyle = {
                paddingLeft: level * 1.2 + 0.4 + 'em'
            };
            iconStyle = {
                left: (0.25 + (level - 1) * 1.2) + 'em'
            };
        }

        // 是否还有子节点
        if (Children.count(children) > 0) {
            children = [
                <Icon
                    key="icon"
                    icon={icon}
                    onClick={this.onClick}
                    style={iconStyle} />,
                <span
                    onClick={this.onClick}
                    key="label"
                    data-role="tree-node-label"
                    style={labelStyle}
                    className={cx().part('label').addVariants('parent').addStates({expand}).build()}>
                    {label}
                </span>,
                <ul
                    className={cx().part('root').addStates({expand}).build()}
                    key="root"
                    ref="list" >
                    {children}
                </ul>
            ];
        }
        else {
            children = (
                <span
                    onClick={this.onClick}
                    key="label"
                    data-role="tree-node-label"
                    style={labelStyle}
                    className={cx().part('label').build()}>
                    {label}
                </span>
            );
        }

        return (
            <li
                {...others}
                data-role="tree-node"
                className={cx(props).addVariants('level' + props.level).build()}>
                {children}
            </li>
        );

    }

}

TreeNode.propTypes = {
    label: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.element
    ]),
    expandIcon: PropTypes.string,
    unexpandIcon: PropTypes.string,
    expand: PropTypes.bool,
    selected: PropTypes.bool,
    level: PropTypes.number
},

TreeNode.defaultProps = {
    label: '',
    expand: false,
    selected: false
};

TreeNode.ICON = [
    'expand-less',
    'expand-more'
];