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

Fixes #113

Merged
merged 2 commits into from Jul 14, 2017
Merged

Fixes #113

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/CSSTransition.js
Expand Up @@ -191,7 +191,7 @@ class CSSTransition extends React.Component {
const { className } = this.getClassNames('exit')

this.removeClasses(node, 'appear');
this.removeClasses(node, 'exit');
this.removeClasses(node, 'enter');
addClass(node, className)

if (this.props.onExit) {
Expand Down
56 changes: 40 additions & 16 deletions src/Transition.js
Expand Up @@ -13,7 +13,7 @@ export const EXITING = 'exiting';
/**
* The Transition component lets you describe a transition from one component
* state to another _over time_ with a simple declarative API. Most commonly
* It's used to animate the mounting and unmounting of Component, but can also
* it's used to animate the mounting and unmounting of a component, but can also
* be used to describe in-place transition states as well.
*
* By default the `Transition` component does not alter the behavior of the
Expand Down Expand Up @@ -50,6 +50,22 @@ export const EXITING = 'exiting';
* );
* ```
*
* As noted the `Transition` component doesn't _do_ anything by itself to its child component.
* What it does do is track transition states over time so you can adjust you
* component (such as adding styles of classes) as it changes states.
*
* There are 4 main states a Transition can be in:
* - `ENTERING`
* - `ENTERED`
* - `EXITING`
* - `EXITED`
*
* Transition state is toggled via the `in` prop. When `true` the component begins the
* "Enter" stage. During this stage, the component will shift from its current transitions state,
* to `'entering'` for the duration of the transition and then to the `'entered'` stage once
* it's complete. So in the following example: `<Transition in timeout={500} />`,
* the component will immediately shift to `'entering'` and stay there for 500ms and switch to `'entered'`.
* When `in` is `false` the same thing happens except the states are `'exiting'` to `'exited'`.
*/
class Transition extends React.Component {
static contextTypes = {
Expand Down Expand Up @@ -280,10 +296,7 @@ class Transition extends React.Component {

Transition.propTypes = {
/**
* Generally a React element to animate, all unknown props on Transition are
* transfered to the **single** child element.
*
* For advanced uses a `function` child can be used instead of a React element.
* A `function` child can be used instead of a React element.
* This function is called with the current transition status
* ('entering', 'entered', 'exiting', 'exited', 'unmounted'), which can used
* to apply context specific props to a component.
Expand All @@ -307,17 +320,25 @@ Transition.propTypes = {
in: PropTypes.bool,

/**
* Wait until the first "enter" transition to mount the component (add it to the DOM)
* By default the child component is mounted immediately along with
* the parent `Transition` component. If you want to "lazy mount" the component on the
* first `in={true}` you can set `mountOnEnter`. After the first enter transition the component will stay
* mounted even on exit unless you also specify `unmountOnExit`
*/
mountOnEnter: PropTypes.bool,

/**
* Unmount the component (remove it from the DOM) when it is not shown
* By default the child component is mounted in the DOM after it enteres the `'exited'` state.
* If you'd prefer to completely unmonut the component after it exits, set `unmountOnExit`.
*/
unmountOnExit: PropTypes.bool,

/**
* Enable or disable appear (entering on mount) transitions.
* Normally a component is not transitioned on it's initial mount. If you
* want to transition on the first mount set `appear` to `true`, and the
* component will enter the component.
*
* > Note: there are no specific "appear" states. `apprear` only an additional `enter` transition.
*/
appear: PropTypes.bool,

Expand Down Expand Up @@ -363,44 +384,47 @@ Transition.propTypes = {
addEndListener: PropTypes.func,

/**
* Callback fired before the "entering" status is applied.
* Callback fired before the "entering" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occuring on the initial mount
*
* @type Function(node: HtmlElement, isAppearing: bool)
* @type Function(node: HtmlElement, isAppearing: bool) -> void
*/
onEnter: PropTypes.func,

/**
* Callback fired after the "entering" status is applied.
* Callback fired after the "entering" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occuring on the initial mount
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
onEntering: PropTypes.func,

/**
* Callback fired after the "enter" status is applied.
* Callback fired after the "enter" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occuring on the initial mount
*
* @type Function(node: HtmlElement, isAppearing: bool)
* @type Function(node: HtmlElement, isAppearing: bool) -> void
*/
onEntered: PropTypes.func,

/**
* Callback fired before the "exiting" status is applied.
*
* @type Function(node: HtmlElement)
* @type Function(node: HtmlElement) -> void
*/
onExit: PropTypes.func,

/**
* Callback fired after the "exiting" status is applied.
*
* @type Function(node: HtmlElement)
* @type Function(node: HtmlElement) -> void
*/
onExiting: PropTypes.func,

/**
* Callback fired after the "exited" status is applied.
*
* @type Function(node: HtmlElement)
* @type Function(node: HtmlElement) -> void
*/
onExited: PropTypes.func,
};
Expand Down
34 changes: 25 additions & 9 deletions src/TransitionGroup.js
Expand Up @@ -37,10 +37,23 @@ const propTypes = {
* on individual children Transitions.
*/
exit: PropTypes.bool,

/**
* You may need to apply reactive updates to a child as it is exiting.
* This is generally done by using `cloneElement` however in the case of an exiting
* child the element has already been removed and not accessible to the consumer.
*
* If you do need to update a child as it leaves you can provide a `childFactory`
* to wrap every child, even the ones that are leaving.
*
* @type Function(child: ReactElement) -> ReactElement
*/
childFactory: PropTypes.func,
};

const defaultProps = {
component: 'div',
childFactory: child => child,
};

/**
Expand Down Expand Up @@ -111,11 +124,8 @@ class TransitionGroup extends React.Component {
// Initial children should all be entering, dependent on appear
this.state = {
children: getChildMapping(props.children, child => {
const onExited = () => {
if (child.props.onExited)
child.props.onExited();

this.handleExited(child.key);
const onExited = (node) => {
this.handleExited(child.key, node, child.props.onExited);
}

return cloneElement(child, {
Expand Down Expand Up @@ -156,7 +166,9 @@ class TransitionGroup extends React.Component {

if (!isValidElement(child)) return;

const onExited = () => this.handleExited(key);
const onExited = (node) => {
this.handleExited(child.key, node, child.props.onExited);
}

const hasPrev = key in prevChildMapping;
const hasNext = key in nextChildMapping;
Expand Down Expand Up @@ -195,20 +207,24 @@ class TransitionGroup extends React.Component {
this.setState({ children });
}

handleExited = (key) => {
handleExited = (key, node, originalHandler) => {
let currentChildMapping = getChildMapping(this.props.children);

if (key in currentChildMapping) return

if (originalHandler)
originalHandler(node)

this.setState((state) => {
let children = { ...state.children };

delete children[key];
return { children };
});
};

render() {
const { component: Component, ...props } = this.props;
const { component: Component, childFactory, ...props } = this.props;
const { children } = this.state;

delete props.appear;
Expand All @@ -217,7 +233,7 @@ class TransitionGroup extends React.Component {

return (
<Component {...props}>
{values(children)}
{values(children).map(childFactory)}
</Component>
);
}
Expand Down
15 changes: 7 additions & 8 deletions www/package.json
Expand Up @@ -13,14 +13,13 @@
"license": "MIT",
"dependencies": {
"bootstrap": "^4.0.0-alpha.6",
"gatsby": "^1.0.0-beta.7",
"gatsby-link": "^1.0.0-beta.6",
"gatsby-plugin-sass": "^1.0.0-beta.1",
"gatsby-remark-prismjs": "^1.0.0-beta.6",
"gatsby-source-filesystem": "^1.0.0-beta.6",
"gatsby-transformer-react-docgen": "^1.0.0-beta.6",
"gatsby-transformer-remark": "^1.0.0-beta.6",
"graphql-type-json": "^0.1.4",
"gatsby": "^1.0.0",
"gatsby-link": "^1.0.0",
"gatsby-plugin-sass": "^1.0.0",
"gatsby-remark-prismjs": "^1.0.0",
"gatsby-source-filesystem": "^1.0.0",
"gatsby-transformer-react-docgen": "^1.0.0",
"gatsby-transformer-remark": "^1.0.0",
"lodash": "^4.17.4"
},
"devDependencies": {
Expand Down