From dc871a612374325555230c2189bfe45c908df57e Mon Sep 17 00:00:00 2001
From: ZeroCho
Date: Tue, 2 Aug 2016 17:00:38 +0900
Subject: [PATCH] fix for IE
---
.babelrc | 14 +
.eslintrc | 3 +
.gitignore | 39 ++
ISSUE_TEMPLATE.md | 5 +
LICENSE | 24 ++
README.md | 663 ++++++++++++++++++++++++++++++++
dist/extendReactClass.js | 91 +++++
dist/generateAppendClassName.js | 53 +++
dist/index.js | 77 ++++
dist/isIterable.js | 41 ++
dist/linkClass.js | 106 +++++
dist/makeConfiguration.js | 55 +++
dist/parseStyleName.js | 38 ++
dist/simple-map.js | 44 +++
dist/wrapStatelessFunction.js | 69 ++++
package.json | 51 +++
src/extendReactClass.js | 50 +++
src/generateAppendClassName.js | 41 ++
src/index.js | 56 +++
src/isIterable.js | 24 ++
src/linkClass.js | 73 ++++
src/makeConfiguration.js | 33 ++
src/parseStyleName.js | 22 ++
src/simple-map.js | 27 ++
src/wrapStatelessFunction.js | 41 ++
25 files changed, 1740 insertions(+)
create mode 100644 .babelrc
create mode 100644 .eslintrc
create mode 100644 .gitignore
create mode 100644 ISSUE_TEMPLATE.md
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 dist/extendReactClass.js
create mode 100644 dist/generateAppendClassName.js
create mode 100644 dist/index.js
create mode 100644 dist/isIterable.js
create mode 100644 dist/linkClass.js
create mode 100644 dist/makeConfiguration.js
create mode 100644 dist/parseStyleName.js
create mode 100644 dist/simple-map.js
create mode 100644 dist/wrapStatelessFunction.js
create mode 100644 package.json
create mode 100644 src/extendReactClass.js
create mode 100644 src/generateAppendClassName.js
create mode 100644 src/index.js
create mode 100644 src/isIterable.js
create mode 100644 src/linkClass.js
create mode 100644 src/makeConfiguration.js
create mode 100644 src/parseStyleName.js
create mode 100644 src/simple-map.js
create mode 100644 src/wrapStatelessFunction.js
diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..f651443
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,14 @@
+{
+ "presets": [
+ "es2015",
+ "stage-0",
+ "react"
+ ],
+ "plugins": [
+ "add-module-exports",
+ "lodash",
+ "transform-class-properties",
+ ["transform-es2015-classes", { "loose": true }],
+ "transform-proto-to-assign"
+ ]
+}
\ No newline at end of file
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..84b918b
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,3 @@
+{
+ "extends": "canonical"
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bc32025
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,39 @@
+# Created by .ignore support plugin (hsz.mobi)
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/dictionaries
+.idea/vcs.xml
+.idea/jsLibraryMappings.xml
+.idea/dataSources.ids
+.idea/dataSources.xml
+.idea/dataSources.local.xml
+.idea/sqlDataSources.xml
+.idea/dynamic.xml
+.idea/uiDesigner.xml
+.idea/gradle.xml
+.idea/libraries
+.idea/mongoSettings.xml
+*.iws
+/out/
+.idea_modules/
+atlassian-ide-plugin.xml
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+logs
+*.log
+npm-debug.log*
+pids
+*.pid
+*.seed
+lib-cov
+coverage
+.nyc_output
+.grunt
+.lock-wscript
+build/Release
+node_modules
+jspm_packages
+.npm
+.node_repl_history
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..109eb2e
--- /dev/null
+++ b/ISSUE_TEMPLATE.md
@@ -0,0 +1,5 @@
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..183e8d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2015, Gajus Kuizinas (http://gajus.com/)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5c8c0ef
--- /dev/null
+++ b/README.md
@@ -0,0 +1,663 @@
+# React CSS Modules
+
+[](https://travis-ci.org/gajus/react-css-modules)
+[](https://www.npmjs.org/package/react-css-modules)
+[](https://github.com/gajus/canonical)
+
+
+
+React CSS Modules implement automatic mapping of CSS modules. Every CSS class is assigned a local-scoped identifier with a global unique name. CSS Modules enable a modular and reusable CSS!
+
+- [CSS Modules](#css-modules)
+ - [webpack `css-loader`](#webpack-css-loader)
+- [What's the Problem?](#whats-the-problem)
+- [The Implementation](#the-implementation)
+- [Usage](#usage)
+ - [Module Bundler](#module-bundler)
+ - [webpack](#webpack)
+ - [Development](#development)
+ - [Production](#production)
+ - [Browserify](#browserify)
+ - [Extending Component Styles](#extending-component-styles)
+ - [`styles` Property](#styles-property)
+ - [Loops and Child Components](#loops-and-child-components)
+ - [Decorator](#decorator)
+ - [Options](#options)
+ - [`allowMultiple`](#allowmultiple)
+ - [`errorWhenNotFound`](#errorwhennotfound)
+- [SASS, SCSS, LESS and other CSS Preprocessors](#sass-scss-less-and-other-css-preprocessors)
+ - [Enable Sourcemaps](#enable-sourcemaps)
+- [Class Composition](#class-composition)
+ - [What Problems does Class Composition Solve?](#what-problems-does-class-composition-solve)
+ - [Class Composition Using CSS Preprocessors](#class-composition-using-css-preprocessors)
+- [SASS, SCSS, LESS and other CSS Preprocessors](#sass-scss-less-and-other-css-preprocessors)
+- [Global CSS](#global-css)
+- [Multiple CSS Modules](#multiple-css-modules)
+
+## CSS Modules
+
+[CSS Modules](https://github.com/css-modules/css-modules) are awesome. If you are not familiar with CSS Modules, it is a concept of using a module bundler such as [webpack](http://webpack.github.io/docs/) to load CSS scoped to a particular document. CSS module loader will generate a unique name for a each CSS class at the time of loading the CSS document ([Interoperable CSS](https://github.com/css-modules/icss) to be precise). To see CSS Modules in practice, [webpack-demo](https://css-modules.github.io/webpack-demo/).
+
+In the context of React, CSS Modules look like this:
+
+```js
+import React from 'react';
+import styles from './table.css';
+
+export default class Table extends React.Component {
+ render () {
+ return ;
+ }
+}
+```
+
+Rendering the component will produce a markup similar to:
+
+```js
+
+```
+
+and a corresponding CSS file that matches those CSS classes.
+
+Awesome!
+
+### webpack `css-loader`
+
+[CSS Modules](https://github.com/css-modules/css-modules) is a specification that can be implemented in multiple ways. `react-css-modules` leverages as existing CSS Modules implementation webpack [css-loader](https://github.com/webpack/css-loader#css-modules).
+
+## What's the Problem?
+
+webpack [css-loader](https://github.com/webpack/css-loader#css-modules) itself has several disadvantages:
+
+* You have to use `camelCase` CSS class names.
+* You have to use `styles` object whenever constructing a `className`.
+* Mixing CSS Modules and global CSS classes is cumbersome.
+* Reference to an undefined CSS Module resolves to `undefined` without a warning.
+
+React CSS Modules component automates loading of CSS Modules using `styleName` property, e.g.
+
+```js
+import React from 'react';
+import CSSModules from 'react-css-modules';
+import styles from './table.css';
+
+class Table extends React.Component {
+ render () {
+ return ;
+ }
+}
+
+export default CSSModules(Table, styles);
+```
+
+Using `react-css-modules`:
+
+* You are not forced to use the `camelCase` naming convention.
+* You do not need to refer to the `styles` object every time you use a CSS Module.
+* There is clear distinction between global CSS and CSS Modules, e.g.
+
+```js
+
+```
+
+* You are warned when `styleName` refers to an undefined CSS Module ([`errorWhenNotFound`](#errorwhennotfound) option).
+* You can enforce use of a single CSS module per `ReactElement` ([`allowMultiple`](#allowmultiple) option).
+
+## The Implementation
+
+`react-css-modules` extends `render` method of the target component. It will use the value of `styleName` to look for CSS Modules in the associated styles object and will append the matching unique CSS class names to the `ReactElement` `className` property value.
+
+[Awesome!](https://twitter.com/intent/retweet?tweet_id=636497036603428864)
+
+## Usage
+
+Setup consists of:
+
+* Setting up a [module bundler](#module-bundler) to load the [Interoperable CSS](https://github.com/css-modules/icss).
+* [Decorating](#decorator) your component using `react-css-modules`.
+
+### Module Bundler
+
+#### webpack
+
+##### Development
+
+In development environment, you want to [Enable Sourcemaps](#enable-sourcemaps) and webpack [Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement.html) (HMR). [`style-loader`](https://github.com/webpack/style-loader) already supports HMR. Therefore, Hot Module Replacement will work out of the box.
+
+Setup:
+
+* Install [`style-loader`](https://www.npmjs.com/package/style-loader).
+* Install [`css-loader`](https://www.npmjs.com/package/css-loader).
+* Setup `/\.css$/` loader:
+
+```js
+{
+ test: /\.css$/,
+ loaders: [
+ 'style?sourceMap',
+ 'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]'
+ ]
+}
+```
+
+##### Production
+
+In production environment, you want to extract chunks of CSS into a single stylesheet file.
+
+> Advantages:
+>
+> * Fewer style tags (older IE has a limit)
+> * CSS SourceMap (with `devtool: "source-map"` and `css-loader?sourceMap`)
+> * CSS requested in parallel
+> * CSS cached separate
+> * Faster runtime (less code and DOM operations)
+>
+> Caveats:
+>
+> * Additional HTTP request
+> * Longer compilation time
+> * More complex configuration
+> * No runtime public path modification
+> * No Hot Module Replacement
+
+– [extract-text-webpack-plugin](https://github.com/webpack/extract-text-webpack-plugin)
+
+Setup:
+
+* Install [`style-loader`](https://www.npmjs.com/package/style-loader).
+* Install [`css-loader`](https://www.npmjs.com/package/css-loader).
+* Use [`extract-text-webpack-plugin`](https://www.npmjs.com/package/extract-text-webpack-plugin) to extract chunks of CSS into a single stylesheet.
+* Setup `/\.css$/` loader:
+
+```js
+{
+ test: /\.css$/,
+ loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]')
+}
+```
+
+* Setup `extract-text-webpack-plugin` plugin:
+
+```js
+new ExtractTextPlugin('app.css', {
+ allChunks: true
+})
+```
+
+Refer to [webpack-demo](https://github.com/css-modules/webpack-demo) or [react-css-modules-examples](https://github.com/gajus/react-css-modules-examples) for an example of a complete setup.
+
+##### Browserify
+
+Refer to [`css-modulesify`](https://github.com/css-modules/css-modulesify).
+
+### Extending Component Styles
+
+Use `styles` property to overwrite the default component styles.
+
+Explanation using `Table` component:
+
+```js
+import React from 'react';
+import CSSModules from 'react-css-modules';
+import styles from './table.css';
+
+class Table extends React.Component {
+ render () {
+ return ;
+ }
+}
+
+export default CSSModules(Table, styles);
+```
+
+In this example, `CSSModules` is used to decorate `Table` component using `./table.css` CSS Modules. When `Table` component is rendered, it will use the properties of the `styles` object to construct `className` values.
+
+Using `styles` property you can overwrite the default component `styles` object, e.g.
+
+```js
+import customStyles from './table-custom-styles.css';
+
+;
+```
+
+[Interoperable CSS](https://github.com/css-modules/icss) can [extend other ICSS](https://github.com/css-modules/css-modules#dependencies). Use this feature to extend default styles, e.g.
+
+```css
+/* table-custom-styles.css */
+.table {
+ composes: table from './table.css';
+}
+
+.row {
+ composes: row from './table.css';
+}
+
+/* .cell {
+ composes: cell from './table.css';
+} */
+
+.table {
+ width: 400px;
+}
+
+.cell {
+ float: left; width: 154px; background: #eee; padding: 10px; margin: 10px 0 10px 10px;
+}
+```
+
+In this example, `table-custom-styles.css` selectively extends `table.css` (the default styles of `Table` component).
+
+Refer to the [`UsingStylesProperty` example](https://github.com/gajus/react-css-modules-examples/tree/master/src/UsingStylesProperty) for an example of a working implementation.
+
+### `styles` Property
+
+Decorated components inherit `styles` property that describes the mapping between CSS modules and CSS classes.
+
+```js
+class extends React.Component {
+ render () {
+ ;
+ }
+}
+```
+
+In the above example, `styleName='foo'` and `className={this.props.styles.foo}` are equivalent.
+
+`styles` property is designed to enable component decoration of [Loops and Child Components](#loops-and-child-components).
+
+### Loops and Child Components
+
+`styleName` cannot be used to define styles of a `ReactElement` that will be generated by another component, e.g.
+
+```js
+import React from 'react';
+import CSSModules from 'react-css-modules';
+import List from './List';
+import styles from './table.css';
+
+class CustomList extends React.Component {
+ render () {
+ let itemTemplate;
+
+ itemTemplate = (name) => {
+ return {name};
+ };
+
+ return
;
+ }
+}
+
+export default CSSModules(CustomList, styles);
+```
+
+The above example will not work. `CSSModules` is used to decorate `CustomList` component. However, it is the `List` component that will render `itemTemplate`.
+
+For that purpose, the decorated component inherits [`styles` property](#styles-property) that you can use just as a regular CSS Modules object. The earlier example can be therefore rewritten to:
+
+```js
+import React from 'react';
+import CSSModules from 'react-css-modules';
+import List from './List';
+import styles from './table.css';
+
+class CustomList extends React.Component {
+ render () {
+ let itemTemplate;
+
+ itemTemplate = (name) => {
+ return {name};
+ };
+
+ return
;
+ }
+}
+
+export default CSSModules(CustomList, styles);
+```
+
+You can use `styleName` property within the child component if you decorate the child component using `CSSModules` before passing it to the rendering component, e.g.
+
+```js
+import React from 'react';
+import CSSModules from 'react-css-modules';
+import List from './List';
+import styles from './table.css';
+
+class CustomList extends React.Component {
+ render () {
+ let itemTemplate;
+
+ itemTemplate = (name) => {
+ return {name};
+ };
+
+ itemTemplate = CSSModules(itemTemplate, this.props.styles);
+
+ return
;
+ }
+}
+
+export default CSSModules(CustomList, styles);
+```
+
+### Decorator
+
+```js
+/**
+ * @typedef CSSModules~Options
+ * @see {@link https://github.com/gajus/react-css-modules#options}
+ * @property {Boolean} allowMultiple
+ * @property {Boolean} errorWhenNotFound
+ */
+
+/**
+ * @param {Function} Component
+ * @param {Object} defaultStyles CSS Modules class map.
+ * @param {CSSModules~Options} options
+ * @return {Function}
+ */
+```
+
+You need to decorate your component using `react-css-modules`, e.g.
+
+```js
+import React from 'react';
+import CSSModules from 'react-css-modules';
+import styles from './table.css';
+
+class Table extends React.Component {
+ render () {
+ return ;
+ }
+}
+
+export default CSSModules(Table, styles);
+```
+
+Thats it!
+
+As the name implies, `react-css-modules` is compatible with the [ES7 decorators](https://github.com/wycats/javascript-decorators) syntax:
+
+```js
+import React from 'react';
+import CSSModules from 'react-css-modules';
+import styles from './table.css';
+
+@CSSModules(styles)
+export default class extends React.Component {
+ render () {
+ return ;
+ }
+}
+```
+
+[Awesome!](https://twitter.com/intent/retweet?tweet_id=636497036603428864)
+
+Refer to the [react-css-modules-examples](https://github.com/gajus/react-css-modules-examples) repository for an example of webpack setup.
+
+### Options
+
+Options are supplied as the third parameter to the `CSSModules` function.
+
+```js
+CSSModules(Component, styles, options);
+```
+
+or as a second parameter to the decorator:
+
+```js
+@CSSModules(styles, options);
+```
+
+#### `allowMultiple`
+
+Default: `false`.
+
+Allows multiple CSS Module names.
+
+When `false`, the following will cause an error:
+
+```js
+
+```
+
+#### `errorWhenNotFound`
+
+Default: `true`.
+
+Throws an error when `styleName` cannot be mapped to an existing CSS Module.
+
+## SASS, SCSS, LESS and other CSS Preprocessors
+
+[Interoperable CSS](https://github.com/css-modules/icss) is compatible with the CSS preprocessors. To use a preprocessor, all you need to do is add the preprocessor to the chain of loaders, e.g. in the case of webpack it is as simple as installing `sass-loader` and adding `!sass` to the end of the `style-loader` loader query (loaders are processed from right to left):
+
+```js
+{
+ test: /\.scss$/,
+ loaders: [
+ 'style',
+ 'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
+ 'resolve-url',
+ 'sass'
+ ]
+}
+```
+
+### Enable Sourcemaps
+
+To enable CSS Source maps, add `sourceMap` parameter to the css-loader and to the `sass-loader`:
+
+```js
+{
+ test: /\.scss$/,
+ loaders: [
+ 'style?sourceMap',
+ 'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
+ 'resolve-url',
+ 'sass?sourceMap'
+ ]
+}
+```
+
+## Class Composition
+
+CSS Modules promote composition pattern, i.e. every CSS Module that is used in a component should define all properties required to describe an element, e.g.
+
+```css
+.box {
+ width: 100px;
+ height: 100px;
+}
+
+.empty {
+ composes: box;
+
+ background: #4CAF50;
+}
+
+.full {
+ composes: box;
+
+ background: #F44336;
+}
+```
+
+Composition promotes better separation of markup and style using semantics that would be hard to achieve without CSS Modules.
+
+Because CSS Module names are local, it is perfectly fine to use generic style names such as "empty" or "full", without "box-" prefix.
+
+To learn more about composing CSS rules, I suggest reading Glen Maddern article about [CSS Modules](http://glenmaddern.com/articles/css-modules) and the official [spec of the CSS Modules](https://github.com/css-modules/css-modules).
+
+### What Problems does Class Composition Solve?
+
+Consider the same example in CSS and HTML:
+
+```css
+.box {
+ width: 100px;
+ height: 100px;
+}
+
+.box-empty {
+ background: #4CAF50;
+}
+
+.box-full {
+ background: #F44336;
+}
+```
+
+```html
+
+```
+
+This pattern emerged with the advent of OOCSS. The biggest disadvantage of this implementation is that you will need to change HTML almost every time you want to change the style.
+
+### Class Composition Using CSS Preprocessors
+
+This section of the document is included as a learning exercise to broaden the understanding about the origin of Class Composition. CSS Modules support a native method of composting CSS Modules using [`composes`](https://github.com/css-modules/css-modules#composition) keyword. CSS Preprocessor is not required.
+
+You can write compositions in SCSS using [`@extend`](http://sass-lang.com/documentation/file.SASS_REFERENCE.html#extend) keyword and using [Mixin Directives](http://sass-lang.com/documentation/file.SASS_REFERENCE.html#mixins), e.g.
+
+Using `@extend`:
+
+```css
+%box {
+ width: 100px;
+ height: 100px;
+}
+
+.box-empty {
+ @extend %box;
+
+ background: #4CAF50;
+}
+
+.box-full {
+ @extend %box;
+
+ background: #F44336;
+}
+```
+
+This translates to:
+
+```css
+.box-empty,
+.box-full {
+ width: 100px;
+ height: 100px;
+}
+
+.box-empty {
+ background: #4CAF50;
+}
+
+.box-full {
+ background: #F44336;
+}
+```
+
+Using mixins:
+
+```css
+@mixin box {
+ width: 100px;
+ height: 100px;
+}
+
+.box-empty {
+ @include box;
+
+ background: #4CAF50;
+}
+
+.box-full {
+ @include box;
+
+ background: #F44336;
+}
+```
+
+This translates to:
+
+```css
+.box-empty {
+ width: 100px;
+ height: 100px;
+ background: #4CAF50;
+}
+
+.box-full {
+ width: 100px;
+ height: 100px;
+ background: #F44336;
+}
+```
+
+## Global CSS
+
+CSS Modules does not restrict you from using global CSS.
+
+```css
+:global .foo {
+
+}
+```
+
+However, use global CSS with caution. With CSS Modules, there are only a handful of valid use cases for global CSS (e.g. [normalization](https://github.com/necolas/normalize.css/)).
+
+## Multiple CSS Modules
+
+Avoid using multiple CSS Modules to describe a single element. Read about [Class Composition](#class-composition).
+
+That said, if you require to use multiple CSS Modules to describe an element, enable the [`allowMultiple`](#allowmultiple) option. When multiple CSS Modules are used to describe an element, `react-css-modules` will append a unique class name for every CSS Module it matches in the `styleName` declaration, e.g.
+
+```css
+.button {
+
+}
+
+.active {
+
+}
+```
+
+```js
+
+```
+
+This will map both [Interoperable CSS](https://github.com/css-modules/icss) CSS classes to the target element.
diff --git a/dist/extendReactClass.js b/dist/extendReactClass.js
new file mode 100644
index 0000000..a0a2688
--- /dev/null
+++ b/dist/extendReactClass.js
@@ -0,0 +1,91 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _assign2 = require('lodash/assign');
+
+var _assign3 = _interopRequireDefault(_assign2);
+
+var _isObject2 = require('lodash/isObject');
+
+var _isObject3 = _interopRequireDefault(_isObject2);
+
+var _react = require('react');
+
+var _react2 = _interopRequireDefault(_react);
+
+var _hoistNonReactStatics = require('hoist-non-react-statics');
+
+var _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics);
+
+var _linkClass = require('./linkClass');
+
+var _linkClass2 = _interopRequireDefault(_linkClass);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); } /* eslint-disable react/prop-types */
+
+/**
+ * @param {ReactClass} Component
+ * @param {Object} defaultStyles
+ * @param {Object} options
+ * @returns {ReactClass}
+ */
+exports.default = function (Component, defaultStyles, options) {
+ var WrappedComponent = function (_Component) {
+ _inherits(WrappedComponent, _Component);
+
+ function WrappedComponent() {
+ _classCallCheck(this, WrappedComponent);
+
+ return _possibleConstructorReturn(this, _Component.apply(this, arguments));
+ }
+
+ WrappedComponent.prototype.render = function render() {
+ var propsChanged = void 0,
+ styles = void 0;
+
+ propsChanged = false;
+
+ if (this.props.styles) {
+ styles = this.props.styles;
+ } else if ((0, _isObject3.default)(defaultStyles)) {
+ this.props = (0, _assign3.default)({}, this.props, {
+ styles: defaultStyles
+ });
+
+ propsChanged = true;
+ styles = defaultStyles;
+ } else {
+ styles = {};
+ }
+
+ var renderResult = _Component.prototype.render.call(this);
+
+ if (propsChanged) {
+ delete this.props.styles;
+ }
+
+ if (renderResult) {
+ return (0, _linkClass2.default)(renderResult, styles, options);
+ }
+
+ return _react2.default.createElement('noscript');
+ };
+
+ return WrappedComponent;
+ }(Component);
+
+ return (0, _hoistNonReactStatics2.default)(WrappedComponent, Component);
+};
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/dist/generateAppendClassName.js b/dist/generateAppendClassName.js
new file mode 100644
index 0000000..295c566
--- /dev/null
+++ b/dist/generateAppendClassName.js
@@ -0,0 +1,53 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _simpleMap = require('./simple-map');
+
+var _simpleMap2 = _interopRequireDefault(_simpleMap);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var stylesIndex = new _simpleMap2.default();
+
+exports.default = function (styles, styleNames, errorWhenNotFound) {
+ var appendClassName = void 0,
+ stylesIndexMap = void 0;
+
+ stylesIndexMap = stylesIndex.get(styles);
+
+ if (stylesIndexMap) {
+ var styleNameIndex = stylesIndexMap.get(styleNames);
+
+ if (styleNameIndex) {
+ return styleNameIndex;
+ }
+ } else {
+ stylesIndexMap = new _simpleMap2.default();
+ stylesIndex.set(styles, new _simpleMap2.default());
+ }
+
+ appendClassName = '';
+
+ for (var styleName in styleNames) {
+ if (styleNames.hasOwnProperty(styleName)) {
+ var className = styles[styleNames[styleName]];
+
+ if (className) {
+ appendClassName += ' ' + className;
+ } else if (errorWhenNotFound === true) {
+ throw new Error('"' + styleNames[styleName] + '" CSS module is undefined.');
+ }
+ }
+ }
+
+ appendClassName = appendClassName.trim();
+
+ stylesIndexMap.set(styleNames, appendClassName);
+
+ return appendClassName;
+};
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/dist/index.js b/dist/index.js
new file mode 100644
index 0000000..552029b
--- /dev/null
+++ b/dist/index.js
@@ -0,0 +1,77 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _isFunction2 = require('lodash/isFunction');
+
+var _isFunction3 = _interopRequireDefault(_isFunction2);
+
+var _extendReactClass = require('./extendReactClass');
+
+var _extendReactClass2 = _interopRequireDefault(_extendReactClass);
+
+var _wrapStatelessFunction = require('./wrapStatelessFunction');
+
+var _wrapStatelessFunction2 = _interopRequireDefault(_wrapStatelessFunction);
+
+var _makeConfiguration = require('./makeConfiguration');
+
+var _makeConfiguration2 = _interopRequireDefault(_makeConfiguration);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Determines if the given object has the signature of a class that inherits React.Component.
+ */
+
+
+/**
+ * @see https://github.com/gajus/react-css-modules#options
+ */
+var isReactComponent = function isReactComponent(maybeReactComponent) {
+ return 'prototype' in maybeReactComponent && (0, _isFunction3.default)(maybeReactComponent.prototype.render);
+};
+
+/**
+ * When used as a function.
+ */
+var functionConstructor = function functionConstructor(Component, defaultStyles, options) {
+ var decoratedClass = void 0;
+
+ var configuration = (0, _makeConfiguration2.default)(options);
+
+ if (isReactComponent(Component)) {
+ decoratedClass = (0, _extendReactClass2.default)(Component, defaultStyles, configuration);
+ } else {
+ decoratedClass = (0, _wrapStatelessFunction2.default)(Component, defaultStyles, configuration);
+ }
+
+ if (Component.displayName) {
+ decoratedClass.displayName = Component.displayName;
+ } else {
+ decoratedClass.displayName = Component.name;
+ }
+
+ return decoratedClass;
+};
+
+/**
+ * When used as a ES7 decorator.
+ */
+var decoratorConstructor = function decoratorConstructor(defaultStyles, options) {
+ return function (Component) {
+ return functionConstructor(Component, defaultStyles, options);
+ };
+};
+
+exports.default = function () {
+ if ((0, _isFunction3.default)(arguments.length <= 0 ? undefined : arguments[0])) {
+ return functionConstructor(arguments.length <= 0 ? undefined : arguments[0], arguments.length <= 1 ? undefined : arguments[1], arguments.length <= 2 ? undefined : arguments[2]);
+ } else {
+ return decoratorConstructor(arguments.length <= 0 ? undefined : arguments[0], arguments.length <= 1 ? undefined : arguments[1]);
+ }
+};
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/dist/isIterable.js b/dist/isIterable.js
new file mode 100644
index 0000000..d3d33d5
--- /dev/null
+++ b/dist/isIterable.js
@@ -0,0 +1,41 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _isObject2 = require('lodash/isObject');
+
+var _isObject3 = _interopRequireDefault(_isObject2);
+
+var _isFunction2 = require('lodash/isFunction');
+
+var _isFunction3 = _interopRequireDefault(_isFunction2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var ITERATOR_SYMBOL = typeof Symbol !== 'undefined' && (0, _isFunction3.default)(Symbol) && Symbol.iterator;
+var OLD_ITERATOR_SYMBOL = '@@iterator';
+
+/**
+ * @see https://github.com/lodash/lodash/issues/1668
+ * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols
+ */
+
+exports.default = function (maybeIterable) {
+ var iterator = void 0;
+
+ if (!(0, _isObject3.default)(maybeIterable)) {
+ return false;
+ }
+
+ if (ITERATOR_SYMBOL) {
+ iterator = maybeIterable[ITERATOR_SYMBOL];
+ } else {
+ iterator = maybeIterable[OLD_ITERATOR_SYMBOL];
+ }
+
+ return (0, _isFunction3.default)(iterator);
+};
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/dist/linkClass.js b/dist/linkClass.js
new file mode 100644
index 0000000..c73b88c
--- /dev/null
+++ b/dist/linkClass.js
@@ -0,0 +1,106 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _isObject2 = require('lodash/isObject');
+
+var _isObject3 = _interopRequireDefault(_isObject2);
+
+var _isArray2 = require('lodash/isArray');
+
+var _isArray3 = _interopRequireDefault(_isArray2);
+
+var _react = require('react');
+
+var _react2 = _interopRequireDefault(_react);
+
+var _objectUnfreeze = require('object-unfreeze');
+
+var _objectUnfreeze2 = _interopRequireDefault(_objectUnfreeze);
+
+var _isIterable = require('./isIterable');
+
+var _isIterable2 = _interopRequireDefault(_isIterable);
+
+var _parseStyleName = require('./parseStyleName');
+
+var _parseStyleName2 = _interopRequireDefault(_parseStyleName);
+
+var _generateAppendClassName = require('./generateAppendClassName');
+
+var _generateAppendClassName2 = _interopRequireDefault(_generateAppendClassName);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var linkElement = function linkElement(element, styles, configuration) {
+ var appendClassName = void 0,
+ elementIsFrozen = void 0,
+ elementShallowCopy = void 0;
+
+ elementShallowCopy = element;
+
+ if (Object.isFrozen && Object.isFrozen(elementShallowCopy)) {
+ elementIsFrozen = true;
+
+ // https://github.com/facebook/react/blob/v0.13.3/src/classic/element/ReactElement.js#L131
+ elementShallowCopy = (0, _objectUnfreeze2.default)(elementShallowCopy);
+ elementShallowCopy.props = (0, _objectUnfreeze2.default)(elementShallowCopy.props);
+ }
+
+ var styleNames = (0, _parseStyleName2.default)(elementShallowCopy.props.styleName || '', configuration.allowMultiple);
+
+ if (_react2.default.isValidElement(elementShallowCopy.props.children)) {
+ elementShallowCopy.props.children = linkElement(_react2.default.Children.only(elementShallowCopy.props.children), styles, configuration);
+ } else if ((0, _isArray3.default)(elementShallowCopy.props.children) || (0, _isIterable2.default)(elementShallowCopy.props.children)) {
+ elementShallowCopy.props.children = _react2.default.Children.map(elementShallowCopy.props.children, function (node) {
+ if (_react2.default.isValidElement(node)) {
+ return linkElement(node, styles, configuration);
+ } else {
+ return node;
+ }
+ });
+ }
+
+ if (styleNames.length) {
+ appendClassName = (0, _generateAppendClassName2.default)(styles, styleNames, configuration.errorWhenNotFound);
+
+ if (appendClassName) {
+ if (elementShallowCopy.props.className) {
+ appendClassName = elementShallowCopy.props.className + ' ' + appendClassName;
+ }
+
+ elementShallowCopy.props.className = appendClassName;
+ }
+ }
+
+ delete elementShallowCopy.props.styleName;
+
+ if (elementIsFrozen) {
+ Object.freeze(elementShallowCopy.props);
+ Object.freeze(elementShallowCopy);
+ }
+
+ return elementShallowCopy;
+};
+
+/**
+ * @param {ReactElement} element
+ * @param {Object} styles CSS modules class map.
+ * @param {CSSModules~Options} configuration
+ */
+
+exports.default = function (element) {
+ var styles = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
+ var configuration = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
+
+ // @see https://github.com/gajus/react-css-modules/pull/30
+ if (!(0, _isObject3.default)(element)) {
+ return element;
+ }
+
+ return linkElement(element, styles, configuration);
+};
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/dist/makeConfiguration.js b/dist/makeConfiguration.js
new file mode 100644
index 0000000..a8bbc81
--- /dev/null
+++ b/dist/makeConfiguration.js
@@ -0,0 +1,55 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _isBoolean2 = require('lodash/isBoolean');
+
+var _isBoolean3 = _interopRequireDefault(_isBoolean2);
+
+var _isUndefined2 = require('lodash/isUndefined');
+
+var _isUndefined3 = _interopRequireDefault(_isUndefined2);
+
+var _forEach2 = require('lodash/forEach');
+
+var _forEach3 = _interopRequireDefault(_forEach2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * @typedef CSSModules~Options
+ * @see {@link https://github.com/gajus/react-css-modules#options}
+ * @property {boolean} allowMultiple
+ * @property {boolean} errorWhenNotFound
+ */
+
+/**
+ * @param {CSSModules~Options} userConfiguration
+ * @returns {CSSModules~Options}
+ */
+exports.default = function () {
+ var userConfiguration = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
+
+ var configuration = {
+ allowMultiple: false,
+ errorWhenNotFound: true
+ };
+
+ (0, _forEach3.default)(userConfiguration, function (value, name) {
+ if ((0, _isUndefined3.default)(configuration[name])) {
+ throw new Error('Unknown configuration property "' + name + '".');
+ }
+
+ if (!(0, _isBoolean3.default)(value)) {
+ throw new Error('"' + name + '" property value must be a boolean.');
+ }
+
+ configuration[name] = value;
+ });
+
+ return configuration;
+};
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/dist/parseStyleName.js b/dist/parseStyleName.js
new file mode 100644
index 0000000..8a8be42
--- /dev/null
+++ b/dist/parseStyleName.js
@@ -0,0 +1,38 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _filter2 = require('lodash/filter');
+
+var _filter3 = _interopRequireDefault(_filter2);
+
+var _trim2 = require('lodash/trim');
+
+var _trim3 = _interopRequireDefault(_trim2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var styleNameIndex = {};
+
+exports.default = function (styleNamePropertyValue, allowMultiple) {
+ var styleNames = void 0;
+
+ if (styleNameIndex[styleNamePropertyValue]) {
+ styleNames = styleNameIndex[styleNamePropertyValue];
+ } else {
+ styleNames = (0, _trim3.default)(styleNamePropertyValue).split(' ');
+ styleNames = (0, _filter3.default)(styleNames);
+
+ styleNameIndex[styleNamePropertyValue] = styleNames;
+ }
+
+ if (allowMultiple === false && styleNames.length > 1) {
+ throw new Error('ReactElement styleName property defines multiple module names ("' + styleNamePropertyValue + '").');
+ }
+
+ return styleNames;
+};
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/dist/simple-map.js b/dist/simple-map.js
new file mode 100644
index 0000000..33db5e6
--- /dev/null
+++ b/dist/simple-map.js
@@ -0,0 +1,44 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var SimpleMap = exports.SimpleMap = function () {
+ function SimpleMap() {
+ _classCallCheck(this, SimpleMap);
+
+ this.keys = [];
+ this.values = [];
+ }
+
+ SimpleMap.prototype.get = function get(key) {
+ var index = this.keys.indexOf(key);
+
+ return this.values[index];
+ };
+
+ SimpleMap.prototype.set = function set(key, value) {
+ this.keys.push(key);
+ this.values.push(value);
+
+ return value;
+ };
+
+ _createClass(SimpleMap, [{
+ key: 'size',
+ get: function get() {
+ return this.keys.length;
+ }
+ }]);
+
+ return SimpleMap;
+}();
+
+var exportedMap = typeof Map === 'undefined' ? SimpleMap : Map;
+
+exports.default = exportedMap;
\ No newline at end of file
diff --git a/dist/wrapStatelessFunction.js b/dist/wrapStatelessFunction.js
new file mode 100644
index 0000000..9948dc2
--- /dev/null
+++ b/dist/wrapStatelessFunction.js
@@ -0,0 +1,69 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _assign2 = require('lodash/assign');
+
+var _assign3 = _interopRequireDefault(_assign2);
+
+var _isObject2 = require('lodash/isObject');
+
+var _isObject3 = _interopRequireDefault(_isObject2);
+
+var _react = require('react');
+
+var _react2 = _interopRequireDefault(_react);
+
+var _linkClass = require('./linkClass');
+
+var _linkClass2 = _interopRequireDefault(_linkClass);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * @see https://facebook.github.io/react/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components
+ */
+/* eslint-disable react/prop-types */
+
+exports.default = function (Component, defaultStyles, options) {
+ var WrappedComponent = function WrappedComponent() {
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ args[_key - 1] = arguments[_key];
+ }
+
+ var props = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
+
+ var styles = void 0,
+ useProps = void 0;
+
+ if (props.styles) {
+ useProps = props;
+ styles = props.styles;
+ } else if ((0, _isObject3.default)(defaultStyles)) {
+ useProps = (0, _assign3.default)({}, props, {
+ styles: defaultStyles
+ });
+
+ styles = defaultStyles;
+ } else {
+ useProps = props;
+ styles = {};
+ }
+
+ var renderResult = Component.apply(undefined, [useProps].concat(args));
+
+ if (renderResult) {
+ return (0, _linkClass2.default)(renderResult, styles, options);
+ }
+
+ return _react2.default.createElement('noscript');
+ };
+
+ (0, _assign3.default)(WrappedComponent, Component);
+
+ return WrappedComponent;
+};
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..383dd4b
--- /dev/null
+++ b/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "react-css-modules",
+ "description": "Seamless mapping of class names to CSS modules inside of React components.",
+ "main": "./dist/",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/gajus/react-css-modules"
+ },
+ "keywords": [
+ "react-component",
+ "react",
+ "css",
+ "modules"
+ ],
+ "version": "3.7.9",
+ "author": {
+ "name": "Gajus Kuizinas",
+ "email": "gajus@gajus.com",
+ "url": "http://gajus.com"
+ },
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "hoist-non-react-statics": "^1.0.5",
+ "lodash": "^4.6.1",
+ "object-unfreeze": "^1.0.2"
+ },
+ "devDependencies": {
+ "babel-cli": "^6.10.1",
+ "babel-plugin-add-module-exports": "^0.2.1",
+ "babel-plugin-lodash": "^3.2.5",
+ "babel-plugin-transform-proto-to-assign": "^6.9.0",
+ "babel-preset-es2015": "^6.9.0",
+ "babel-preset-react": "^6.11.1",
+ "babel-preset-stage-0": "^6.5.0",
+ "babel-register": "^6.9.0",
+ "chai": "^3.5.0",
+ "eslint": "^3.0.0",
+ "eslint-config-canonical": "^1.7.12",
+ "jsdom": "^8.1.0",
+ "mocha": "^2.5.3",
+ "react": "^15.0.0-rc.1",
+ "react-addons-shallow-compare": "^15.0.0-rc.1",
+ "react-addons-test-utils": "^15.0.0-rc.1",
+ "react-dom": "^15.0.0-rc.1"
+ },
+ "scripts": {
+ "lint": "eslint ./src ./tests",
+ "test": "mocha --compilers js:babel-register ./tests/**/*.js",
+ "build": "babel ./src --out-dir ./dist"
+ }
+}
\ No newline at end of file
diff --git a/src/extendReactClass.js b/src/extendReactClass.js
new file mode 100644
index 0000000..b5cfb2d
--- /dev/null
+++ b/src/extendReactClass.js
@@ -0,0 +1,50 @@
+/* eslint-disable react/prop-types */
+
+import React from 'react';
+import _ from 'lodash';
+import hoistNonReactStatics from 'hoist-non-react-statics';
+import linkClass from './linkClass';
+
+/**
+ * @param {ReactClass} Component
+ * @param {Object} defaultStyles
+ * @param {Object} options
+ * @returns {ReactClass}
+ */
+export default (Component: Object, defaultStyles: Object, options: Object) => {
+ const WrappedComponent = class extends Component {
+ render () {
+ let propsChanged,
+ styles;
+
+ propsChanged = false;
+
+ if (this.props.styles) {
+ styles = this.props.styles;
+ } else if (_.isObject(defaultStyles)) {
+ this.props = _.assign({}, this.props, {
+ styles: defaultStyles
+ });
+
+ propsChanged = true;
+ styles = defaultStyles;
+ } else {
+ styles = {};
+ }
+
+ const renderResult = super.render();
+
+ if (propsChanged) {
+ delete this.props.styles;
+ }
+
+ if (renderResult) {
+ return linkClass(renderResult, styles, options);
+ }
+
+ return React.createElement('noscript');
+ }
+ };
+
+ return hoistNonReactStatics(WrappedComponent, Component);
+};
diff --git a/src/generateAppendClassName.js b/src/generateAppendClassName.js
new file mode 100644
index 0000000..3bbb23f
--- /dev/null
+++ b/src/generateAppendClassName.js
@@ -0,0 +1,41 @@
+import Map from './simple-map';
+
+const stylesIndex = new Map();
+
+export default (styles, styleNames: Array, errorWhenNotFound: boolean): string => {
+ let appendClassName,
+ stylesIndexMap;
+
+ stylesIndexMap = stylesIndex.get(styles);
+
+ if (stylesIndexMap) {
+ const styleNameIndex = stylesIndexMap.get(styleNames);
+
+ if (styleNameIndex) {
+ return styleNameIndex;
+ }
+ } else {
+ stylesIndexMap = new Map();
+ stylesIndex.set(styles, new Map());
+ }
+
+ appendClassName = '';
+
+ for (const styleName in styleNames) {
+ if (styleNames.hasOwnProperty(styleName)) {
+ const className = styles[styleNames[styleName]];
+
+ if (className) {
+ appendClassName += ' ' + className;
+ } else if (errorWhenNotFound === true) {
+ throw new Error('"' + styleNames[styleName] + '" CSS module is undefined.');
+ }
+ }
+ }
+
+ appendClassName = appendClassName.trim();
+
+ stylesIndexMap.set(styleNames, appendClassName);
+
+ return appendClassName;
+};
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..7ee7e4e
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,56 @@
+import _ from 'lodash';
+import extendReactClass from './extendReactClass';
+import wrapStatelessFunction from './wrapStatelessFunction';
+import makeConfiguration from './makeConfiguration';
+
+/**
+ * @see https://github.com/gajus/react-css-modules#options
+ */
+type TypeOptions = {};
+
+/**
+ * Determines if the given object has the signature of a class that inherits React.Component.
+ */
+const isReactComponent = (maybeReactComponent: any): boolean => {
+ return 'prototype' in maybeReactComponent && _.isFunction(maybeReactComponent.prototype.render);
+};
+
+/**
+ * When used as a function.
+ */
+const functionConstructor = (Component: Function, defaultStyles: Object, options: TypeOptions): Function => {
+ let decoratedClass;
+
+ const configuration = makeConfiguration(options);
+
+ if (isReactComponent(Component)) {
+ decoratedClass = extendReactClass(Component, defaultStyles, configuration);
+ } else {
+ decoratedClass = wrapStatelessFunction(Component, defaultStyles, configuration);
+ }
+
+ if (Component.displayName) {
+ decoratedClass.displayName = Component.displayName;
+ } else {
+ decoratedClass.displayName = Component.name;
+ }
+
+ return decoratedClass;
+};
+
+/**
+ * When used as a ES7 decorator.
+ */
+const decoratorConstructor = (defaultStyles: Object, options: TypeOptions): Function => {
+ return (Component: Function) => {
+ return functionConstructor(Component, defaultStyles, options);
+ };
+};
+
+export default (...args) => {
+ if (_.isFunction(args[0])) {
+ return functionConstructor(args[0], args[1], args[2]);
+ } else {
+ return decoratorConstructor(args[0], args[1]);
+ }
+};
diff --git a/src/isIterable.js b/src/isIterable.js
new file mode 100644
index 0000000..2c800b1
--- /dev/null
+++ b/src/isIterable.js
@@ -0,0 +1,24 @@
+import _ from 'lodash';
+
+const ITERATOR_SYMBOL = typeof Symbol !== 'undefined' && _.isFunction(Symbol) && Symbol.iterator;
+const OLD_ITERATOR_SYMBOL = '@@iterator';
+
+/**
+ * @see https://github.com/lodash/lodash/issues/1668
+ * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols
+ */
+export default (maybeIterable: any): boolean => {
+ let iterator;
+
+ if (!_.isObject(maybeIterable)) {
+ return false;
+ }
+
+ if (ITERATOR_SYMBOL) {
+ iterator = maybeIterable[ITERATOR_SYMBOL];
+ } else {
+ iterator = maybeIterable[OLD_ITERATOR_SYMBOL];
+ }
+
+ return _.isFunction(iterator);
+};
diff --git a/src/linkClass.js b/src/linkClass.js
new file mode 100644
index 0000000..ea199e9
--- /dev/null
+++ b/src/linkClass.js
@@ -0,0 +1,73 @@
+import _ from 'lodash';
+import React, {
+ ReactElement
+} from 'react';
+import objectUnfreeze from 'object-unfreeze';
+import isIterable from './isIterable';
+import parseStyleName from './parseStyleName';
+import generateAppendClassName from './generateAppendClassName';
+
+const linkElement = (element: ReactElement, styles: Object, configuration: Object): ReactElement => {
+ let appendClassName,
+ elementIsFrozen,
+ elementShallowCopy;
+
+ elementShallowCopy = element;
+
+ if (Object.isFrozen && Object.isFrozen(elementShallowCopy)) {
+ elementIsFrozen = true;
+
+ // https://github.com/facebook/react/blob/v0.13.3/src/classic/element/ReactElement.js#L131
+ elementShallowCopy = objectUnfreeze(elementShallowCopy);
+ elementShallowCopy.props = objectUnfreeze(elementShallowCopy.props);
+ }
+
+ const styleNames = parseStyleName(elementShallowCopy.props.styleName || '', configuration.allowMultiple);
+
+ if (React.isValidElement(elementShallowCopy.props.children)) {
+ elementShallowCopy.props.children = linkElement(React.Children.only(elementShallowCopy.props.children), styles, configuration);
+ } else if (_.isArray(elementShallowCopy.props.children) || isIterable(elementShallowCopy.props.children)) {
+ elementShallowCopy.props.children = React.Children.map(elementShallowCopy.props.children, (node) => {
+ if (React.isValidElement(node)) {
+ return linkElement(node, styles, configuration);
+ } else {
+ return node;
+ }
+ });
+ }
+
+ if (styleNames.length) {
+ appendClassName = generateAppendClassName(styles, styleNames, configuration.errorWhenNotFound);
+
+ if (appendClassName) {
+ if (elementShallowCopy.props.className) {
+ appendClassName = elementShallowCopy.props.className + ' ' + appendClassName;
+ }
+
+ elementShallowCopy.props.className = appendClassName;
+ }
+ }
+
+ delete elementShallowCopy.props.styleName;
+
+ if (elementIsFrozen) {
+ Object.freeze(elementShallowCopy.props);
+ Object.freeze(elementShallowCopy);
+ }
+
+ return elementShallowCopy;
+};
+
+/**
+ * @param {ReactElement} element
+ * @param {Object} styles CSS modules class map.
+ * @param {CSSModules~Options} configuration
+ */
+export default (element: ReactElement, styles = {}, configuration = {}): ReactElement => {
+ // @see https://github.com/gajus/react-css-modules/pull/30
+ if (!_.isObject(element)) {
+ return element;
+ }
+
+ return linkElement(element, styles, configuration);
+};
diff --git a/src/makeConfiguration.js b/src/makeConfiguration.js
new file mode 100644
index 0000000..83b2d41
--- /dev/null
+++ b/src/makeConfiguration.js
@@ -0,0 +1,33 @@
+import _ from 'lodash';
+
+/**
+ * @typedef CSSModules~Options
+ * @see {@link https://github.com/gajus/react-css-modules#options}
+ * @property {boolean} allowMultiple
+ * @property {boolean} errorWhenNotFound
+ */
+
+/**
+ * @param {CSSModules~Options} userConfiguration
+ * @returns {CSSModules~Options}
+ */
+export default (userConfiguration = {}) => {
+ const configuration = {
+ allowMultiple: false,
+ errorWhenNotFound: true
+ };
+
+ _.forEach(userConfiguration, (value, name) => {
+ if (_.isUndefined(configuration[name])) {
+ throw new Error('Unknown configuration property "' + name + '".');
+ }
+
+ if (!_.isBoolean(value)) {
+ throw new Error('"' + name + '" property value must be a boolean.');
+ }
+
+ configuration[name] = value;
+ });
+
+ return configuration;
+};
diff --git a/src/parseStyleName.js b/src/parseStyleName.js
new file mode 100644
index 0000000..39c328a
--- /dev/null
+++ b/src/parseStyleName.js
@@ -0,0 +1,22 @@
+import _ from 'lodash';
+
+const styleNameIndex = {};
+
+export default (styleNamePropertyValue: string, allowMultiple: boolean): Array => {
+ let styleNames;
+
+ if (styleNameIndex[styleNamePropertyValue]) {
+ styleNames = styleNameIndex[styleNamePropertyValue];
+ } else {
+ styleNames = _.trim(styleNamePropertyValue).split(' ');
+ styleNames = _.filter(styleNames);
+
+ styleNameIndex[styleNamePropertyValue] = styleNames;
+ }
+
+ if (allowMultiple === false && styleNames.length > 1) {
+ throw new Error('ReactElement styleName property defines multiple module names ("' + styleNamePropertyValue + '").');
+ }
+
+ return styleNames;
+};
diff --git a/src/simple-map.js b/src/simple-map.js
new file mode 100644
index 0000000..4582e33
--- /dev/null
+++ b/src/simple-map.js
@@ -0,0 +1,27 @@
+export class SimpleMap {
+ constructor () {
+ this.keys = [];
+ this.values = [];
+ }
+
+ get size () {
+ return this.keys.length;
+ }
+
+ get (key) {
+ const index = this.keys.indexOf(key);
+
+ return this.values[index];
+ }
+
+ set (key, value) {
+ this.keys.push(key);
+ this.values.push(value);
+
+ return value;
+ }
+}
+
+const exportedMap = typeof Map === 'undefined' ? SimpleMap : Map;
+
+export default exportedMap;
diff --git a/src/wrapStatelessFunction.js b/src/wrapStatelessFunction.js
new file mode 100644
index 0000000..878119a
--- /dev/null
+++ b/src/wrapStatelessFunction.js
@@ -0,0 +1,41 @@
+/* eslint-disable react/prop-types */
+
+import _ from 'lodash';
+import React from 'react';
+import linkClass from './linkClass';
+
+/**
+ * @see https://facebook.github.io/react/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components
+ */
+export default (Component: Function, defaultStyles: Object, options: Object): Function => {
+ const WrappedComponent = (props = {}, ...args) => {
+ let styles,
+ useProps;
+
+ if (props.styles) {
+ useProps = props;
+ styles = props.styles;
+ } else if (_.isObject(defaultStyles)) {
+ useProps = _.assign({}, props, {
+ styles: defaultStyles
+ });
+
+ styles = defaultStyles;
+ } else {
+ useProps = props;
+ styles = {};
+ }
+
+ const renderResult = Component(useProps, ...args);
+
+ if (renderResult) {
+ return linkClass(renderResult, styles, options);
+ }
+
+ return React.createElement('noscript');
+ };
+
+ _.assign(WrappedComponent, Component);
+
+ return WrappedComponent;
+};