@appearhere/bloom
Version:
Appear Here's pattern library and styleguide
109 lines (91 loc) • 2.73 kB
JavaScript
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { TransitionMotion, spring } from 'react-motion';
import noop from '../../utils/noop';
import css from './SiblingTransition.css';
import { SIBLING_TRANSITION as DEFAULT_SPRING_CONFIG } from '../../constants/springs';
export default class SiblingTransition extends Component {
static propTypes = {
springConfig: PropTypes.shape({
stiffness: PropTypes.number,
damping: PropTypes.number,
}),
animate: PropTypes.bool,
route: PropTypes.string.isRequired,
children: PropTypes.element,
shouldAnimateLeft: PropTypes.func,
didLeave: PropTypes.func,
};
static defaultProps = {
springConfig: DEFAULT_SPRING_CONFIG,
didLeave: noop,
};
componentWillReceiveProps(nextProps) {
const { route: oldRoute } = this.props;
const { route: newRoute, animate } = nextProps;
if (!animate) this.setState({ newRoute: null, oldRoute: null });
if (newRoute !== oldRoute) this.setState({ newRoute, oldRoute });
}
getStyles = () => {
const { springConfig } = this.props;
return {
x: spring(0, springConfig),
};
}
willEnter = () => {
const { shouldAnimateLeft, animate } = this.props;
const { newRoute, oldRoute } = this.state;
if (!animate) return { x: 0 };
const transitionLeft = shouldAnimateLeft(newRoute, oldRoute);
return {
x: transitionLeft ? 100 : -100,
};
}
willLeave = () => {
const { springConfig, animate, shouldAnimateLeft } = this.props;
const { newRoute, oldRoute } = this.state;
if (!animate) return { x: 0 };
const transitionLeft = shouldAnimateLeft(newRoute, oldRoute);
return {
x: spring(transitionLeft ? -100 : 100, springConfig),
};
}
render() {
const {
route,
children: child,
didLeave,
...rest,
} = this.props;
return (
<TransitionMotion
{ ...rest }
styles={ [{
key: route,
style: this.getStyles(),
data: child,
}] }
willEnter={ this.willEnter }
willLeave={ this.willLeave }
didLeave={ didLeave }
>
{ interpolated => (
<div className={ css.container }>
{ interpolated.map(({ key, data, style }) => (
<div
key={ key }
className={ css.animated }
style={ {
position: style.x === 0 ? 'relative' : 'absolute',
transform: `translate3d(${style.x}%, 0, 0)`,
} }
>
{ data }
</div>
)) }
</div>
) }
</TransitionMotion>
);
}
}