Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/rackt/react-modal
Browse files Browse the repository at this point in the history
  • Loading branch information
mzabriskie committed Nov 17, 2014
2 parents 28dbc63 + 1038e3b commit 2f1973b
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 30 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
v0.0.5 - Thu, 13 Nov 2014 18:55:47 GMT
--------------------------------------

- [b15aa82](../../commit/b15aa82) [added] Supporting custom className
- [b7a38de](../../commit/b7a38de) [fixed] Warning caused by trying to focus null element closes #11


v0.0.4 - Tue, 11 Nov 2014 16:08:14 GMT
--------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-modal",
"version": "0.0.4",
"version": "0.0.5",
"homepage": "https://github.com/rackt/react-modal",
"authors": [
"Ryan Florence",
Expand Down
93 changes: 72 additions & 21 deletions dist/react-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ var React = (typeof window !== "undefined" ? window.React : typeof global !== "u
var div = React.DOM.div;
var focusManager = _dereq_('../helpers/focusManager');
var scopeTab = _dereq_('../helpers/scopeTab');
var cx = _dereq_('react/lib/cx');

// so that our CSS is statically analyzable
var CLASS_NAMES = {
Expand Down Expand Up @@ -102,21 +103,36 @@ var ModalPortal = module.exports = React.createClass({
},

componentDidMount: function() {
this.handleProps(this.props);
this.maybeFocus();
// Focus needs to be set when mounting and already open
if (this.props.isOpen) {
this.setFocusAfterRender(true);
this.open();
}
},

componentWillReceiveProps: function(newProps) {
this.handleProps(newProps);
},
// Focus only needs to be set once when the modal is being opened
if (!this.props.isOpen && newProps.isOpen) {
this.setFocusAfterRender(true);
}

handleProps: function(props) {
if (props.isOpen === true)
if (newProps.isOpen === true)
this.open();
else if (props.isOpen === false)
else if (newProps.isOpen === false)
this.close();
},

componentDidUpdate: function () {
if (this.focusAfterRender) {
this.focusContent();
this.setFocusAfterRender(false);
}
},

setFocusAfterRender: function (focus) {
this.focusAfterRender = focus;
},

open: function() {
focusManager.setupScopedFocus(this.getDOMNode());
focusManager.markForFocusLater();
Expand All @@ -134,17 +150,6 @@ var ModalPortal = module.exports = React.createClass({
this.closeWithoutTimeout();
},

componentDidUpdate: function() {
this.maybeFocus();
},

maybeFocus: function() {
if (this.props.isOpen &&
!this.refs.content.getDOMNode().contains(document.activeElement)) {
this.focusContent();
}
},

focusContent: function() {
this.refs.content.getDOMNode().focus();
},
Expand Down Expand Up @@ -212,7 +217,7 @@ var ModalPortal = module.exports = React.createClass({
},
div({
ref: "content",
className: this.buildClassName('content'),
className: cx(this.buildClassName('content'), this.props.className),
tabIndex: "-1",
onClick: stopPropagation,
onKeyDown: this.handleKeyDown
Expand All @@ -224,7 +229,7 @@ var ModalPortal = module.exports = React.createClass({
}
});

},{"../helpers/focusManager":4,"../helpers/scopeTab":6}],3:[function(_dereq_,module,exports){
},{"../helpers/focusManager":4,"../helpers/scopeTab":6,"react/lib/cx":9}],3:[function(_dereq_,module,exports){
var _element = null;

function setElement(element) {
Expand Down Expand Up @@ -435,6 +440,52 @@ module.exports = findTabbableDescendants;
module.exports = _dereq_('./components/Modal');


},{"./components/Modal":1}]},{},[8])
},{"./components/Modal":1}],9:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @providesModule cx
*/

/**
* This function is used to mark string literals representing CSS class names
* so that they can be transformed statically. This allows for modularization
* and minification of CSS class names.
*
* In static_upstream, this function is actually implemented, but it should
* eventually be replaced with something more descriptive, and the transform
* that is used in the main stack should be ported for use elsewhere.
*
* @param string|object className to modularize, or an object of key/values.
* In the object case, the values are conditions that
* determine if the className keys should be included.
* @param [string ...] Variable list of classNames in the string case.
* @return string Renderable space-separated CSS className.
*/
function cx(classNames) {
if (typeof classNames == 'object') {
return Object.keys(classNames).filter(function(className) {
return classNames[className];
}).join(' ');
} else {
return Array.prototype.join.call(arguments, ' ');
}
}

module.exports = cx;

},{}]},{},[8])
(8)
});
2 changes: 1 addition & 1 deletion dist/react-modal.min.js

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions examples/bootstrap/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
body {
font-family: "Helvetica Neue", Arial;
font-weight: 200;
background: #ccc;
}

