Skip to content

Commit

Permalink
add CSSModules decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
Graf009 committed May 18, 2016
1 parent b52b647 commit 00128b0
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 0 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@
"dependencies": {
"@eagle/redux-immutablejs": "0.1.0",
"babel-runtime": "6.6.1",
"classnames": "2.2.5",
"hoist-non-react-statics": "1.0.6",
"immutable": "3.8.1",
"lodash.filter": "4.4.0",
"lodash.foreach": "4.3.0",
"lodash.isfunction": "3.0.8",
"lodash.map": "4.4.0",
"lodash.mapvalues": "4.4.0",
"lodash.reduce": "4.4.0",
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import createActions from './lib/createActions'
import createReducer from './lib/createReducer'
import createReducerActions from './lib/createReducerActions'
import combineReducers from './lib/combineReducers'
import CSSModules from './lib/CSSModules'

class TangoComponent extends ReactComponent {
static defaultState = {};
Expand All @@ -29,6 +30,7 @@ const PropTypes = {
export {
TangoComponent as Component,
connect,
CSSModules,
PropTypes,
Provider,
combineReducers,
Expand Down
22 changes: 22 additions & 0 deletions src/lib/CSSModules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

import isFunction from 'lodash.isfunction'

import extendReactClass from './css-modules/extendReactClass'
import wrapStatelessFunction from './css-modules/wrapStatelessFunction'

const isReactComponent = (maybeReactComponent) =>
'prototype' in maybeReactComponent && isFunction(maybeReactComponent.prototype.render)

export default (styles, options) => Component => {
let decoratedClass

if (isReactComponent(Component)) {
decoratedClass = extendReactClass(Component, styles, options)
} else {
decoratedClass = wrapStatelessFunction(Component, styles, options)
}

decoratedClass.displayName = Component.displayName || Component.name

return decoratedClass
}
18 changes: 18 additions & 0 deletions src/lib/css-modules/extendReactClass.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import hoistNonReactStatics from 'hoist-non-react-statics'

import linkElement from './linkElement'

export default (Component, styles, options) => {
class WrappedComponent extends Component {
render() {
const renderResult = super.render()

if (renderResult) {
return linkElement(renderResult, styles, options)
}
return renderResult
}
}

return hoistNonReactStatics(WrappedComponent, Component)
}
33 changes: 33 additions & 0 deletions src/lib/css-modules/linkElement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Children, isValidElement, cloneElement } from 'react'
import classNames from 'classnames/bind'

const linkElement = (element, styles, options) => {
const cx = classNames.bind(styles)
let className
let children

if (isValidElement(element.props.children)) {
children = linkElement(element.props.children, styles, options)
} else {
children = Children.map(element.props.children, (node) => {
if (isValidElement(node)) {
return linkElement(node, styles, options)
}
return node
})
}

if (element.props.styleName) {
className = cx(element.props.styleName)

if (element.props.className) {
className = `${element.props.className} ${className}`
}

return cloneElement(element, { className }, children)
}

return element
}

export default linkElement
14 changes: 14 additions & 0 deletions src/lib/css-modules/wrapStatelessFunction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import linkElement from './linkElement'

export default (Component, styles, options) => {
const WrappedComponent = (props = {}, ...args) => {
const renderResult = Component(props, ...args)

if (renderResult) {
return linkElement(renderResult, styles, options)
}
return renderResult
}

return WrappedComponent
}
1 change: 1 addition & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as tango from '../src'
test('should export the right stuff', t => {
t.truthy(tango.Component, 'Component')
t.truthy(tango.connect, 'connect')
t.truthy(tango.CSSModules, 'CSSModules')
t.truthy(tango.PropTypes, 'PropTypes')
t.truthy(tango.Provider, 'Provider')
t.truthy(tango.combineReducers, 'combineReducers')
Expand Down

0 comments on commit 00128b0

Please sign in to comment.