123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- import { cloneElement, Component, toChildArray } from 'preact'
- import classNames from 'classnames'
- const transitionName = 'uppy-transition-slideDownUp'
- const duration = 250
- /**
- * Vertical slide transition.
- *
- * This can take a _single_ child component, which _must_ accept a `className` prop.
- *
- * Currently this is specific to the `uppy-transition-slideDownUp` transition,
- * but it should be simple to extend this for any type of single-element
- * transition by setting the CSS name and duration as props.
- */
- class Slide extends Component {
- constructor (props) {
- super(props)
- this.state = {
- cachedChildren: null,
- className: '',
- }
- }
- // TODO: refactor to stable lifecycle method
- // eslint-disable-next-line
- componentWillUpdate (nextProps) {
- const { cachedChildren } = this.state
- const child = toChildArray(nextProps.children)[0]
- if (cachedChildren === child) return null
- const patch = {
- cachedChildren: child,
- }
- // Enter transition
- if (child && !cachedChildren) {
- patch.className = `${transitionName}-enter`
- cancelAnimationFrame(this.animationFrame)
- clearTimeout(this.leaveTimeout)
- this.leaveTimeout = undefined
- this.animationFrame = requestAnimationFrame(() => {
- // Force it to render before we add the active class
- // this.base.getBoundingClientRect()
- this.setState({
- className: `${transitionName}-enter ${transitionName}-enter-active`,
- })
- this.enterTimeout = setTimeout(() => {
- this.setState({ className: '' })
- }, duration)
- })
- }
- // Leave transition
- if (cachedChildren && !child && this.leaveTimeout === undefined) {
- patch.cachedChildren = cachedChildren
- patch.className = `${transitionName}-leave`
- cancelAnimationFrame(this.animationFrame)
- clearTimeout(this.enterTimeout)
- this.enterTimeout = undefined
- this.animationFrame = requestAnimationFrame(() => {
- this.setState({
- className: `${transitionName}-leave ${transitionName}-leave-active`,
- })
- this.leaveTimeout = setTimeout(() => {
- this.setState({
- cachedChildren: null,
- className: '',
- })
- }, duration)
- })
- }
- // eslint-disable-next-line
- this.setState(patch)
- }
- render () {
- const { cachedChildren, className } = this.state
- if (!cachedChildren) {
- return null
- }
- return cloneElement(cachedChildren, {
- className: classNames(className, cachedChildren.props.className),
- })
- }
- }
- export default Slide
|