Skip to content

Instantly share code, notes, and snippets.

@rtorr
Last active August 29, 2015 14:22
Show Gist options
  • Save rtorr/29891c2a6c9ddc40540c to your computer and use it in GitHub Desktop.
Save rtorr/29891c2a6c9ddc40540c to your computer and use it in GitHub Desktop.
Portal that works with flux
var React = require('react/addons');
var activeStyle = {
position: 'fixed',
top: '0',
left: '0',
right: '0',
bottom: '0',
zIndex: '2000'
};
var backgroundStyle = {
background: 'rgba(0, 0, 0, 0.6)',
position: 'fixed',
top: '0',
left: '0',
right: '0',
bottom: '0',
cursor: 'pointer'
};
var modalContent = {
position: 'relative',
zIndex: '3000'
};
var Modal = React.createClass({
render: function() {
return (
<div style={activeStyle}>
<div style={backgroundStyle} onClick={this.props.handleClose}></div>
<div style={modalContent}>
{this.props.children}
</div>
</div>
);
}
});
module.exports = Modal;
var React = require('react/addons');
var PureRenderMixin = React.addons.PureRenderMixin;
var Freighter = require('freighter');
var PortalStore = require('./PortalStore');
var PortalActions = require('./PortalActions');
var Portal = React.createClass({
mixins: [PureRenderMixin, Freighter],
stores: [PortalStore],
propTypes: {
children: React.PropTypes.element.isRequired,
onClose: React.PropTypes.func
},
getStateFromStores(){
return PortalStore.getStoreData();
},
componentWillMount() {
if (this.state.active) {
this.openPortal();
}
},
componentDidMount(){
document.addEventListener('keydown', this.handleKeydown);
},
componentWillUnmount(){
document.removeEventListener('keydown', this.handleKeydown);
this.closePortal();
},
closePortal() {
if (this.node) {
React.unmountComponentAtNode(this.node);
document.body.removeChild(this.node);
}
this.portal = null;
this.node = null;
},
handleClose(){
PortalActions.close();
},
handleKeydown(e) {
// ESC
if (e.keyCode === 27) {
this.closePortal();
}
},
renderPortal(){
if (!this.node) {
this.node = document.createElement('div');
document.body.appendChild(this.node);
this.portal = React.render(React.cloneElement(this.props.children, {handleClose: this.handleClose}), this.node);
}
PortalActions.open();
},
componentDidUpdate(){
switch(this.state.active){
case false:
this.closePortal();
break;
case true:
if (this.node){
this.portal = React.render(React.cloneElement(this.props.children, {handleClose: this.handleClose}), this.node);
}
break;
}
},
openPortal(e) {
if (e) {
e.preventDefault();
e.stopPropagation();
}
this.renderPortal();
},
render() {
if (this.props.openByClickOn) {
return <div className="Portal__open-by-click-on" onClick={this.openPortal}>{this.props.openByClickOn}</div>;
} else {
return null;
}
}
});
module.exports = Portal;
var LCARS = require('lcars');
var PortalConstants = require('./PortalConstants');
var PortalActions = {
open(){
LCARS.dispatch({
type: PortalConstants.PORTAL.OPEN
});
},
close(){
LCARS.dispatch({
type: PortalConstants.PORTAL.CLOSE
});
}
};
module.exports = PortalActions;
var keyMirror = require('react/lib/keyMirror');
var PortalConstants = {
PORTAL: keyMirror({
OPEN: null,
CLOSE: null
})
};
module.exports = PortalConstants;
var LCARS = require('lcars');
var CargoBay = require('cargo-bay');
var merge = require('amp-merge');
var PortalConstants = require('PortalConstants');
var StoreData = {
_data: {
active: false
},
clonedData: function() {
return JSON.parse(JSON.stringify(this._data));
}
};
var PortalStore = merge(CargoBay, {
set(key, value){
StoreData._data[key] = value;
return StoreData.clonedData();
},
getStoreData(){
return StoreData.clonedData();
}
});
PortalStore.dispatchToken = LCARS.register(function(action){
switch (action.type){
case PortalConstants.PORTAL.OPEN:
PortalStore.set('active', true);
PortalStore.emitChange();
break;
case PortalConstants.PORTAL.CLOSE:
PortalStore.set('active', false);
PortalStore.emitChange();
break;
}
});
module.exports = PortalStore;
var React = require('react/addons');
var Modal = require('./Modal');
var Portal = require('./Portal');
var SomeComponent = React.createClass({
render(){
var button = <a>close</a>;
return (
<Portal openByClickOn={button}>
<Modal>
<p>hello modal</p>
</Modal>
</Portal>
);
}
});
module.exports = SomeComponent;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment