Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add done argument to onEntering and onExiting #331

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"@semantic-release/npm": "^3.2.4",
"@storybook/addon-actions": "^3.2.11",
"@storybook/react": "^3.2.11",
"animejs": "^2.2.0",
"babel-cli": "^6.24.0",
"babel-core": "^6.24.0",
"babel-eslint": "^7.1.1",
Expand Down
36 changes: 18 additions & 18 deletions src/Transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ class Transition extends React.Component {

const timeouts = this.getTimeouts();

const setEntered = () => {
this.safeSetState({ status: ENTERED }, () => {
this.props.onEntered(node, appearing)
})
}

// no enter animation skip right to ENTERED
// if we are mounting and running this it means appear _must_ be set
if (!mounting && !enter) {
Expand All @@ -238,38 +244,34 @@ class Transition extends React.Component {
this.props.onEnter(node, appearing);

this.safeSetState({ status: ENTERING }, () => {
this.props.onEntering(node, appearing);
this.props.onEntering(node, appearing, setEntered);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

won't e.g. onEntered get called twice if the user both manually triggers the transition end and the timeout fires? i think, then, that this should hook into that weird "next callback" mechanism. i wish i clearly remembered how that actually worked well enough to give you a real suggestion on implementation, though


// FIXME: appear timeout?
this.onTransitionEnd(node, timeouts.enter, () => {
this.safeSetState({ status: ENTERED }, () => {
this.props.onEntered(node, appearing);
});
});
this.onTransitionEnd(node, timeouts.enter, setEntered);
});
}

performExit(node) {
const { exit } = this.props;
const timeouts = this.getTimeouts();

const setExited = () => {
this.safeSetState({ status: EXITED }, () => {
this.props.onExited(node)
})
}

// no exit animation skip right to EXITED
if (!exit) {
this.safeSetState({ status: EXITED }, () => {
this.props.onExited(node);
});
setExited()
return;
}
this.props.onExit(node);

this.safeSetState({ status: EXITING }, () => {
this.props.onExiting(node);
this.props.onExiting(node, setExited);

this.onTransitionEnd(node, timeouts.exit, () => {
this.safeSetState({ status: EXITED }, () => {
this.props.onExited(node);
});
});
this.onTransitionEnd(node, timeouts.exit, setExited);
});
}

Expand Down Expand Up @@ -437,9 +439,7 @@ Transition.propTypes = {
* @type {number | { enter?: number, exit?: number }}
*/
timeout: (props, ...args) => {
let pt = timeoutsShape
if (!props.addEndListener) pt = pt.isRequired
return pt(props, ...args);
return timeoutsShape(props, ...args);
},

/**
Expand Down
7 changes: 7 additions & 0 deletions stories/Transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { storiesOf } from '@storybook/react';

import { Fade, Collapse } from './transitions/Bootstrap'
import JavascriptTransition from './transitions/JavaScriptTransition';
import StoryFixture from './StoryFixture';


Expand Down Expand Up @@ -45,4 +46,10 @@ storiesOf('Transition', module)
</div>
</Collapse>
</ToggleFixture>
))
.add('Javascript Transition', () => (
<ToggleFixture>
<JavascriptTransition />
</ToggleFixture>
));

72 changes: 72 additions & 0 deletions stories/transitions/JavaScriptTransition.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react'
import anime from 'animejs'
import Transition from '../../src/Transition'

const styles = css`
.box {
width: 5rem;
height: 5rem;
background-color: #ec515c;
}

.container {
padding: 1rem;
}
`

let currentAnimation
const cancelCurrentAnimation = () => currentAnimation && currentAnimation.pause()

const animateBoxIn = (box, appearing, complete) => {
cancelCurrentAnimation()
const duration = 500 + Math.floor(Math.random() * 1000)
currentAnimation = anime({
targets: box,
translateX: [-100, 0],
opacity: {
value: [0, 1],
easing: 'linear'
},
rotate: '1turn',
complete,
duration
})
}

const animateBoxOut = (box, complete) => {
cancelCurrentAnimation()
const duration = 500 + Math.floor(Math.random() * 1000)
currentAnimation = anime({
targets: box,
translateX: [0, 100],
opacity: {
value: 0,
easing: 'linear'
},
rotate: '2turn',
complete,
duration
})
}

const onEntered = () => console.log('entered')
const onExited = () => console.log('exited')

function JavascriptTransition({ in: visible }) {
return (
<div className={styles.container}>
<Transition
in={visible}
unmountOnExit
onEntering={animateBoxIn}
onExiting={animateBoxOut}
onEntered={onEntered}
onExited={onExited}
>
<div className={styles.box} />
</Transition>
</div>
)
}

export default JavascriptTransition
45 changes: 45 additions & 0 deletions test/Transition-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,51 @@ describe('Transition', () => {
inst.setProps({ 'in': true });
})

it('should pass in a callback to onEntering to switch state to "entered"', done => {
let cachedStatus
const inst = mount(
<Transition
onEntering={(node, appearing, setEntered) => {
expect(cachedStatus).toEqual('entering')
setEntered()
setTimeout(()=>{
expect(cachedStatus).toEqual('entered')
done()
}, 0)
}}
>
{(status) => {
cachedStatus = status
return null
}}
</Transition>
)
inst.setProps({ 'in': true });
})

it('should pass in a callback to onExiting to switch state to "exited"', done => {
let cachedStatus
const inst = mount(
<Transition
onExiting={(node, setExited) => {
expect(cachedStatus).toEqual('exiting')
setExited()
setTimeout(()=>{
expect(cachedStatus).toEqual('exited')
done()
}, 0)
}}
>
{(status) => {
cachedStatus = status
return null
}}
</Transition>
)
inst.setProps({ 'in': true });
inst.setProps({ 'in': false });
})

it('should fallback to timeous with addEndListener ', done => {
let calledEnd = false
let listener = (node, end) => setTimeout(() => {
Expand Down
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,10 @@ amdefine@>=0.0.4:
version "1.0.1"
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"

animejs@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/animejs/-/animejs-2.2.0.tgz#35eefdfc535b81949c9cb06f0b3e60c02e6fdc80"

ansi-align@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
Expand Down