react-biz
Version:
React components for Business
107 lines (91 loc) • 2.81 kB
JavaScript
import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';
import transitions from '../styles/transitions';
const reflow = (elem) => elem.offsetHeight;
class ExpandTransitionChild extends Component {
static propTypes = {
children: PropTypes.node,
enterDelay: PropTypes.number,
style: PropTypes.object,
transitionDelay: PropTypes.number,
transitionDuration: PropTypes.number
};
static defaultProps = {
enterDelay: 0,
transitionDelay: 0,
transitionDuration: 450
};
componentWillUnmount () {
clearTimeout(this.enterTimer);
clearTimeout(this.enteredTimer);
clearTimeout(this.leaveTimer);
}
componentWillAppear (callback) {
this.open();
callback();
}
componentDidAppear () {
this.setAutoHeight();
}
componentWillEnter (callback) {
const {enterDelay, transitionDelay, transitionDuration} = this.props;
const element = ReactDOM.findDOMNode(this);
element.style.height = 0;
this.enterTimer = setTimeout(() => this.open(), enterDelay);
this.enteredTimer = setTimeout(
() => callback(),
enterDelay + transitionDelay + transitionDuration
);
}
componentDidEnter () {
this.setAutoHeight();
}
componentWillLeave (callback) {
const {transitionDelay, transitionDuration} = this.props;
const element = ReactDOM.findDOMNode(this);
// Set fixed height first for animated property value
element.style.height = `${this.refs.wrapper.clientHeight}px`;
reflow(element);
element.style.transitionDuration = `${transitionDuration}ms`;
element.style.height = 0;
this.leaveTimer = setTimeout(() => callback(), transitionDelay + transitionDuration);
}
setAutoHeight () {
const {style} = ReactDOM.findDOMNode(this);
style.transitionDuration = 0;
style.height = 'auto';
}
open () {
const element = ReactDOM.findDOMNode(this);
element.style.height = `${this.refs.wrapper.clientHeight}px`;
}
render () {
const {
children,
enterDelay, // eslint-disable-line no-unused-vars
style,
transitionDelay, // eslint-disable-line no-unused-vars
transitionDuration,
...other
} = this.props;
const mergedRootStyles = Object.assign({
position: 'relative',
height: 0,
width: '100%',
top: 0,
left: 0,
overflow: 'hidden',
transition: transitions.easeOut(
`${transitionDuration}ms`,
['height'],
`${transitionDelay}ms`
)
}, style);
return (
<div {...other} style={mergedRootStyles}>
<div ref="wrapper">{children}</div>
</div>
);
}
}
export default ExpandTransitionChild;