UNPKG

react-stonecutter

Version:
139 lines (119 loc) 3.78 kB
import React from 'react'; import { TransitionMotion, spring } from 'react-motion'; import stripStyle from 'react-motion/lib/stripStyle'; import { buildTransform, positionToProperties } from '../utils/transformHelpers'; import isEqual from 'lodash.isequal'; import { commonPropTypes, commonDefaultProps } from '../utils/commonProps'; export default React.createClass({ propTypes: { ...commonPropTypes, springConfig: React.PropTypes.shape({ stiffness: React.PropTypes.number, damping: React.PropTypes.number, precision: React.PropTypes.number }) }, getDefaultProps() { return { ...commonDefaultProps, springConfig: { stiffness: 60, damping: 14, precision: 0.1 } }; }, componentWillMount() { this.setState(this.doLayout(this.props)); }, componentWillReceiveProps(nextProps) { if (!isEqual(nextProps, this.props)) { this.setState(this.doLayout(nextProps)); } }, doLayout(props) { const items = React.Children.toArray(props.children) .map(element => ({ key: element.key, data: { element } })); const { positions, gridWidth, gridHeight } = props.layout(items.map(item => ({ ...item.data.element.props, key: item.data.element.key })), props); const styles = positions.map((position, i) => ({ ...items[i], style: { ...items[i].style, zIndex: 2, ...springify(props.entered(items[i].data.element.props, props, { gridWidth, gridHeight }), props.springConfig), ...springify(positionToProperties(position), props.springConfig) } })); return { styles, gridWidth, gridHeight }; }, willEnter(transitionStyle) { const { gridWidth, gridHeight } = this.state; return { ...stripStyle(transitionStyle.style), zIndex: 1, ...this.props.enter(transitionStyle.data.element.props, this.props, { gridWidth, gridHeight }) }; }, willLeave(transitionStyle) { const { gridWidth, gridHeight } = this.state; const exitStyle = this.props.exit(transitionStyle.data.element.props, this.props, { gridWidth, gridHeight }); return { ...transitionStyle.style, zIndex: 0, ...springify(exitStyle, this.props.springConfig) }; }, render() { const { component, style, perspective, lengthUnit, angleUnit, ...rest } = this.props; return ( <TransitionMotion styles={this.state.styles} willEnter={this.willEnter} willLeave={this.willLeave} > {interpolatedStyles => React.createElement(component, { style: { position: 'relative', ...style, width: `${this.state.gridWidth}${lengthUnit}`, height: `${this.state.gridHeight}${lengthUnit}` }, ...rest }, interpolatedStyles.map(config => { const { style: { opacity, zIndex }, data } = config; const transform = buildTransform(config.style, perspective, { length: lengthUnit, angle: angleUnit }); return React.cloneElement(data.element, { style: { ...data.element.props.style, position: 'absolute', top: 0, left: 0, zIndex, opacity, transform, WebkitTransform: transform, msTransform: transform } }); }))} </TransitionMotion> ); } }); function springify(style, springConfig) { return Object.keys(style).reduce((obj, key) => { obj[key] = spring(style[key], springConfig); return obj; }, {}); }