diff --git a/src/dialog.jsx b/src/dialog.jsx
index 9dcaa130e70fad..6de0e342a31e2b 100644
--- a/src/dialog.jsx
+++ b/src/dialog.jsx
@@ -462,7 +462,7 @@ const Dialog = React.createClass({
render() {
return (
-
+
);
},
@@ -523,10 +523,6 @@ const Dialog = React.createClass({
}, this._onDismiss);
},
- layerWillUnmount() {
- if (this.props.onDismiss) this.props.onDismiss();
- },
-
isOpen() {
return this.state.openImmediately;
},
diff --git a/src/popover/popover.jsx b/src/popover/popover.jsx
index 6bf77fd86ab80c..da58ad956fba63 100644
--- a/src/popover/popover.jsx
+++ b/src/popover/popover.jsx
@@ -49,7 +49,7 @@ const Popover = React.createClass({
vertical: 'top',
horizontal: 'left',
},
- useLayerForClickAway:true,
+ useLayerForClickAway: true,
zDepth: 1,
};
},
@@ -70,6 +70,7 @@ const Popover = React.createClass({
getChildContext() {
return {
+ muiTheme: this.state.muiTheme,
};
},
@@ -80,20 +81,35 @@ const Popover = React.createClass({
componentWillReceiveProps(nextProps, nextContext) {
let newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme;
- if (nextProps.open !== this.state.open) {
+
+ if (this._isAnimating === true || nextProps.open !== this.state.open) {
if (nextProps.open) {
this.anchorEl = nextProps.anchorEl || this.props.anchorEl;
this.setState({
open: true,
muiTheme: newMuiTheme,
- });
- } else {
- this.setState({
- open: false,
- muiTheme: newMuiTheme,
}, () => {
- this._animateClose();
+ this._animate(true);
});
+ } else {
+ if (nextProps.animated) {
+ this._animate(false);
+ this._isAnimating = true;
+ this._timeout = setTimeout(() => {
+ if (this.isMounted()) {
+ this._isAnimating = false;
+ this.setState({
+ open: false,
+ muiTheme: newMuiTheme,
+ });
+ }
+ }, 500);
+ } else {
+ this.setState({
+ open: false,
+ muiTheme: newMuiTheme,
+ });
+ }
}
}
},
@@ -102,22 +118,18 @@ const Popover = React.createClass({
this.setPlacement();
},
- componentWillUnmount() {
- if (this.state.open) {
- this._animateClose();
- }
- },
-
render() {
- return ;
+ return (
+
+ );
},
renderLayer() {
- let {
+ const {
animated,
targetOrigin,
className,
@@ -125,35 +137,34 @@ const Popover = React.createClass({
} = this.props;
const anchorEl = this.props.anchorEl || this.anchorEl;
- let anchor = this.getAnchorPosition(anchorEl);
- let horizontal = targetOrigin.horizontal.replace('middle', 'vertical');
+ const anchor = this.getAnchorPosition(anchorEl);
+ const horizontal = targetOrigin.horizontal.replace('middle', 'vertical');
- let wrapperStyle = {
+ const wrapperStyle = this.mergeAndPrefix({
position: 'fixed',
top: anchor.top,
left: anchor.left,
zIndex: this.state.muiTheme.zIndex.popover,
- opacity:1,
- overflow:'auto',
- maxHeight:'100%',
- transform:'scale(0,0)',
+ opacity: 1,
+ overflow: 'auto',
+ maxHeight: '100%',
+ transform: 'scale(0,0)',
transformOrigin: `${horizontal} ${targetOrigin.vertical}`,
transition: animated ? Transitions.easeOut('500ms', ['transform', 'opacity']) : null,
- };
- wrapperStyle = this.mergeAndPrefix(wrapperStyle, this.props.style);
+ }, this.props.style);
- let horizontalAnimation = {
- maxHeight:'100%',
- overflowY:'auto',
- transform:'scaleX(0)',
- opacity:1,
+ const horizontalAnimation = {
+ maxHeight: '100%',
+ overflowY: 'auto',
+ transform: 'scaleX(0)',
+ opacity: 1,
transition: animated ? Transitions.easeOut('250ms', ['transform', 'opacity']) : null,
transformOrigin: `${horizontal} ${targetOrigin.vertical}`,
};
- let verticalAnimation = {
- opacity:1,
- transform:'scaleY(0)',
+ const verticalAnimation = {
+ opacity: 1,
+ transform: 'scaleY(0)',
transformOrigin: `${horizontal} ${targetOrigin.vertical}`,
transition: animated ? Transitions.easeOut('500ms', ['transform', 'opacity']) : null,
};
@@ -177,11 +188,7 @@ const Popover = React.createClass({
}
},
- componentClickAway(event) {
- if (event.defaultPrevented) {
- return;
- }
-
+ componentClickAway() {
this.requestClose('clickAway');
},
@@ -189,16 +196,12 @@ const Popover = React.createClass({
this.setPlacement();
},
- _animateClose() {
+ _animate(open) {
if (!this.refs.layer || !this.refs.layer.getLayer()) {
return;
}
const el = this.refs.layer.getLayer().children[0];
- this._animate(el, false);
- },
-
- _animate(el) {
let value = '0';
const inner = el.children[0];
const innerInner = inner.children[0];
@@ -206,7 +209,7 @@ const Popover = React.createClass({
const rootStyle = inner.style;
const innerStyle = innerInner.style;
- if (this.state.open) {
+ if (open) {
value = '1';
}
@@ -264,7 +267,7 @@ const Popover = React.createClass({
const targetEl = this.refs.layer.getLayer().children[0];
if (!targetEl) {
- return {};
+ return;
}
let {targetOrigin, anchorOrigin} = this.props;
@@ -289,8 +292,6 @@ const Popover = React.createClass({
targetEl.style.top = targetPosition.top + 'px';
targetEl.style.left = targetPosition.left + 'px';
-
- this._animate(targetEl, true);
},
autoCloseWhenOffScreen(anchorPosition) {
diff --git a/src/render-to-layer.js b/src/render-to-layer.js
index 1b7d38cb3fc60a..3c2786ca2933f5 100644
--- a/src/render-to-layer.js
+++ b/src/render-to-layer.js
@@ -1,6 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import debounce from 'lodash.debounce';
import Dom from './utils/dom';
import DefaultRawTheme from './styles/raw-themes/light-raw-theme';
import ThemeManager from './styles/theme-manager';
@@ -16,7 +15,7 @@ const RenderToLayer = React.createClass({
getDefaultProps() {
return {
- useLayerForClickAway:true,
+ useLayerForClickAway: true,
};
},
@@ -40,8 +39,10 @@ const RenderToLayer = React.createClass({
//to update theme inside state whenever a new theme is passed down
//from the parent / owner using context
componentWillReceiveProps(nextProps, nextContext) {
- let newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme;
- this.setState({muiTheme: newMuiTheme});
+ const newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme;
+ this.setState({
+ muiTheme: newMuiTheme,
+ });
},
componentDidMount() {
@@ -58,17 +59,23 @@ const RenderToLayer = React.createClass({
}
},
- onClickAway(e) {
- if (e.defaultPrevented) {
+ onClickAway(event) {
+ if (event.defaultPrevented) {
+ return;
+ }
+
+ if (!this.props.componentClickAway) {
+ return;
+ }
+
+ if (!this.props.open) {
return;
}
const el = this._layer;
- if (e.target !== el && (e.target === window)
- || (document.documentElement.contains(e.target) && !Dom.isDescendant(el, e.target))) {
- if (this.props.componentClickAway && this.props.open) {
- this.props.componentClickAway(e);
- }
+ if (event.target !== el && (event.target === window)
+ || (document.documentElement.contains(event.target) && !Dom.isDescendant(el, event.target))) {
+ this.props.componentClickAway(event);
}
},
@@ -81,74 +88,65 @@ const RenderToLayer = React.createClass({
},
_renderLayer() {
- if (this.props.open) {
+ const {
+ open,
+ render,
+ } = this.props;
+
+ if (open) {
if (!this._layer) {
this._layer = document.createElement('div');
document.body.appendChild(this._layer);
+
+ if (this.props.useLayerForClickAway) {
+ this._layer.addEventListener('touchstart', this.onClickAway);
+ this._layer.addEventListener('click', this.onClickAway);
+ this._layer.style.position = 'fixed';
+ this._layer.style.top = 0;
+ this._layer.style.bottom = 0;
+ this._layer.style.left = 0;
+ this._layer.style.right = 0;
+ this._layer.style.zIndex = this.state.muiTheme.zIndex.layer;
+ } else {
+ setTimeout(() => {
+ window.addEventListener('touchstart', this.onClickAway);
+ window.addEventListener('click', this.onClickAway);
+ }, 0);
+ }
}
- if (this.props.useLayerForClickAway) {
- this._layer.addEventListener('touchstart', this.onClickAway);
- this._layer.addEventListener('click', this.onClickAway);
- this._layer.style.position = 'fixed';
- this._layer.style.top = 0;
- this._layer.style.bottom = 0;
- this._layer.style.left = 0;
- this._layer.style.right = 0;
- this._layer.style.zIndex = this.state.muiTheme.zIndex.layer;
- }
- else {
- setTimeout(() => {
- window.addEventListener('touchstart', this.onClickAway);
- window.addEventListener('click', this.onClickAway);
- }, 0);
- }
- if (this.reactUnmount) {
- this.reactUnmount.cancel();
- }
- } else if (this._layer) {
- if (this.props.useLayerForClickAway) {
- this._layer.style.position = 'relative';
- this._layer.removeEventListener('touchstart', this.onClickAway);
- this._layer.removeEventListener('click', this.onClickAway);
+
+ // By calling this method in componentDidMount() and
+ // componentDidUpdate(), you're effectively creating a "wormhole" that
+ // funnels React's hierarchical updates through to a DOM node on an
+ // entirely different part of the page.
+
+ const layerElement = render();
+
+ if (layerElement === null) {
+ this.layerElement = ReactDOM.unstable_renderSubtreeIntoContainer(this, null, this._layer);
} else {
- window.removeEventListener('touchstart', this.onClickAway);
- window.removeEventListener('click', this.onClickAway);
+ this.layerElement = ReactDOM.unstable_renderSubtreeIntoContainer(this, layerElement, this._layer);
}
- this._unrenderLayer();
} else {
- return;
- }
+ if (this._layer) {
+ if (this.props.useLayerForClickAway) {
+ this._layer.style.position = 'relative';
+ this._layer.removeEventListener('touchstart', this.onClickAway);
+ this._layer.removeEventListener('click', this.onClickAway);
+ } else {
+ window.removeEventListener('touchstart', this.onClickAway);
+ window.removeEventListener('click', this.onClickAway);
+ }
- // By calling this method in componentDidMount() and
- // componentDidUpdate(), you're effectively creating a "wormhole" that
- // funnels React's hierarchical updates through to a DOM node on an
- // entirely different part of the page.
-
- const layerElement = this.props.render();
- // Renders can return null, but React.render() doesn't like being asked
- // to render null. If we get null back from renderLayer(), just render
- // a noscript element, like React does when an element's render returns
- // null.
- if (layerElement === null) {
- this.layerElement = ReactDOM.unstable_renderSubtreeIntoContainer(this, , this._layer);
- } else {
- this.layerElement = ReactDOM.unstable_renderSubtreeIntoContainer(this, layerElement, this._layer);
+ this._unrenderLayer();
+ }
}
},
_unrenderLayer: function() {
- if (!this.reactUnmount)
- this.reactUnmount = debounce(() => {
- if (this._layer) {
- if (this.layerWillUnmount) {
- this.layerWillUnmount(this._layer);
- }
- ReactDOM.unmountComponentAtNode(this._layer);
- document.body.removeChild(this._layer);
- this._layer = null;
- }
- }, 1000);
- this.reactUnmount();
+ ReactDOM.unmountComponentAtNode(this._layer);
+ document.body.removeChild(this._layer);
+ this._layer = null;
},
});