.ReactModal__Overlay {
-webkit-perspective: 600;
perspective: 600;
opacity: 0;
overflow-x: hidden;
overflow-y: auto;
background-color: rgba(0, 0, 0, 0.5);
}

.ReactModal__Overlay--after-open {
opacity: 1;
transition: opacity 150ms ease-out;
}

.ReactModal__Content {
-webkit-transform: scale(0.5) rotateX(-30deg);
}

.ReactModal__Content--after-open {
-webkit-transform: scale(1) rotateX(0deg);
transition: all 150ms ease-in;
}

.ReactModal__Overlay--before-close {
opacity: 0;
}

.ReactModal__Content--before-close {
-webkit-transform: scale(0.5) rotateX(30deg);
transition: all 150ms ease-in;
}

.ReactModal__Content.modal-dialog {
border: none;
background-color: transparent;
}
69 changes: 69 additions & 0 deletions examples/bootstrap/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/** @jsx React.DOM */
var React = require('react');
var Modal = require('../../lib/index');

var appElement = document.getElementById('example');

Modal.setAppElement(appElement);
Modal.injectCSS();

var App = React.createClass({

getInitialState: function() {
return { modalIsOpen: false };
},

openModal: function() {
this.setState({modalIsOpen: true});
},

closeModal: function() {
this.setState({modalIsOpen: false});
},

handleModalCloseRequest: function() {
// opportunity to validate something and keep the modal open even if it
// requested to be closed
this.setState({modalIsOpen: false});
},

handleSaveClicked: function(e) {
alert('Save button was clicked');
},

render: function() {
return (
<div>
<button onClick={this.openModal}>Open Modal</button>
<Modal
className="Modal__Bootstrap modal-dialog"
closeTimeoutMS={150}
isOpen={this.state.modalIsOpen}
onRequestClose={this.handleModalCloseRequest}
>
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" onClick={this.handleModalCloseRequest}>
<span aria-hidden="true">&times;</span>
<span className="sr-only">Close</span>
</button>
<h4 className="modal-title">Modal title</h4>
</div>
<div className="modal-body">
<h4>Really long content...</h4>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" onClick={this.handleModalCloseRequest}>Close</button>
<button type="button" className="btn btn-primary" onClick={this.handleSaveClicked}>Save changes</button>
</div>
</div>
</Modal>
</div>
);
}
});

React.renderComponent(<App/>, appElement);
10 changes: 10 additions & 0 deletions examples/bootstrap/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!doctype html public "embarassment">
<title>Bootstrap-Style Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<link href="app.css" rel="stylesheet"/>
<body>
<div id="example"></div>
<script src="/__build__/shared.js"></script>
<script src="/__build__/bootstrap.js"></script>

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-modal",
"version": "0.0.4",
"version": "0.0.5",
"description": "Accessible modal dialog component for React.JS",
"main": "./lib/index",
"repository": {
Expand Down
6 changes: 0 additions & 6 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,6 @@ module.exports = {
]
},

resolve: {
alias: {
'react-router': '../../modules/index'
}
},

plugins: [
new webpack.optimize.CommonsChunkPlugin('shared.js')
]
Expand Down

0 comments on commit 2f1973b

Please sign in to comment.