diff --git a/components/autocomplete/Autocomplete.jsx b/components/autocomplete/Autocomplete.jsx
index e340298c..8845e834 100644
--- a/components/autocomplete/Autocomplete.jsx
+++ b/components/autocomplete/Autocomplete.jsx
@@ -1,206 +1,206 @@
-//import React from 'react';
-//import ReactDOM from 'react-dom';
-//import ClassNames from 'classnames';
-//import Input from '../input';
-//import events from '../utils/events';
-//import style from './style';
-//
-//const POSITION = {
-// AUTO: 'auto',
-// DOWN: 'down',
-// UP: 'up'
-//};
-//
-//class Autocomplete extends React.Component {
-// static propTypes = {
-// className: React.PropTypes.string,
-// direction: React.PropTypes.oneOf(['auto', 'up', 'down']),
-// disabled: React.PropTypes.bool,
-// error: React.PropTypes.string,
-// label: React.PropTypes.string,
-// multiple: React.PropTypes.bool,
-// onChange: React.PropTypes.func,
-// source: React.PropTypes.any,
-// value: React.PropTypes.any
-// };
-//
-// static defaultProps = {
-// className: '',
-// direction: 'auto',
-// multiple: true,
-// source: {}
-// };
-//
-// state = {
-// direction: this.props.direction,
-// focus: false,
-// query: this.query(this.props.value)
-// };
-//
-// componentWillReceiveProps (nextProps) {
-// if (!this.props.multiple) {
-// this.setState({query: nextProps.value});
-// }
-// }
-//
-// shouldComponentUpdate (nextProps, nextState) {
-// if (!this.state.focus && nextState.focus && this.props.direction === POSITION.AUTO) {
-// const direction = this.calculateDirection();
-// if (this.state.direction !== direction) {
-// this.setState({ direction });
-// return false;
-// }
-// }
-// return true;
-// }
-//
-// handleChange = (keys, event) => {
-// const key = this.props.multiple ? keys : keys[0];
-// const query = this.query(key);
-// if (this.props.onChange) this.props.onChange(key, event);
-// this.setState({ focus: false, query }, () => { this.refs.input.blur(); });
-// };
-//
-// handleQueryBlur = () => {
-// if (this.state.focus) this.setState({focus: false});
-// };
-//
-// handleQueryChange = (value) => {
-// this.setState({query: value});
-// };
-//
-// handleQueryFocus = () => {
-// this.refs.suggestions.scrollTop = 0;
-// this.setState({active: '', focus: true});
-// };
-//
-// handleQueryKeyUp = (event) => {
-// if (event.which === 13 && this.state.active) this.select(this.state.active, event);
-// if (event.which === 27) this.refs.input.blur();
-// if ([40, 38].indexOf(event.which) !== -1) {
-// const suggestionsKeys = [...this.suggestions().keys()];
-// let index = suggestionsKeys.indexOf(this.state.active) + (event.which === 40 ? +1 : -1);
-// if (index < 0) index = suggestionsKeys.length - 1;
-// if (index >= suggestionsKeys.length) index = 0;
-// this.setState({active: suggestionsKeys[index]});
-// }
-// };
-//
-// handleSuggestionHover = (key) => {
-// this.setState({active: key});
-// };
-//
-// calculateDirection () {
-// if (this.props.direction === 'auto') {
-// const client = ReactDOM.findDOMNode(this.refs.input).getBoundingClientRect();
-// const screen_height = window.innerHeight || document.documentElement.offsetHeight;
-// const up = client.top > ((screen_height / 2) + client.height);
-// return up ? 'up' : 'down';
-// } else {
-// return this.props.direction;
-// }
-// }
-//
-// query (key) {
-// return !this.props.multiple && this.props.value ? this.source().get(key) : '';
-// }
-//
-// suggestions2 () {
-// const suggestions2 = new Map();
-// const query = this.state.query.toLowerCase().trim() || '';
-// const values = this.values();
-// for (const [key, value] of this.source()) {
-// if (!values.has(key) && value.toLowerCase().trim().startsWith(query)) {
-// suggestions2.set(key, value);
-// }
-// }
-// return suggestions2;
-// }
-//
-// source () {
-// const { source } = this.props;
-// if (source.hasOwnProperty('length')) {
-// return new Map(source.map((item) => [item, item]));
-// } else {
-// return new Map(Object.keys(source).map((key) => [key, source[key]]));
-// }
-// }
-//
-// values () {
-// const valueMap = new Map();
-// const values = this.props.multiple ? this.props.value : [this.props.value];
-// for (const [k, v] of this.source()) {
-// if (values.indexOf(k) !== -1) valueMap.set(k, v);
-// }
-// return valueMap;
-// }
-//
-// select (key, event) {
-// events.pauseEvent(event);
-// const values = this.values(this.props.value);
-// this.handleChange([key, ...values.keys()], event);
-// }
-//
-// unselect (key, event) {
-// const values = this.values(this.props.value);
-// values.delete(key);
-// this.handleChange([...values.keys()], event);
-// }
-//
-// renderSelected () {
-// if (this.props.multiple) {
-// const selectedItems = [...this.values()].map(([key, value]) => {
-// return
{value};
-// });
-//
-// return ;
-// }
-// }
-//
-// renderSuggestions () {
-// const suggestions2 = [...this.suggestions2()].map(([key, value]) => {
-// const className = ClassNames(style.suggestion, {[style.active]: this.state.active === key});
-// return (
-//
-// {value}
-//
-// );
-// });
-//
-// const className = ClassNames(style.suggestions2, {[style.up]: this.state.direction === 'up'});
-// return ;
-// }
-//
-// render () {
-// const {error, label, ...other} = this.props;
-// const className = ClassNames(style.root, {
-// [style.focus]: this.state.focus
-// }, this.props.className);
-//
-// return (
-//
-// {this.renderSelected()}
-//
-// {this.renderSuggestions()}
-//
-// );
-// }
-//}
-//
-//export default Autocomplete;
+import React from 'react';
+import ReactDOM from 'react-dom';
+import ClassNames from 'classnames';
+import Input from '../input';
+import events from '../utils/events';
+import style from './style';
+
+const POSITION = {
+ AUTO: 'auto',
+ DOWN: 'down',
+ UP: 'up'
+};
+
+class Autocomplete extends React.Component {
+ static propTypes = {
+ className: React.PropTypes.string,
+ direction: React.PropTypes.oneOf(['auto', 'up', 'down']),
+ disabled: React.PropTypes.bool,
+ error: React.PropTypes.string,
+ label: React.PropTypes.string,
+ multiple: React.PropTypes.bool,
+ onChange: React.PropTypes.func,
+ source: React.PropTypes.any,
+ value: React.PropTypes.any
+ };
+
+ static defaultProps = {
+ className: '',
+ direction: 'auto',
+ multiple: true,
+ source: {}
+ };
+
+ state = {
+ direction: this.props.direction,
+ focus: false,
+ query: this.query(this.props.value)
+ };
+
+ componentWillReceiveProps (nextProps) {
+ if (!this.props.multiple) {
+ this.setState({query: nextProps.value});
+ }
+ }
+
+ shouldComponentUpdate (nextProps, nextState) {
+ if (!this.state.focus && nextState.focus && this.props.direction === POSITION.AUTO) {
+ const direction = this.calculateDirection();
+ if (this.state.direction !== direction) {
+ this.setState({ direction });
+ return false;
+ }
+ }
+ return true;
+ }
+
+ handleChange = (keys, event) => {
+ const key = this.props.multiple ? keys : keys[0];
+ const query = this.query(key);
+ if (this.props.onChange) this.props.onChange(key, event);
+ this.setState({ focus: false, query }, () => { this.refs.input.blur(); });
+ };
+
+ handleQueryBlur = () => {
+ if (this.state.focus) this.setState({focus: false});
+ };
+
+ handleQueryChange = (value) => {
+ this.setState({query: value});
+ };
+
+ handleQueryFocus = () => {
+ this.refs.suggestions.scrollTop = 0;
+ this.setState({active: '', focus: true});
+ };
+
+ handleQueryKeyUp = (event) => {
+ if (event.which === 13 && this.state.active) this.select(this.state.active, event);
+ if (event.which === 27) this.refs.input.blur();
+ if ([40, 38].indexOf(event.which) !== -1) {
+ const suggestionsKeys = [...this.suggestions().keys()];
+ let index = suggestionsKeys.indexOf(this.state.active) + (event.which === 40 ? +1 : -1);
+ if (index < 0) index = suggestionsKeys.length - 1;
+ if (index >= suggestionsKeys.length) index = 0;
+ this.setState({active: suggestionsKeys[index]});
+ }
+ };
+
+ handleSuggestionHover = (key) => {
+ this.setState({active: key});
+ };
+
+ calculateDirection () {
+ if (this.props.direction === 'auto') {
+ const client = ReactDOM.findDOMNode(this.refs.input).getBoundingClientRect();
+ const screen_height = window.innerHeight || document.documentElement.offsetHeight;
+ const up = client.top > ((screen_height / 2) + client.height);
+ return up ? 'up' : 'down';
+ } else {
+ return this.props.direction;
+ }
+ }
+
+ query (key) {
+ return !this.props.multiple && this.props.value ? this.source().get(key) : '';
+ }
+
+ suggestions () {
+ const suggest = new Map();
+ const query = this.state.query.toLowerCase().trim() || '';
+ const values = this.values();
+ for (const [key, value] of this.source()) {
+ if (!values.has(key) && value.toLowerCase().trim().startsWith(query)) {
+ suggest.set(key, value);
+ }
+ }
+ return suggest;
+ }
+
+ source () {
+ const { source: src } = this.props;
+ if (src.hasOwnProperty('length')) {
+ return new Map(src.map((item) => [item, item]));
+ } else {
+ return new Map(Object.keys(src).map((key) => [key, src[key]]));
+ }
+ }
+
+ values () {
+ const valueMap = new Map();
+ const vals = this.props.multiple ? this.props.value : [this.props.value];
+ for (const [k, v] of this.source()) {
+ if (vals.indexOf(k) !== -1) valueMap.set(k, v);
+ }
+ return valueMap;
+ }
+
+ select (key, event) {
+ events.pauseEvent(event);
+ const values = this.values(this.props.value);
+ this.handleChange([key, ...values.keys()], event);
+ }
+
+ unselect (key, event) {
+ const values = this.values(this.props.value);
+ values.delete(key);
+ this.handleChange([...values.keys()], event);
+ }
+
+ renderSelected () {
+ if (this.props.multiple) {
+ const selectedItems = [...this.values()].map(([key, value]) => {
+ return {value};
+ });
+
+ return ;
+ }
+ }
+
+ renderSuggestions () {
+ const suggestions = [...this.suggestions()].map(([key, value]) => {
+ const className = ClassNames(style.suggestion, {[style.active]: this.state.active === key});
+ return (
+
+ {value}
+
+ );
+ });
+
+ const className = ClassNames(style.suggestions, {[style.up]: this.state.direction === 'up'});
+ return ;
+ }
+
+ render () {
+ const {error, label, ...other} = this.props;
+ const className = ClassNames(style.root, {
+ [style.focus]: this.state.focus
+ }, this.props.className);
+
+ return (
+
+ {this.renderSelected()}
+
+ {this.renderSuggestions()}
+
+ );
+ }
+}
+
+export default Autocomplete;
diff --git a/components/utils/index.js b/components/utils/index.js
index c48fd647..c4b25603 100644
--- a/components/utils/index.js
+++ b/components/utils/index.js
@@ -4,3 +4,7 @@ import time from './time';
import utils from './utils';
export default {events, prefixer, time, utils};
+export {events};
+export {prefixer};
+export {time};
+export {utils};
diff --git a/server.js b/server.js
index 5c2ad483..a0942f30 100644
--- a/server.js
+++ b/server.js
@@ -17,14 +17,14 @@ app.use(require('webpack-dev-middleware')(compiler, {
app.use(require('webpack-hot-middleware')(compiler));
app.get('*', function (req, res) {
- res.sendFile(path.join(__dirname, './www/index.html'));
+ res.sendFile(path.join(__dirname, './spec/index.html'));
});
-app.listen(8081, '0.0.0.0', function (err) {
+app.listen(8080, '0.0.0.0', function (err) {
if (err) {
console.log(err);
return;
}
- console.log('Listening at http://0.0.0.0:8081');
+ console.log('Listening at http://0.0.0.0:8080');
});
diff --git a/webpack.config.development.js b/webpack.config.development.js
index 8c84b122..24d0da98 100644
--- a/webpack.config.development.js
+++ b/webpack.config.development.js
@@ -23,8 +23,8 @@ module.exports = {
loaders: [
{
test: /\.(js|jsx)$/,
- loader: ['babel'],
- include: path.join(__dirname, 'spec')
+ loader: 'babel',
+ exclude: /(node_modules)/
}, {
test: /\.(scss|css)$/,
loader: ExtractTextPlugin.extract('style', 'css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass?sourceMap')