diff --git a/.babelrc b/.babelrc index 9b7d435a..e72c7f45 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,17 @@ { - "presets": ["es2015", "stage-0", "react"] + "env": { + "development": { + "presets": ["es2015", "stage-0", "react"] + }, + "production": { + "presets": ["es2015", "stage-0", "react"], + "plugins": [ + [ + "transform-react-remove-prop-types", { + "mode": "wrap" + } + ] + ] + } + } } diff --git a/demo/src/components/App/components/GitHub/GitHub.js b/demo/src/components/App/components/GitHub/GitHub.js index 1fcd3e30..f5536d41 100644 --- a/demo/src/components/App/components/GitHub/GitHub.js +++ b/demo/src/components/App/components/GitHub/GitHub.js @@ -16,11 +16,9 @@ const GitHub = props => { ); }; -if (process.env.NODE_ENV !== 'production') { - GitHub.propTypes = { - user: PropTypes.string.isRequired, - repo: PropTypes.string.isRequired - }; -} +GitHub.propTypes = { + user: PropTypes.string.isRequired, + repo: PropTypes.string.isRequired +}; export default GitHub; diff --git a/demo/src/components/App/components/Header/Header.js b/demo/src/components/App/components/Header/Header.js index a22ae441..b4adf20d 100644 --- a/demo/src/components/App/components/Header/Header.js +++ b/demo/src/components/App/components/Header/Header.js @@ -11,6 +11,11 @@ const mapStateToProps = ({ header }) => ({ }); class Header extends Component { + static propTypes = { + stargazers: PropTypes.string.isRequired, + loadStargazers: PropTypes.func.isRequired + }; + componentDidMount() { this.props.loadStargazers(); } @@ -57,11 +62,4 @@ class Header extends Component { } } -if (process.env.NODE_ENV !== 'production') { - Header.propTypes = { - stargazers: PropTypes.string.isRequired, - loadStargazers: PropTypes.func.isRequired - }; -} - export default connect(mapStateToProps, { loadStargazers })(Header); diff --git a/demo/src/components/App/components/Link/Link.js b/demo/src/components/App/components/Link/Link.js index fdfd3dab..192d9382 100644 --- a/demo/src/components/App/components/Link/Link.js +++ b/demo/src/components/App/components/Link/Link.js @@ -15,14 +15,12 @@ const Link = props => { ); }; -if (process.env.NODE_ENV !== 'production') { - Link.propTypes = { - className: PropTypes.string, - href: PropTypes.string.isRequired, - underline: PropTypes.bool.isRequired, - children: PropTypes.node - }; -} +Link.propTypes = { + className: PropTypes.string, + href: PropTypes.string.isRequired, + underline: PropTypes.bool.isRequired, + children: PropTypes.node +}; Link.defaultProps = { className: null, diff --git a/package.json b/package.json index 74dacf82..cab2257e 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ "test": "nyc mocha \"test/**/*.test.js\"", "copy-static-files": "cp demo/src/index.html demo/src/components/App/components/Examples/components/Basic/autosuggest.css demo/dist/", "dist": "rm -rf dist && mkdir dist && babel src -d dist", - "demo-dist": "rm -rf demo/dist && mkdir demo/dist && npm run copy-static-files && webpack --config webpack.gh-pages.config.js", - "standalone": "webpack --config webpack.standalone.config.js && webpack --config webpack.standalone-demo.config.js", + "demo-dist": "rm -rf demo/dist && mkdir demo/dist && npm run copy-static-files && cross-env BABEL_ENV=production webpack --config webpack.gh-pages.config.js", + "standalone": "cross-env BABEL_ENV=production webpack --config webpack.standalone.config.js && webpack --config webpack.standalone-demo.config.js", "prebuild": "npm run lint && npm test", "build": "npm run dist && npm run standalone", "gh-pages-build": "npm run prebuild && npm run demo-dist", @@ -39,12 +39,14 @@ "babel-eslint": "^7.0.0", "babel-loader": "^6.2.5", "babel-plugin-react-transform": "^2.0.2", + "babel-plugin-transform-react-remove-prop-types": "^0.2.10", "babel-preset-es2015": "^6.16.0", "babel-preset-react": "^6.16.0", "babel-preset-stage-0": "^6.16.0", "babel-register": "^6.16.3", "bithound": "^1.7.0", "chai": "^3.5.0", + "cross-env": "^3.1.3", "css-loader": "^0.25.0", "es6-promise": "^4.0.5", "eslint": "^3.8.1", @@ -100,7 +102,7 @@ ], "nyc": { "statements": 96, - "branches": 90, + "branches": 91, "functions": 100, "lines": 95, "include": [ diff --git a/src/Autosuggest.js b/src/Autosuggest.js index 80c8e929..143c0a0e 100644 --- a/src/Autosuggest.js +++ b/src/Autosuggest.js @@ -13,6 +13,42 @@ const mapStateToProps = state => ({ }); class Autosuggest extends Component { + static propTypes = { + suggestions: PropTypes.array.isRequired, + onSuggestionsFetchRequested: PropTypes.func.isRequired, + onSuggestionsClearRequested: PropTypes.func, + onSuggestionSelected: PropTypes.func, + renderInputComponent: PropTypes.func, + renderSuggestionsContainer: PropTypes.func, + getSuggestionValue: PropTypes.func.isRequired, + renderSuggestion: PropTypes.func.isRequired, + inputProps: PropTypes.object.isRequired, + shouldRenderSuggestions: PropTypes.func.isRequired, + alwaysRenderSuggestions: PropTypes.bool.isRequired, + multiSection: PropTypes.bool.isRequired, + renderSectionTitle: PropTypes.func, + getSectionSuggestions: PropTypes.func, + focusInputOnSuggestionClick: PropTypes.bool.isRequired, + focusFirstSuggestion: PropTypes.bool.isRequired, + theme: PropTypes.object.isRequired, + id: PropTypes.string.isRequired, + inputRef: PropTypes.func.isRequired, + + isFocused: PropTypes.bool.isRequired, + isCollapsed: PropTypes.bool.isRequired, + focusedSectionIndex: PropTypes.number, + focusedSuggestionIndex: PropTypes.number, + valueBeforeUpDown: PropTypes.string, + + inputFocused: PropTypes.func.isRequired, + inputBlurred: PropTypes.func.isRequired, + inputChanged: PropTypes.func.isRequired, + updateFocusedSuggestion: PropTypes.func.isRequired, + resetFocusedSuggestion: PropTypes.func.isRequired, + revealSuggestions: PropTypes.func.isRequired, + closeSuggestions: PropTypes.func.isRequired + }; + componentDidMount() { document.addEventListener('mousedown', this.onDocumentMouseDown); } @@ -416,42 +452,4 @@ class Autosuggest extends Component { } } -if (process.env.NODE_ENV !== 'production') { - Autosuggest.propTypes = { - suggestions: PropTypes.array.isRequired, - onSuggestionsFetchRequested: PropTypes.func.isRequired, - onSuggestionsClearRequested: PropTypes.func, - onSuggestionSelected: PropTypes.func, - renderInputComponent: PropTypes.func, - renderSuggestionsContainer: PropTypes.func, - getSuggestionValue: PropTypes.func.isRequired, - renderSuggestion: PropTypes.func.isRequired, - inputProps: PropTypes.object.isRequired, - shouldRenderSuggestions: PropTypes.func.isRequired, - alwaysRenderSuggestions: PropTypes.bool.isRequired, - multiSection: PropTypes.bool.isRequired, - renderSectionTitle: PropTypes.func, - getSectionSuggestions: PropTypes.func, - focusInputOnSuggestionClick: PropTypes.bool.isRequired, - focusFirstSuggestion: PropTypes.bool.isRequired, - theme: PropTypes.object.isRequired, - id: PropTypes.string.isRequired, - inputRef: PropTypes.func.isRequired, - - isFocused: PropTypes.bool.isRequired, - isCollapsed: PropTypes.bool.isRequired, - focusedSectionIndex: PropTypes.number, - focusedSuggestionIndex: PropTypes.number, - valueBeforeUpDown: PropTypes.string, - - inputFocused: PropTypes.func.isRequired, - inputBlurred: PropTypes.func.isRequired, - inputChanged: PropTypes.func.isRequired, - updateFocusedSuggestion: PropTypes.func.isRequired, - resetFocusedSuggestion: PropTypes.func.isRequired, - revealSuggestions: PropTypes.func.isRequired, - closeSuggestions: PropTypes.func.isRequired - }; -} - export default connect(mapStateToProps, actionCreators)(Autosuggest); diff --git a/src/AutosuggestContainer.js b/src/AutosuggestContainer.js index 5d96cc8c..0b53d5fd 100644 --- a/src/AutosuggestContainer.js +++ b/src/AutosuggestContainer.js @@ -47,6 +47,61 @@ const mapToAutowhateverTheme = theme => { }; export default class AutosuggestContainer extends Component { + static propTypes = { + suggestions: PropTypes.array.isRequired, + onSuggestionsFetchRequested: (props, propName) => { + const onSuggestionsFetchRequested = props[propName]; + + if (typeof onSuggestionsFetchRequested !== 'function') { + throw new Error('\'onSuggestionsFetchRequested\' must be implemented. See: https://github.com/moroshko/react-autosuggest#onSuggestionsFetchRequestedProp'); + } + }, + onSuggestionsClearRequested: (props, propName) => { + const onSuggestionsClearRequested = props[propName]; + + if (props.alwaysRenderSuggestions === false && typeof onSuggestionsClearRequested !== 'function') { + throw new Error('\'onSuggestionsClearRequested\' must be implemented. See: https://github.com/moroshko/react-autosuggest#onSuggestionsClearRequestedProp'); + } + }, + onSuggestionSelected: PropTypes.func, + renderInputComponent: PropTypes.func, + renderSuggestionsContainer: PropTypes.func, + getSuggestionValue: PropTypes.func.isRequired, + renderSuggestion: PropTypes.func.isRequired, + inputProps: (props, propName) => { + const inputProps = props[propName]; + + if (!inputProps.hasOwnProperty('value')) { + throw new Error('\'inputProps\' must have \'value\'.'); + } + + if (!inputProps.hasOwnProperty('onChange')) { + throw new Error('\'inputProps\' must have \'onChange\'.'); + } + }, + shouldRenderSuggestions: PropTypes.func, + alwaysRenderSuggestions: PropTypes.bool, + multiSection: PropTypes.bool, + renderSectionTitle: (props, propName) => { + const renderSectionTitle = props[propName]; + + if (props.multiSection === true && typeof renderSectionTitle !== 'function') { + throw new Error('\'renderSectionTitle\' must be implemented. See: https://github.com/moroshko/react-autosuggest#renderSectionTitleProp'); + } + }, + getSectionSuggestions: (props, propName) => { + const getSectionSuggestions = props[propName]; + + if (props.multiSection === true && typeof getSectionSuggestions !== 'function') { + throw new Error('\'getSectionSuggestions\' must be implemented. See: https://github.com/moroshko/react-autosuggest#getSectionSuggestionsProp'); + } + }, + focusInputOnSuggestionClick: PropTypes.bool, + focusFirstSuggestion: PropTypes.bool, + theme: PropTypes.object, + id: PropTypes.string + }; + static defaultProps = { shouldRenderSuggestions: defaultShouldRenderSuggestions, alwaysRenderSuggestions: false, @@ -111,60 +166,3 @@ export default class AutosuggestContainer extends Component { ); } } - -if (process.env.NODE_ENV !== 'production') { - AutosuggestContainer.propTypes = { - suggestions: PropTypes.array.isRequired, - onSuggestionsFetchRequested: (props, propName) => { - const onSuggestionsFetchRequested = props[propName]; - - if (typeof onSuggestionsFetchRequested !== 'function') { - throw new Error('\'onSuggestionsFetchRequested\' must be implemented. See: https://github.com/moroshko/react-autosuggest#onSuggestionsFetchRequestedProp'); - } - }, - onSuggestionsClearRequested: (props, propName) => { - const onSuggestionsClearRequested = props[propName]; - - if (props.alwaysRenderSuggestions === false && typeof onSuggestionsClearRequested !== 'function') { - throw new Error('\'onSuggestionsClearRequested\' must be implemented. See: https://github.com/moroshko/react-autosuggest#onSuggestionsClearRequestedProp'); - } - }, - onSuggestionSelected: PropTypes.func, - renderInputComponent: PropTypes.func, - renderSuggestionsContainer: PropTypes.func, - getSuggestionValue: PropTypes.func.isRequired, - renderSuggestion: PropTypes.func.isRequired, - inputProps: (props, propName) => { - const inputProps = props[propName]; - - if (!inputProps.hasOwnProperty('value')) { - throw new Error('\'inputProps\' must have \'value\'.'); - } - - if (!inputProps.hasOwnProperty('onChange')) { - throw new Error('\'inputProps\' must have \'onChange\'.'); - } - }, - shouldRenderSuggestions: PropTypes.func, - alwaysRenderSuggestions: PropTypes.bool, - multiSection: PropTypes.bool, - renderSectionTitle: (props, propName) => { - const renderSectionTitle = props[propName]; - - if (props.multiSection === true && typeof renderSectionTitle !== 'function') { - throw new Error('\'renderSectionTitle\' must be implemented. See: https://github.com/moroshko/react-autosuggest#renderSectionTitleProp'); - } - }, - getSectionSuggestions: (props, propName) => { - const getSectionSuggestions = props[propName]; - - if (props.multiSection === true && typeof getSectionSuggestions !== 'function') { - throw new Error('\'getSectionSuggestions\' must be implemented. See: https://github.com/moroshko/react-autosuggest#getSectionSuggestionsProp'); - } - }, - focusInputOnSuggestionClick: PropTypes.bool, - focusFirstSuggestion: PropTypes.bool, - theme: PropTypes.object, - id: PropTypes.string - }; -}