Update react-modal and establish canvas modal style

fixes PLAT-771

Change-Id: Ia7ea6ca7002f1c1926f845d74af3544337c96def
Reviewed-on: https://gerrit.instructure.com/44584
Tested-by: Jenkins <jenkins@instructure.com>
Product-Review: Colleen Palmer <colleen@instructure.com>
Reviewed-by: Colleen Palmer <colleen@instructure.com>
QA-Review: Eric Berry <ericb@instructure.com>
This commit is contained in:
Eric Berry 2014-11-18 10:16:16 -07:00
parent e3a8ea8445
commit 3235a5b020
22 changed files with 573 additions and 97 deletions

View File

@ -1,15 +1,17 @@
require [
'jquery'
'underscore'
'react'
'compiled/fn/preventDefault'
'compiled/views/PublishButtonView'
'compiled/views/PublishIconView'
'jsx/styleguide/ReactModalExample'
'jqueryui/accordion'
'jqueryui/tabs'
'jqueryui/button'
'jqueryui/tooltip'
'jquery.instructure_date_and_time'
], ($, _, preventDefault, PublishButtonView, PublishIconView) ->
], ($, _, React, preventDefault, PublishButtonView, PublishIconView, ReactModalExample) ->
do ->
dialog = $('#dialog-buttons-dialog').dialog({
@ -19,6 +21,22 @@ require [
$('#show-dialog-buttons-dialog').click -> dialog.open()
# React Modal
React.renderComponent(
ReactModalExample
className: 'ReactModal__Content--canvas'
overlayClassName: 'ReactModal__Overlay--canvas'
, document.getElementById('react-modal-example')
);
React.renderComponent(
ReactModalExample
label: 'Trigger Confirm Dialog'
className: 'ReactModal__Content--canvas ReactModal__Content--mini-modal'
overlayClassName: 'ReactModal__Overlay--canvas'
, document.getElementById('react-modal-confirm-example')
)
## OLD STYLEGUIDE ##
iconEventsMap =

View File

@ -181,7 +181,7 @@ define [
@setState(newState)
render: withReactDOM ->
ReactModal {isOpen: true, onRequestClose: @closeModal, closeTimeoutMS: 10},
ReactModal {isOpen: true, onRequestClose: @closeModal, className: 'ReactModal__Content--ef-file-preview', overlayClassName: 'ReactModal__Overlay--ef-file-preview', closeTimeoutMS: 10},
div {className: 'ef-file-preview-overlay'},
div {className: 'ef-file-preview-header'},
h1 {className: 'ef-file-preview-header-filename'},

View File

@ -0,0 +1,71 @@
/** React.DOM */
define([
'React',
'react-modal'
], function(React, Modal) {
Modal.injectCSS();
var ReactModalExample = React.createClass({
getInitialState () {
return {
modalIsOpen: false
}
},
openModal (e) {
e.preventDefault();
this.setState({ modalIsOpen: true });
},
closeModal () {
this.setState({ modalIsOpen: false });
},
handleSubmit () {
alert('Submitted');
},
render () {
return (
<div className="ModalExample">
<a href="#" role="button" aria-label="Trigger Modal" className="btn btn-primary" onClick={this.openModal}>Trigger Modal</a>
<Modal isOpen={this.state.modalIsOpen} onRequestClose={this.closeModal}>
<div className="ReactModal__Layout">
<div className="ReactModal__InnerSection ReactModal__Header">
<div className="ReactModal__Header-Title">
<h4>Are you ready to submit?</h4>
</div>
<div className="ReactModal__Header-Actions">
<button className="Button Button--link Button--small" type="button" onClick={this.closeModal}>
<i className="icon-x"></i>
</button>
</div>
</div>
<div className="ReactModal__InnerSection ReactModal__Body">
This will be awesome.
</div>
<div className="ReactModal__InnerSection ReactModal__Footer">
<div className="ReactModal__Footer-Actions">
<button type="button" className="Button" onClick={this.closeModal}>Cancel</button>
<button type="button" className="Button Button--primary" onClick={this.handleSubmit}>Submit</button>
</div>
</div>
</div>
</Modal>
</div>
);
}
});
React.renderComponent(<ReactModalExample/>, document.getElementById('content'));
});

View File

@ -0,0 +1,78 @@
/** @jsx React.DOM */
define([
'react',
'react-modal'
], function (React, Modal) {
var ReactModalExample = React.createClass({
getInitialState() {
return {
modalIsOpen: false
}
},
openModal(e) {
e.preventDefault();
this.setState({modalIsOpen: true});
},
closeModal(e) {
e.preventDefault();
this.setState({modalIsOpen: false});
},
handleSubmit(e) {
e.preventDefault();
this.setState({modalIsOpen: false});
alert('Submitted');
},
render() {
return (
<div className="ReactModalExample">
<a href="#" role="button" aria-label="Trigger Modal" className="btn btn-primary" onClick={this.openModal}>{this.props.label || 'Trigger Modal'}</a>
<Modal isOpen={this.state.modalIsOpen}
onRequestClose={this.closeModal}
className={this.props.className}
overlayClassName={this.props.overlayClassName}>
<div className="ReactModal__Layout">
<div className="ReactModal__InnerSection ReactModal__Header">
<div className="ReactModal__Header-Title">
<h4>Modal Title Goes Here</h4>
</div>
<div className="ReactModal__Header-Actions">
<button className="Button Button--link Button--small" type="button" onClick={this.closeModal}>
<i className="icon-x"></i>
</button>
</div>
</div>
<div className="ReactModal__InnerSection ReactModal__Body">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus deserunt doloremque, explicabo illo
ipsum libero magni odio officia optio perferendis ratione repellat suscipit tempore. Commodi hic sed.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus deserunt doloremque, explicabo illo
ipsum libero magni odio officia optio perferendis ratione repellat suscipit tempore. Commodi hic sed.
</div>
<div className="ReactModal__InnerSection ReactModal__Footer">
<div className="ReactModal__Footer-Actions">
<button type="button" className="btn btn-default" onClick={this.closeModal}>Cancel</button>
<button type="button" className="btn btn-primary" onClick={this.handleSubmit}>Submit</button>
</div>
</div>
</div>
</Modal>
</div>
);
}
});
return ReactModalExample;
});

View File

@ -18,6 +18,7 @@
@import "inst_tree";
@import "misc";
@import "new-and-total-badge";
@import "react_modal";
@import "show_hide_opacity";
@import "spacing";
@import "alignment";

View File

@ -0,0 +1,174 @@
/* @styleguide Modal Dialog - React (new!)
### Default Canvas modal
React Modal comes with very few default classes to make it as themeable as possible. If you want plain-vanilla Canvas modal styles, be sure to specify `className: 'ReactModal__Content--canvas'` when you initialize the modal, as follows:
```javascript
React.renderComponent(
ReactModalExample(
{ className: 'ReactModal__Content--canvas'
overlayClassName: 'ReactModal__Overlay--canvas' }
), document.getElementById('react-modal-example')
);
```
```html
<p>
<div id="react-modal-example"></div>
</p>
```
See `app/jsx/styleguide/ReactModalExample.jsx` for complete example usage.
<br />
### Mini Canvas modal
For small dialogs like Confirms, the default Canvas modal width might seem too much. The **.ReactModal__Content--mini-modal** class can be appended to the **.ReactModal__Content--canvas** class to render a less wide modal dialog.
```javascript
React.renderComponent(
ReactModalExample(
{ label: 'Trigger Confirm Dialog',
className: 'ReactModal__Content--canvas ReactModal__Content--mini-modal',
overlayClassName: 'ReactModal__Overlay--canvas' }
), document.getElementById('react-modal-confirm-example')
);
```
```html
<p>
<div id="react-modal-confirm-example"></div>
</p>
```
See `app/jsx/examples/ReactModalExample.jsx` for complete example usage.
*/
// Global styles for any React modal.
// Do not change these or your name will be cursed for generations.
.ReactModal__Overlay {
transition: opacity 0.2s ease-out;
overflow-x: hidden;
overflow-y: auto;
background: rgba($canvas-secondary, 0.75);
z-index: 150;
opacity: 0;
&.ReactModal__Overlay--after-open {
opacity: 1;
}
}
@mixin ReactModalPadding {
padding: 6px;
@include breakpoint(tablet) { padding: 12px; }
@include breakpoint(desktop) { padding: 16px; }
}
.ReactModal__Content {
// To accomodate different kinds of modals, styles for
// the regular Canvas modal have been scoped under the
// .ReactModal__Content--canvas class. So if you want a
// normal modal, remember to add className='ReactModal__Content--canvas'
// when you initialize the modal in your JSX.
// This className will append itself to the .ReactModal__Content
// element, and you will get all the nice styles below.
&.ReactModal__Content--canvas {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
padding: 6px;
@include breakpoint(mini-tablet) { padding: 12px; }
@include breakpoint(tablet) { padding: 0; }
.ReactModal__Layout {
border-radius: $baseBorderRadius;
box-shadow: 0 1px 4px 1px rgba($canvas-secondary, 0.95);
@include breakpoint(tablet) {
max-width: 696px;
transition: all 0.5s cubic-bezier(0,1,0.5,1);
opacity: 0;
transform: rotateX(60deg) scale(0.8);
}
}
&.ReactModal__Content--after-open .ReactModal__Layout {
@include breakpoint(tablet) {
opacity: 1;
transform: rotateX(0) scale(1);
}
}
&.ReactModal__Content--mini-modal {
.ReactModal__Layout {
@include breakpoint(tablet) { max-width: 384px; }
}
}
// ReactModal__InnerSection class exists so that even if
// a modal has no header or footer, it still gets nice
// rounded corners
.ReactModal__InnerSection {
&:first-of-type { border-top-left-radius: $baseBorderRadius; border-top-right-radius: $baseBorderRadius; }
&:last-of-type { border-bottom-left-radius: $baseBorderRadius; border-bottom-right-radius: $baseBorderRadius; }
}
.ReactModal__Header {
@include ReactModalPadding;
display: flex;
align-items: center;
background: $canvas-light;
border-bottom: 1px solid $can-border-light;
}
.ReactModal__Header-Title {
flex: 1;
// remove margin from heading elements
* { margin: 0; }
}
.ReactModal__Header-Actions { text-align: right; }
.ReactModal__Body {
padding: 6px;
background: $canvas-light;
@include breakpoint(tablet) { padding: 16px; }
@include breakpoint(desktop) { padding: 24px; }
}
.ReactModal__Footer {
@include ReactModalPadding;
background: lighten($canvas-neutral, 5%);
border-top: 1px solid $can-border-light;
@include breakpoint(mini-tablet) {
display: flex;
align-items: center;
}
}
.ReactModal__Footer-Actions {
@include breakpoint(mini-tablet) {
flex: 1;
display: flex;
justify-content: flex-end;
}
.Button, .btn {
margin-left: 4px;
&:first-of-type { margin-left: 0; }
}
}
}
}

View File

@ -9,15 +9,11 @@ $spacing-width: 0;
$preview-footer-height: 140px;
$preview-header-height: 70px;
// Make sure that ReactModal gets above everything else
.ReactModal__Overlay {
z-index: 100;
&.ReactModal__Overlay--after-open {
background-color: rgba($preview-bg, 0.9);
}
.ReactModal__Overlay.ReactModal__Overlay--ef-file-preview {
background: rgba(black, 0.9);
}
.ReactModal__Content {
.ReactModal__Content.ReactModal__Content--ef-file-preview {
height: 100%;
display: flex;
}

View File

@ -19,6 +19,6 @@
"ic-sortable": "0.0.2",
"react": "0.11.0",
"react-router": "0.9.3",
"react-modal": "~0.0.2"
"react-modal": "0.0.6"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "react-modal",
"version": "0.0.2",
"version": "0.0.6",
"homepage": "https://github.com/rackt/react-modal",
"authors": [
"Ryan Florence",
@ -26,14 +26,13 @@
"karma.conf.js",
"package.json"
],
"_release": "0.0.2",
"_release": "0.0.6",
"_resolution": {
"type": "version",
"tag": "v0.0.2",
"commit": "26012856a5100ab55c6fc8e49c199a7cfecdf9ff"
"tag": "v0.0.6",
"commit": "734acb5b309780b10bc6bd4fb850dd214e5fd948"
},
"_source": "git://github.com/rackt/react-modal.git",
"_target": "~0.0.2",
"_originalSource": "react-modal",
"_direct": true
"_target": "0.0.6",
"_originalSource": "react-modal"
}

View File

@ -1,3 +1,29 @@
v0.0.6 - Wed, 03 Dec 2014 21:24:45 GMT
--------------------------------------
- [28dbc63](../../commit/28dbc63) [added] Supporting custom overlay className closes #14
- [6626dae](../../commit/6626dae) [fixed] erroneous alias in webpack build
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
--------------------------------------
- [e57bab5](../../commit/e57bab5) [fixed] Issue with focus being lost - closes #9
v0.0.3 - Fri, 31 Oct 2014 19:25:20 GMT
--------------------------------------
-
v0.0.2 - Thu, 25 Sep 2014 02:36:47 GMT
--------------------------------------

View File

@ -1,28 +1,29 @@
React Modal
===========
Accessible React Modal Dialog Component
Accessible React Modal Dialog Component. This isn't ready to be used
yet, still under development.
Accessibility Notes
-------------------
Etc. etc. etc.
Usage
-----
```xml
<Modal
isOpen={this.state.modalIsOpen}
onRequestClose={this.handleModalCloseRequest}
closeTimeoutMS={150}
isOpen={bool}
onRequestClose={fn}
closeTimeoutMS={n}
>
<h1>Modal Content</h1>
<p>Etc.</p>
</Modal>
```
Accessibility Notes
-------------------
Inside the app:
Inside an app:
```js
/** @jsx React.DOM */
@ -49,35 +50,23 @@ var App = React.createClass({
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});
},
render: function() {
return (
<div>
<button onClick={this.openModal}>Open Modal</button>
<Modal
closeTimeoutMS={150}
isOpen={this.state.modalIsOpen}
onRequestClose={this.handleModalCloseRequest}
onRequestClose={this.closeModal}
>
<h1>Hello</h1>
<h2>Hello</h2>
<button onClick={this.closeModal}>close</button>
<div>I am a modal</div>
<form>
<input />
<input />
<input />
<input />
<input />
<br/>
<button>hi</button>
<button>hi</button>
<button>hi</button>
<button>hi</button>
<button>tab navigation</button>
<button>stays</button>
<button>inside</button>
<button>the modal</button>
</form>
</Modal>
</div>

View File

@ -1,6 +1,6 @@
{
"name": "react-modal",
"version": "0.0.2",
"version": "0.0.6",
"homepage": "https://github.com/rackt/react-modal",
"authors": [
"Ryan Florence",

View File

@ -51,7 +51,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 () {
@ -63,12 +66,12 @@ function sanitizeProps(props) {
delete props.ref;
}
},{"../helpers/ariaAppHider":3,"../helpers/injectCSS":5,"./ModalPortal":2}],2:[function(_dereq_,module,exports){
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
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 = {
@ -100,19 +103,34 @@ 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);
}
if (newProps.isOpen === true)
this.open();
else if (newProps.isOpen === false)
this.close();
},
handleProps: function(props) {
if (props.isOpen === true)
this.open();
else if (props.isOpen === false)
this.close();
componentDidUpdate: function () {
if (this.focusAfterRender) {
this.focusContent();
this.setFocusAfterRender(false);
}
},
setFocusAfterRender: function (focus) {
this.focusAfterRender = focus;
},
open: function() {
@ -132,15 +150,6 @@ var ModalPortal = module.exports = React.createClass({
this.closeWithoutTimeout();
},
componentDidUpdate: function() {
this.maybeFocus();
},
maybeFocus: function() {
if (this.props.isOpen)
this.focusContent();
},
focusContent: function() {
this.refs.content.getDOMNode().focus();
},
@ -176,7 +185,7 @@ var ModalPortal = module.exports = React.createClass({
},
requestClose: function() {
if (this.ownerHandlesClose)
if (this.ownerHandlesClose())
this.props.onRequestClose();
},
@ -202,13 +211,14 @@ var ModalPortal = module.exports = React.createClass({
render: function() {
return this.shouldBeClosed() ? div() : (
div({
className: this.buildClassName('overlay'),
ref: "overlay",
className: cx(this.buildClassName('overlay'), this.props.overlayClassName),
style: this.overlayStyles,
onClick: this.handleOverlayClick
},
div({
ref: "content",
className: this.buildClassName('content'),
className: cx(this.buildClassName('content'), this.props.className),
tabIndex: "-1",
onClick: stopPropagation,
onKeyDown: this.handleKeyDown
@ -220,8 +230,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) {
@ -432,6 +441,45 @@ 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.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @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)
});

File diff suppressed because one or more lines are too long

View File

@ -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;
}

View File

@ -2,6 +2,7 @@ var React = require('react');
var div = React.DOM.div;
var focusManager = require('../helpers/focusManager');
var scopeTab = require('../helpers/scopeTab');
var cx = require('react/lib/cx');
// so that our CSS is statically analyzable
var CLASS_NAMES = {
@ -33,19 +34,34 @@ 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);
}
if (newProps.isOpen === true)
this.open();
else if (newProps.isOpen === false)
this.close();
},
handleProps: function(props) {
if (props.isOpen === true)
this.open();
else if (props.isOpen === false)
this.close();
componentDidUpdate: function () {
if (this.focusAfterRender) {
this.focusContent();
this.setFocusAfterRender(false);
}
},
setFocusAfterRender: function (focus) {
this.focusAfterRender = focus;
},
open: function() {
@ -65,15 +81,6 @@ var ModalPortal = module.exports = React.createClass({
this.closeWithoutTimeout();
},
componentDidUpdate: function() {
this.maybeFocus();
},
maybeFocus: function() {
if (this.props.isOpen)
this.focusContent();
},
focusContent: function() {
this.refs.content.getDOMNode().focus();
},
@ -97,8 +104,8 @@ var ModalPortal = module.exports = React.createClass({
},
handleKeyDown: function(event) {
if (event.key == 9 /*tab*/) scopeTab(this.getDOMNode(), event);
if (event.key == 27 /*esc*/) this.requestClose();
if (event.keyCode == 9 /*tab*/) scopeTab(this.getDOMNode(), event);
if (event.keyCode == 27 /*esc*/) this.requestClose();
},
handleOverlayClick: function() {
@ -109,7 +116,7 @@ var ModalPortal = module.exports = React.createClass({
},
requestClose: function() {
if (this.ownerHandlesClose)
if (this.ownerHandlesClose())
this.props.onRequestClose();
},
@ -135,13 +142,14 @@ var ModalPortal = module.exports = React.createClass({
render: function() {
return this.shouldBeClosed() ? div() : (
div({
className: this.buildClassName('overlay'),
ref: "overlay",
className: cx(this.buildClassName('overlay'), this.props.overlayClassName),
style: this.overlayStyles,
onClick: this.handleOverlayClick
},
div({
ref: "content",
className: this.buildClassName('content'),
className: cx(this.buildClassName('content'), this.props.className),
tabIndex: "-1",
onClick: stopPropagation,
onKeyDown: this.handleKeyDown
@ -152,4 +160,3 @@ var ModalPortal = module.exports = React.createClass({
);
}
});

View File

@ -0,0 +1,11 @@
#!/bin/sh
mkdir -p dist
NODE_ENV=production node_modules/.bin/browserify lib/index.js \
-t reactify \
-t browserify-shim \
-t envify \
--detect-globals false \
-s ReactModal > dist/react-modal.js
node_modules/.bin/uglifyjs dist/react-modal.js \
--compress warnings=false > dist/react-modal.min.js

View File

@ -0,0 +1,3 @@
#!/bin/sh
node_modules/.bin/webpack-dev-server --inline --content-base examples/

View File

@ -0,0 +1,2 @@
#!/bin/sh
node_modules/rf-release/node_modules/.bin/changelog -t preview -s

View File

@ -0,0 +1,3 @@
#!/bin/sh
scripts/build
node_modules/.bin/release

View File

@ -0,0 +1,2 @@
#!/bin/sh
NODE_ENV=test node_modules/.bin/karma start "$@"

View File

@ -0,0 +1,46 @@
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' }
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin('shared.js')
]
};