import React from 'react'
import PropTypes from 'prop-types'
import Component from '../utils/Component'
import classnames from 'classnames'
import Icon from '../icon'
import Logger from '../utils/logger'
import '../style'
import 'phoenix-styles/less/modules/accordion.less'
/**
* <h5>操作类组件,主要包括组件:</h5>
* <strong><a href='../classes/Accordion.html'>Accordion 手风琴</a></strong><br/>
* <strong><a href='../classes/Toast.html'>Toast 飘字</a></strong><br>
* <strong><a href='../classes/Popup.html'>Popup 弹层</a></strong><br>
* <strong><a href='../classes/Slider.html'>Slider 滑动输入条</a></strong><br>
* <strong><a href='../classes/Swipe.html'>Swipe 左滑动</a></strong><br>
* <strong><a href='../classes/Menu.html'>Menu 菜单</a></strong><br>
* <strong><a href='../classes/LoadingList.html'>LoadingList 加载更多</a></strong><br>
* <h6>点击以上链接或者左侧导航栏的组件名称链接进行查看</h6>
* @module 操作类组件
* @main 操作类组件
* @static
*/
/**
* 手风琴组件<br/>
* - 通过visible设置初始展开或收起的状态, 可选true/false。
* - 可通过clickCallback设置展开收起时额外的回调函数。
* - 可通过hideIcon设置隐藏向下的箭头。
*
* 主要属性和接口:
* - visible:初始展开或收起的状态, 默认false收起。
* = hideIcon:设置隐藏向下的箭头, 默认false可见。<br/>
* 如:
* ```code
* <Accordion visible={true} hideIcon>
* <Accordion.Header>
* 标题一
* </Accordion.Header>
* <Accordion.Body>
* ...
* </Accordion.Body>
* </Accordion>
* ```
* - clickCallback:点击收起展开的额外的回调执行函数。<br/>
* 如:
* ```code
* <Accordion clickCallback={(visible)=>{console.log(visible);}}>
* <Accordion.Header>
* 标题一
* </Accordion.Header>
* <Accordion.Body>
* ...
* </Accordion.Body>
* </Accordion>
* ```
*
* @class Accordion
* @module 操作类组件
* @extends Component
* @constructor
* @since 0.4.0
* @demo accordion|accordion.js {展示}
* @show true
* */
class Accordion extends Component{
static propTypes = {
/**
* 样式前缀
* @property classPrefix
* @type String
* @default 'accordion'
* */
classPrefix: PropTypes.string,
/**
* 标签tagName
* @property componentTag
* @type String
* */
componentTag:PropTypes.string,
/**
* 是否可见标识
* @property visible
* @type Boolean
* @default false
* */
visible: PropTypes.bool,
/**
* 点击收起展开的回调函数
* @method clickCallback
* @param {boolean} visible 当前收起展开的状态
* @type Function
* */
clickCallback: PropTypes.func,
/**
* 向下的箭头是否可见, 默认可见
* @property hideIcon
* @type Boolean
* @default false
* */
hideIcon: PropTypes.bool
};
static defaultProps = {
visible: false,
hideIcon: false,
classPrefix:'accordion',
componentTag:'div',
classMapping : {
'visible': 'visible'
}
};
constructor(props, context) {
super(props, context);
new Logger('Accordion');
this.state = {
visible: props.visible
}
}
componentWillReceiveProps(nextProps){
if(this.state.visible != nextProps.visible) this.setState({visible: nextProps.visible});
}
changeVisible(){
this.setState({
visible: !this.state.visible
}, ()=>{
if(this.props.clickCallback) this.props.clickCallback(this.state.visible);
});
}
renderChildren(){
let _this = this;
let newChildren = [];
let {hideIcon} = this.props;
React.Children.forEach(this.props.children, function(child, index){
newChildren.push(React.cloneElement(child,{
key: index,
hideIcon: hideIcon,
visible: _this.state.visible,
changeVisible: _this.changeVisible.bind(_this)
}));
});
return newChildren;
}
renderAccordion(){
let {componentTag:Component, className} = this.props;
return (
<Component {...this.otherProps} className={classnames(
this.getProperty(true),
className
)}>
{this.renderChildren()}
</Component>
)
}
render(){
return this.renderAccordion()
}
}
class AccordionHeader extends Component {
constructor(props, context){
super(props, context);
}
static defaultProps = {
classPrefix:'accordion-header',
classMapping : {}
};
clickHandle(){
let {changeVisible, onClick} = this.props
this.props.changeVisible()
if(onClick) onClick()
}
renderIcon(){
let {visible, hideIcon} = this.props;
if(!hideIcon){
return <Icon phIcon='expand-more' className={visible? 'active':''} />;
}else{
return '';
}
}
renderAccordionHeader(){
let {className} = this.props;
return (
<div {...this.otherProps} className={classnames(
this.getProperty(true),
className
)}
onClick={this.clickHandle.bind(this)}
>
{this.props.children}
{this.renderIcon()}
</div>
)
}
render(){
return this.renderAccordionHeader()
}
};
class AccordionBody extends Component{
constructor(props, context) {
super(props, context);
this.height = 0;
}
static defaultProps = {
classPrefix:'accordion-body',
classMapping : {}
};
componentDidMount(){
setTimeout(()=>{
this.height = this.accordionBody.offsetHeight+'px'
this.setHeight()
},0)
}
componentDidUpdate(){
this.setHeight();
}
setHeight(){
this.accordionBodyParent.style.height = this.props.visible ? this.height : 0
}
renderAccordionBody(){
let {children,className} = this.props;
return (
<div {...this.otherProps} className={classnames(
this.getProperty(true),
'animated',
className
)} ref={(accordionBodyParent)=>{this.accordionBodyParent = accordionBodyParent}}>
<div ref={(accordionBody)=>{this.accordionBody = accordionBody}}>
{children}
</div>
</div>
)
}
render(){
return this.renderAccordionBody()
}
}
Accordion.Header = AccordionHeader;
Accordion.Body = AccordionBody;
export default Accordion;