accounts-frontend/src/components/ui/motion/SlideMotion.js

83 lines
2.6 KiB
JavaScript
Raw Normal View History

2017-07-22 21:27:38 +05:30
// @flow
import React, { Component } from 'react';
import { Motion, spring } from 'react-motion';
import MeasureHeight from 'components/MeasureHeight';
2017-11-19 23:46:15 +05:30
import styles from './slide-motion.scss';
2017-07-22 21:27:38 +05:30
2017-11-19 23:46:15 +05:30
export default class SlideMotion extends Component<{
2017-08-23 02:01:41 +05:30
activeStep: number,
children: *
}, {
version: number
}> {
2017-07-22 21:27:38 +05:30
state: {
version: number
} = {
version: 0
};
isHeightMeasured: bool;
componentWillReceiveProps() {
// mark this view as dirty to re-measure height
this.setState({
version: this.state.version + 1
});
}
render() {
const {
activeStep,
children
} = this.props;
const {version} = this.state;
const activeStepHeight = this.state[`step${activeStep}Height`] || 0;
// a hack to disable height animation on first render
const isHeightMeasured = this.isHeightMeasured;
this.isHeightMeasured = isHeightMeasured || activeStepHeight > 0;
const motionStyle = {
transform: spring(activeStep * 100, {stiffness: 500, damping: 50, precision: 0.5}),
height: isHeightMeasured ? spring(activeStepHeight, {stiffness: 500, damping: 20, precision: 0.5}) : activeStepHeight
};
return (
<Motion style={motionStyle}>
{(interpolatingStyle: {height: number, transform: string}) => (
<div style={{
overflow: 'hidden',
height: `${interpolatingStyle.height}px`
}}>
<div className={styles.container} style={{
WebkitTransform: `translateX(-${interpolatingStyle.transform}%)`,
transform: `translateX(-${interpolatingStyle.transform}%)`
}}>
{React.Children.map(children, (child, index) => (
<MeasureHeight
className={styles.item}
onMeasure={this.onStepMeasure(index)}
state={version}
key={index}
>
{child}
</MeasureHeight>
))}
</div>
</div>
)}
</Motion>
);
}
onStepMeasure(step: number) {
return (height: number) => this.setState({
[`step${step}Height`]: height
});
}
}