Skip to content

Commit

Permalink
fun children
Browse files Browse the repository at this point in the history
  • Loading branch information
jquense committed Apr 19, 2017
1 parent 1326f11 commit 78a2cfe
Show file tree
Hide file tree
Showing 6 changed files with 1,867 additions and 154 deletions.
34 changes: 20 additions & 14 deletions src/Transition.js
@@ -1,3 +1,4 @@
import * as PropTypes from 'prop-types';
import React from 'react';
import ReactDOM from 'react-dom';

Expand All @@ -20,7 +21,7 @@ export const EXITING = 4;
*/
class Transition extends React.Component {
static contextTypes = {
transitionGroup: React.PropTypes.object,
transitionGroup: PropTypes.object,
};
static childContextTypes = {
transitionGroup: ()=>{},
Expand Down Expand Up @@ -236,34 +237,39 @@ class Transition extends React.Component {
if (typeof children === 'function') {
return children(status, childProps)
}

const child = React.Children.only(children);
return React.cloneElement(child, childProps);
}
}

Transition.propTypes = {
children: PropTypes.oneOfType([
PropTypes.func.isRequired,
PropTypes.element.isRequired,
]).isRequired,
/**
* Show the component; triggers the enter or exit animation
*/
in: React.PropTypes.bool,
in: PropTypes.bool,

/**
* Wait until the first "enter" transition to mount the component (add it to the DOM)
*/
mountOnEnter: React.PropTypes.bool,
mountOnEnter: PropTypes.bool,

/**
* Unmount the component (remove it from the DOM) when it is not shown
*/
unmountOnExit: React.PropTypes.bool,
unmountOnExit: PropTypes.bool,

/**
* Run the enter animation when the component mounts, if it is initially
* shown
*/
appear: React.PropTypes.bool,
enter: React.PropTypes.bool,
exit: React.PropTypes.bool,
appear: PropTypes.bool,
enter: PropTypes.bool,
exit: PropTypes.bool,

/**
* A Timeout for the animation, in milliseconds, to ensure that a node doesn't
Expand All @@ -285,31 +291,31 @@ Transition.propTypes = {
* node.addEventListener('transitionend', done, false);
* }}
*/
addEndListener: React.PropTypes.func,
addEndListener: PropTypes.func,
/**
* Callback fired before the "entering" classes are applied
*/
onEnter: React.PropTypes.func,
onEnter: PropTypes.func,
/**
* Callback fired after the "entering" classes are applied
*/
onEntering: React.PropTypes.func,
onEntering: PropTypes.func,
/**
* Callback fired after the "enter" classes are applied
*/
onEntered: React.PropTypes.func,
onEntered: PropTypes.func,
/**
* Callback fired before the "exiting" classes are applied
*/
onExit: React.PropTypes.func,
onExit: PropTypes.func,
/**
* Callback fired after the "exiting" classes are applied
*/
onExiting: React.PropTypes.func,
onExiting: PropTypes.func,
/**
* Callback fired after the "exited" classes are applied
*/
onExited: React.PropTypes.func,
onExited: PropTypes.func,
};

// Name the function so it is clearer in the documentation
Expand Down
2 changes: 2 additions & 0 deletions src/TransitionGroup.js
Expand Up @@ -99,6 +99,8 @@ class TransitionGroup extends React.Component {
children[key] = cloneElement(child, {
onExited,
in: prevChild.props.in,
exit: this.getProp(child, 'exit', nextProps),
enter: this.getProp(child, 'enter', nextProps),
});
}
})
Expand Down
45 changes: 29 additions & 16 deletions stories/Transition.js
Expand Up @@ -2,10 +2,11 @@ import React from 'react';
import style from 'dom-helpers/style';
import { storiesOf } from '@kadira/storybook';

import Transition from '../src/Transition';
import Transition, { EXITED, ENTERED, ENTERING, EXITING } from '../src/Transition';
import CSSTransition from '../src/CSSTransition';
import StoryFixture from './StoryFixture';


const _ = css`
.fade {
opacity: 0;
Expand All @@ -24,18 +25,27 @@ const _ = css`
position: relative;
height: 0;
overflow: hidden;
transition: height, visibility .35s ease;
transition: .35s ease;
transition-property: height, visibility;
}
`;


const fadeStyles = {
[ENTERING]: 'in',
[ENTERED]: 'in',
}

const Fade = props => (
<Transition
{...props}
className="fade"
timeout={150}
onEntering={node => node.classList.add('in')}
onExit={node => node.classList.remove('in')}
/>
>
{status => React.cloneElement(props.children, {
className: `fade ${fadeStyles[status] || ''}`
})}
</Transition>
)

function getHeight(elem) {
Expand All @@ -49,20 +59,24 @@ function getHeight(elem) {
}


const collapseStyles = {
[EXITED]: 'collapse',
[EXITING]: 'collapsing',
[ENTERING]: 'collapsing',
[ENTERED]: 'collapse in',
}

class Collapse extends React.Component {
/* -- Expanding -- */
handleEnter = (elem) => {
elem.style.height = '0';
}

handleEntering = (elem) => {
elem.classList.add('collapsing')
elem.style.height = `${elem.scrollHeight}px`;
}

handleEntered = (elem) => {
elem.classList.remove('collapsing')
elem.classList.add('collapse', 'in')
elem.style.height = null;
}

Expand All @@ -73,27 +87,26 @@ class Collapse extends React.Component {
}

handleExiting = (elem) => {
elem.classList.add('collapsing')
elem.style.height = '0';
}

handleExited = (elem) => {
elem.classList.remove('collapsing')
}

render() {
const { children } = this.props;
return (
<Transition
{...this.props}
timeout={350}
className="collapse"
onEnter={this.handleEnter}
onEntering={this.handleEntering}
onEntered={this.handleEntered}
onExit={this.handleExit}
onExiting={this.handleExiting}
onExited={this.handleExited}
/>
>
{(state, props) => React.cloneElement(children, {
...props,
className: collapseStyles[state]
})}
</Transition>
);
}
}
Expand Down
6 changes: 4 additions & 2 deletions stories/TransitionGroup.js
Expand Up @@ -55,6 +55,8 @@ storiesOf('Css Transition Group', module)
Should animate when items are added to the list but not when they are
removed or on initial appear
`}
appear
items={[ 'Item number: 1' ]}
>
<Fade />
</CSSTransitionGroupFixture>
Expand All @@ -65,11 +67,11 @@ storiesOf('Css Transition Group', module)
Should animate when items are added to the list but not when they are
removed or on initial appear
`}

exit={false}
timeout={{ enter: FADE_TIMEOUT }}
items={[ 'Item number: 1' ]}
>
<Fade exit={false} />
<Fade />
</CSSTransitionGroupFixture>
))
.add('Animates on exit', () => (
Expand Down
22 changes: 0 additions & 22 deletions test/TransitionGroup-test.js
Expand Up @@ -17,28 +17,6 @@ describe.only('TransitionGroup', () => {
container = document.createElement('div');
});

it('should warn when string refs are used', () => {
class Child extends React.Component {
render() {
return <span />;
}
}

spyOn(console, 'error');

tsp(
<TransitionGroup>
<Child ref="string" />
</TransitionGroup>,
)
.render();

expect(console.error).toHaveBeenCalled();
expect(console.error.calls.mostRecent().args[0]).toMatch(
/string refs are not supported on children of TransitionGroup and will be ignored/,
);
});

it('should allow null components', () => {
function FirstChild(props) {
const childrenArray = React.Children.toArray(props.children);
Expand Down

0 comments on commit 78a2cfe

Please sign in to comment.