src/components/Transitions/Slide.js
import React, { PureComponent } from 'react'
import Transition from 'react-transition-group/Transition'
import PropTypes from 'prop-types'
const TIMEOUT = 0
const TRASITION_TIME = 200
const OFFSET = 200
const TIMING_FUNCTION = 'ease-in-out'
const AXIS = 'x'
class Slide extends PureComponent {
static propTypes = {
/**
* A convenience prop that enables or disabled appear animations for
* all children. Note that specifying this will override any defaults
* set on individual children Transitions.
*/
appear: PropTypes.bool,
/** Axis that is animated */
axis: PropTypes.oneOf(['x', 'y']),
children: PropTypes.node,
/** Optional style overrides for div that is offset and contains children. */
containerStyle: PropTypes.object,
/** Show the component; triggers the enter or exit states */
in: PropTypes.bool,
/** Inverts offset direction, e.g. changes animation direction from right to left */
invert: PropTypes.bool,
/**
* Number of pixels to offset the children. To have the children completely hidden
* prior to animation, offset should equal the width of the widest child.
*/
offset: PropTypes.number,
/** Optional style overrides. */
style: PropTypes.object,
/** Delay in milliseconds until animation start. */
timeout: PropTypes.number,
/** Name of the transition-timing-function CSS property. */
timingFunction: PropTypes.oneOf(['ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear']),
/** Time of animation in milliseconds. */
transitionTime: PropTypes.number,
}
static defaultProps = {
timeout: TIMEOUT,
transitionTime: TRASITION_TIME,
timingFunction: TIMING_FUNCTION,
offset: OFFSET,
axis: AXIS,
style: {},
in: true,
appear: true,
invert: false,
}
get transformAxis() {
return this.props.axis === 'x' ? 'translateX' : 'translateY'
}
get transitionStyles() {
const { offset, invert } = this.props
const offsetDirection = invert ? '-' : ''
return {
entering: {
transform: `${this.transformAxis}(${offsetDirection}${offset}px)`,
},
entered: {
transform: `${this.transformAxis}(0)`,
},
}
}
get initialStyles() {
const { transitionTime, timingFunction, offset, invert } = this.props
const offsetDirection = invert ? '' : '-'
return {
transform: `${this.transformAxis}(${offsetDirection}${offset}px)`,
transition: `all ${transitionTime}ms ${timingFunction}`,
}
}
renderChild = state => {
const { style, children, containerStyle } = this.props
const styles = {
...this.initialStyles,
...this.transitionStyles[state],
...containerStyle,
}
const topLevelStyle = {
overflowY: 'hidden',
overflowX: 'visible',
...style,
}
return (
<div style={topLevelStyle}>
<div style={styles}>{children}</div>
</div>
)
}
render() {
const { in: inProp, timeout, appear } = this.props
return (
<Transition in={inProp} appear={appear} timeout={timeout}>
{this.renderChild}
</Transition>
)
}
}
export default Slide