diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e859fc56..94995bd7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,10 +28,10 @@ always be in sync. ### Development -- `script/test` will fire up a karma runner and watch for changes in the - specs directory. -- `npm test` will do the same but doesn't watch, just runs the tests. -- `script/build-examples` does exactly that. +- `npm start` runs the dev server to run/develop examples +- `npm test` will run the test. +- `script/test` same as `npm test` but keeps karma running and watches + for changes ### Build diff --git a/examples/basic/app.js b/examples/basic/app.js index 42c3dbe8..b4b0a5cf 100644 --- a/examples/basic/app.js +++ b/examples/basic/app.js @@ -27,6 +27,10 @@ var App = React.createClass({ this.setState({modalIsOpen: false}); }, + handleInputChange: function() { + this.setState({foo: 'bar'}); + }, + render: function() { return (
@@ -40,7 +44,7 @@ var App = React.createClass({
I am a modal
- + diff --git a/examples/basic/index.html b/examples/basic/index.html index b6b5dc97..8ccdb073 100644 --- a/examples/basic/index.html +++ b/examples/basic/index.html @@ -4,5 +4,6 @@
- - + + + diff --git a/lib/components/Modal.js b/lib/components/Modal.js index c39a87f4..c9059f3d 100644 --- a/lib/components/Modal.js +++ b/lib/components/Modal.js @@ -50,7 +50,10 @@ var Modal = module.exports = React.createClass({ ariaAppHider.toggle(props.isOpen, props.appElement); } sanitizeProps(props); - this.portal = React.renderComponent(ModalPortal(props), this.node); + if (this.portal) + this.portal.setProps(props); + else + this.portal = React.renderComponent(ModalPortal(props), this.node); }, render: function () { @@ -61,4 +64,3 @@ var Modal = module.exports = React.createClass({ function sanitizeProps(props) { delete props.ref; } - diff --git a/lib/components/ModalPortal.js b/lib/components/ModalPortal.js index da496f8d..54ad7c65 100644 --- a/lib/components/ModalPortal.js +++ b/lib/components/ModalPortal.js @@ -70,8 +70,10 @@ var ModalPortal = module.exports = React.createClass({ }, maybeFocus: function() { - if (this.props.isOpen) + if (this.props.isOpen && + !this.refs.content.getDOMNode().contains(document.activeElement)) { this.focusContent(); + } }, focusContent: function() { @@ -109,7 +111,7 @@ var ModalPortal = module.exports = React.createClass({ }, requestClose: function() { - if (this.ownerHandlesClose) + if (this.ownerHandlesClose()) this.props.onRequestClose(); }, @@ -152,4 +154,3 @@ var ModalPortal = module.exports = React.createClass({ ); } }); - diff --git a/package.json b/package.json index 21438486..71cfabe9 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "example": "examples" }, "scripts": { - "test": "script/test --browsers Firefox --single-run" + "test": "script/test --browsers Firefox --single-run", + "start": "script/dev-examples" }, "authors": [ "Ryan Florence" @@ -24,6 +25,7 @@ "browserify-shim": "3.6.0", "envify": "1.2.0", "expect": "0.1.1", + "jsx-loader": "0.11.2", "karma": "0.12.16", "karma-browserify": "^0.2.1", "karma-chrome-launcher": "0.1.4", @@ -32,10 +34,10 @@ "karma-mocha": "0.1.3", "mocha": "1.20.1", "react": ">=0.11.0", - "react-tap-event-plugin": "git://github.com/appsforartists/react-tap-event-plugin", "reactify": "^0.14.0", "rf-release": "0.3.1", - "uglify-js": "2.4.15" + "uglify-js": "2.4.15", + "webpack-dev-server": "1.6.5" }, "peerDependencies": { "react": ">=0.11.0" @@ -55,4 +57,4 @@ "browserify-shim": { "react": "global:React" } -} \ No newline at end of file +} diff --git a/script/build-examples b/script/build-examples deleted file mode 100755 index 417e1420..00000000 --- a/script/build-examples +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -BROWSERIFY="node_modules/.bin/browserify --detect-globals false" -BUNDLE_EXAMPLE="$BROWSERIFY -t reactify -t envify -x react -x react-modal" -NODE_ENV=development $BROWSERIFY -t reactify -t envify -r react -r ./lib:react-modal > examples/global-bundle.js - -$BUNDLE_EXAMPLE examples/basic/app.js > examples/basic/app-bundle.js diff --git a/script/dev-examples b/script/dev-examples new file mode 100755 index 00000000..fb83b319 --- /dev/null +++ b/script/dev-examples @@ -0,0 +1,3 @@ +#!/bin/sh +node_modules/.bin/webpack-dev-server --inline --content-base examples/ + diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 00000000..b0f344f1 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,52 @@ +var fs = require('fs'); +var path = require('path'); +var webpack = require('webpack'); + +var EXAMPLES_DIR = path.resolve(__dirname, 'examples'); + +function isDirectory(dir) { + return fs.lstatSync(dir).isDirectory(); +} + +function buildEntries() { + return fs.readdirSync(EXAMPLES_DIR).reduce(function (entries, dir) { + if (dir === 'build') + return entries; + + var isDraft = dir.charAt(0) === '_'; + + if (!isDraft && isDirectory(path.join(EXAMPLES_DIR, dir))) + entries[dir] = path.join(EXAMPLES_DIR, dir, 'app.js'); + + return entries; + }, {}); +} + +module.exports = { + + entry: buildEntries(), + + output: { + filename: '[name].js', + chunkFilename: '[id].chunk.js', + path: 'examples/__build__', + publicPath: '/__build__/' + }, + + module: { + loaders: [ + { test: /\.js$/, loader: 'jsx-loader?harmony' } + ] + }, + + resolve: { + alias: { + 'react-router': '../../modules/index' + } + }, + + plugins: [ + new webpack.optimize.CommonsChunkPlugin('shared.js') + ] + +};