Skip to content

Commit

Permalink
[fixed] Only calculate overlay position on display
Browse files Browse the repository at this point in the history
  • Loading branch information
Jimmy Jia committed Jul 20, 2015
1 parent 45909a2 commit c837d8d
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 382 deletions.
72 changes: 35 additions & 37 deletions src/Collapse.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,84 +115,82 @@ class Collapse extends React.Component {

Collapse.propTypes = {
/**
* Collapse the Component in or out.
* Whether the component is entered; triggers the enter or exit animation
*/
in: React.PropTypes.bool,
in: React.PropTypes.bool,

/**
* Provide the duration of the animation in milliseconds, used to ensure that finishing callbacks are fired even if the
* original browser transition end events are canceled.
* Whether the component should be unmounted (removed from DOM) when exited
*/
duration: React.PropTypes.number,
unmountOnExit: React.PropTypes.bool,

/**
* Specifies the dimension used when collapsing.
*
* _Note: Bootstrap only partially supports 'width'!
* You will need to supply your own css animation for the `.width` css class._
* Whether transition in should run when the Transition component mounts, if
* the component is initially entered
*/
dimension: React.PropTypes.oneOfType([
React.PropTypes.oneOf(['height', 'width']),
React.PropTypes.func
]),
transitionAppear: React.PropTypes.bool,

/**
* A function that returns the height or width of the animating DOM node. Allows for providing some custom logic how much
* Collapse component should animate in its specified dimension.
*
* `getDimensionValue` is called with the current dimension prop value and the DOM node.
* Duration of the animation in milliseconds, to ensure that finishing
* callbacks are fired even if the original browser transition end events are
* canceled
*/
getDimensionValue: React.PropTypes.func,
duration: React.PropTypes.number,

/**
* A Callback fired before the component starts to expand.
* Callback fired before the "entering" classes are applied
*/
onEnter: React.PropTypes.func,

/**
* A Callback fired immediately after the component starts to expand.
* Callback fired after the "entering" classes are applied
*/
onEntering: React.PropTypes.func,

/**
* A Callback fired after the component has expanded.
* Callback fired after the "enter" classes are applied
*/
onEntered: React.PropTypes.func,

/**
* A Callback fired before the component starts to collapse.
* Callback fired before the "exiting" classes are applied
*/
onExit: React.PropTypes.func,

/**
* A Callback fired immediately after the component starts to collapse.
* Callback fired after the "exiting" classes are applied
*/
onExiting: React.PropTypes.func,

/**
* A Callback fired after the component has collapsed.
* Callback fired after the "exited" classes are applied
*/
onExited: React.PropTypes.func,

/**
* Specify whether the transitioning component should be unmounted (removed from the DOM) once the exit animation finishes.
* The dimension used when collapsing
*
* _Note: Bootstrap only partially supports 'width'!
* You will need to supply your own CSS animation for the `.width` CSS class._
*/
unmountOnExit: React.PropTypes.bool,
dimension: React.PropTypes.oneOfType([
React.PropTypes.oneOf(['height', 'width']),
React.PropTypes.func
]),

/**
* Specify whether the component should collapse or expand when it mounts.
* Function that returns the height or width of the animating DOM node
*
* Allows for providing some custom logic for how much the Collapse component
* should animate in its specified dimension. Called with the current
* dimension prop value and the DOM node.
*/
transitionAppear: React.PropTypes.bool
getDimensionValue: React.PropTypes.func
};

Collapse.defaultProps = {
in: false,
in: false,
duration: 300,
dimension: 'height',
transitionAppear: false,
unmountOnExit: false,
transitionAppear: false,

dimension: 'height',
getDimensionValue
};

export default Collapse;

68 changes: 29 additions & 39 deletions src/Fade.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,87 +2,77 @@ import React from 'react';
import Transition from './Transition';

class Fade extends React.Component {

constructor(props, context){
super(props, context);
}

render() {
return (
<Transition
{...this.props}
in={this.props.in}
className='fade'
enteredClassName='in'
enteringClassName='in'
>
{ this.props.children }
{this.props.children}
</Transition>
);
}
}

// Explicitly copied from Transition for doc generation.

Fade.propTypes = {
/**
* Fade the Component in or out.
* Whether the component is entered; triggers the enter or exit animation
*/
in: React.PropTypes.bool,
in: React.PropTypes.bool,

/**
* Provide the duration of the animation in milliseconds, used to ensure that finishing callbacks are fired even if the
* original browser transition end events are canceled.
* Whether the component should be unmounted (removed from DOM) when exited
*/
duration: React.PropTypes.number,
unmountOnExit: React.PropTypes.bool,

/**
* A Callback fired before the component starts to fade in.
* Whether transition in should run when the Transition component mounts, if
* the component is initially entered
*/
onEnter: React.PropTypes.func,
transitionAppear: React.PropTypes.bool,

/**
* A Callback fired immediately after the component has started to faded in.
* Duration of the animation in milliseconds, to ensure that finishing
* callbacks are fired even if the original browser transition end events are
* canceled
*/
onEntering: React.PropTypes.func,
duration: React.PropTypes.number,

/**
* A Callback fired after the component has faded in.
* Callback fired before the "entering" classes are applied
*/
onEntered: React.PropTypes.func,

onEnter: React.PropTypes.func,
/**
* A Callback fired before the component starts to fade out.
* Callback fired after the "entering" classes are applied
*/
onExit: React.PropTypes.func,

onEntering: React.PropTypes.func,
/**
* A Callback fired immediately after the component has started to faded out.
* Callback fired after the "enter" classes are applied
*/
onExiting: React.PropTypes.func,

onEntered: React.PropTypes.func,
/**
* A Callback fired after the component has faded out.
* Callback fired before the "exiting" classes are applied
*/
onExited: React.PropTypes.func,


onExit: React.PropTypes.func,
/**
* Specify whether the transitioning component should be unmounted (removed from the DOM) once the exit animation finishes.
* Callback fired after the "exiting" classes are applied
*/
unmountOnExit: React.PropTypes.bool,

onExiting: React.PropTypes.func,
/**
* Specify whether the component should fade in or out when it mounts.
* Callback fired after the "exited" classes are applied
*/
transitionAppear: React.PropTypes.bool

onExited: React.PropTypes.func
};

Fade.defaultProps = {
in: false,
in: false,
duration: 300,
dimension: 'height',
transitionAppear: false,
unmountOnExit: false
unmountOnExit: false,
transitionAppear: false
};

export default Fade;
Expand Down
96 changes: 48 additions & 48 deletions src/Overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,24 @@ import CustomPropTypes from './utils/CustomPropTypes';
import Fade from './Fade';
import classNames from 'classnames';


class Overlay extends React.Component {

constructor(props, context){
constructor(props, context) {
super(props, context);

this.state = { exited: false };
this.state = {exited: !props.show};
this.onHiddenListener = this.handleHidden.bind(this);
}

componentWillReceiveProps(nextProps) {
let state = {};

if ( !nextProps.show && this.props.show ){
state.exiting = true;
}

if (nextProps.show) {
state = { exited: false, exiting: false };
this.setState({exited: false});
} else if (!nextProps.animation) {
// Otherwise let handleHidden take care of marking exited.
this.setState({exited: true});
}

this.setState(state);
}

render(){
render() {
let {
container
, containerPadding
Expand All @@ -42,56 +35,63 @@ class Overlay extends React.Component {
, animation: Transition
, ...props } = this.props;

let child = null;

if ( Transition === true ){
if (Transition === true) {
Transition = Fade;
}

if (props.show || (Transition && this.state.exiting && !this.state.exited)) {
// Don't un-render the overlay while it's transitioning out.
const mountOverlay = props.show || (Transition && !this.state.exited);

if (!mountOverlay) {
// Don't bother showing anything if we don't have to.
return null;
}

child = children;
let child = children;

// Position the child before the animation to avoid `null` DOM nodes
if (Transition) {
// This animates the child by injecting props, so it must be inner-most.
child = (
<Position {...{ container, containerPadding, target, placement }}>
{ child }
</Position>
<Transition
in={props.show}
transitionAppear
onExited={this.onHiddenListener}
>
{child}
</Transition>
);
} else {
child = cloneElement(
child,
{className: classNames('in', child.className)}
);

child = Transition
? (
<Transition
unmountOnExit
in={props.show}
transitionAppear={props.show}
onExited={this.onHiddenListener}
>
{ child }
</Transition>
)
: cloneElement(child, { className: classNames('in', child.className) });

//Adds a wrapping div so it cannot be before Transition
if (rootClose) {
child = (
<RootCloseWrapper onRootClose={props.onHide}>
{ child }
</RootCloseWrapper>
);
}
}

// This must wrap the transition to avoid position recalculations.
child = (
<Position {...{container, containerPadding, target, placement}}>
{child}
</Position>
);

// This goes after everything else because it adds a wrapping div.
if (rootClose) {
child = (
<RootCloseWrapper onRootClose={props.onHide}>
{child}
</RootCloseWrapper>
);
}

return (
<Portal container={container}>
{ child }
{child}
</Portal>
);
}

handleHidden(){
this.setState({ exited: true, exiting: false });
handleHidden() {
this.setState({exited: true});
}
}

Expand Down

0 comments on commit c837d8d

Please sign in to comment.