Last active
November 22, 2018 18:13
-
-
Save tkh44/8db9f056451f2b81b54d73e4890c7bf3 to your computer and use it in GitHub Desktop.
Helper for react motion to stagger animation mounting with TransitionMotion component. Props to https://github.com/maisano/react-router-transition for the idea
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createElement, cloneElement, Children } from 'react'; | |
import { TransitionMotion, spring, presets } from 'react-motion'; | |
import compose from 'recompose/compose'; | |
import defaultProps from 'recompose/defaultProps'; | |
import withHandlers from 'recompose/withHandlers'; | |
import toClass from 'recompose/toClass'; | |
const TransitionGroup = compose( | |
defaultProps({ | |
component: 'div', | |
className: '', | |
style: {}, | |
leaveImmediate: false, | |
stagger: false, | |
atEnter: { | |
scale: 0.8, | |
opacity: 0 | |
}, | |
atLeave: { | |
scale: spring(0.8, { stiffness: 360, damping: 25 }), | |
opacity: spring(0, { stiffness: 360, damping: 25 }) | |
}, | |
atActive: { | |
scale: spring(1, { stiffness: 360, damping: 25 }), | |
opacity: 1 | |
}, | |
mapStyles(styles) { | |
return { | |
opacity: styles.opacity, | |
transform: `scale(${styles.scale})` | |
}; | |
} | |
}), | |
withHandlers({ | |
getDefaultStyles: ({ children, atEnter }) => { | |
return () => { | |
if (!children) { | |
return []; | |
} | |
return Children.toArray(children).filter(Boolean).map((child, i) => { | |
return { | |
key: child.key || i, | |
data: child, | |
style: atEnter | |
}; | |
}); | |
}; | |
}, | |
getStyles: ({ children, atActive, stagger }) => { | |
return () => { | |
if (!children) { | |
return []; | |
} | |
if (stagger) { | |
return (prevStyles) => { | |
return Children.map(children, (child, i) => { | |
if (!child) { | |
return; | |
} | |
if (i === 0 || !prevStyles[i - 1]) { | |
return { | |
key: child.key || i, | |
data: child, | |
style: atActive | |
}; | |
} | |
return { | |
key: child.key, | |
data: child, | |
style: prevStyles[i - 1].style | |
}; | |
}); | |
}; | |
} | |
return Children.map(children, (child, i) => { | |
if (!child) { | |
return; | |
} | |
return { | |
key: child.key || i, | |
data: child, | |
style: atActive | |
}; | |
}); | |
}; | |
}, | |
willEnter: ({ atEnter }) => () => atEnter, | |
willLeave: ({ atLeave, leaveImmediate }) => { | |
return () => { | |
if (leaveImmediate) { | |
return null; | |
} | |
return atLeave; | |
}; | |
} | |
}), | |
toClass | |
)(({ component, className, style, getDefaultStyles, getStyles, willEnter, willLeave, mapStyles }) => { | |
return createElement( | |
TransitionMotion, | |
{ | |
defaultStyles: getDefaultStyles(), | |
styles: getStyles(), | |
willEnter, | |
willLeave, | |
children: (interpolatedStyles) => { | |
return createElement( | |
component, | |
{ | |
className, | |
style, | |
children: interpolatedStyles.map((config) => { | |
return cloneElement( | |
config.data, | |
{ | |
key: config.key, | |
style: mapStyles(config.style) | |
} | |
); | |
}) | |
} | |
); | |
} | |
} | |
); | |
}); | |
export default TransitionGroup; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment