Skip to content

Commit c1bdc5a

Browse files
authored
Merge pull request javivelasco#20 from raveclassic/flatten_multiple_wrapping
flatten multiple wrapping
2 parents 5121672 + b7d31cc commit c1bdc5a

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

src/components/themr.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,26 @@ const DEFAULT_OPTIONS = {
1010
withRef: false
1111
}
1212

13+
const THEMR_CONFIG = typeof Symbol !== 'undefined' ?
14+
Symbol('THEMR_CONFIG') :
15+
'__REACT_CSS_THEMR_CONFIG__'
16+
1317
export default (componentName, localTheme, options = {}) => (ThemedComponent) => {
1418
const { composeTheme: optionComposeTheme, withRef: optionWithRef } = { ...DEFAULT_OPTIONS, ...options }
1519
validateComposeOption(optionComposeTheme)
16-
return class Themed extends Component {
20+
21+
let config = ThemedComponent[THEMR_CONFIG]
22+
if (config && config.componentName === componentName) {
23+
config.localTheme = themeable(config.localTheme, localTheme)
24+
return ThemedComponent
25+
}
26+
27+
config = {
28+
componentName,
29+
localTheme
30+
}
31+
32+
class Themed extends Component {
1733
static displayName = `Themed ${ThemedComponent.name}`;
1834

1935
static contextTypes = {
@@ -54,20 +70,20 @@ export default (componentName, localTheme, options = {}) => (ThemedComponent) =>
5470

5571
getThemeNotComposed() {
5672
if (this.props.theme) return this.getNamespacedTheme()
57-
if (localTheme) return localTheme
73+
if (config.localTheme) return config.localTheme
5874
return this.getContextTheme()
5975
}
6076

6177
getContextTheme() {
6278
return this.context.themr
63-
? this.context.themr.theme[componentName]
79+
? this.context.themr.theme[config.componentName]
6480
: {}
6581
}
6682

6783
getTheme() {
6884
return this.props.composeTheme === COMPOSE_SOFTLY
69-
? { ...this.getContextTheme(), ...localTheme, ...this.getNamespacedTheme() }
70-
: themeable(themeable(this.getContextTheme(), localTheme), this.getNamespacedTheme())
85+
? { ...this.getContextTheme(), ...config.localTheme, ...this.getNamespacedTheme() }
86+
: themeable(themeable(this.getContextTheme(), config.localTheme), this.getNamespacedTheme())
7187
}
7288

7389
render() {
@@ -94,6 +110,10 @@ export default (componentName, localTheme, options = {}) => (ThemedComponent) =>
94110
return renderedElement
95111
}
96112
}
113+
114+
Themed[THEMR_CONFIG] = config
115+
116+
return Themed
97117
}
98118

99119
export function themeable(style = {}, theme) {

test/components/themr.spec.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,4 +381,31 @@ describe('Themr decorator function', () => {
381381
expect(Foo.propTypes.foo).toBe(propTypes.foo)
382382
expect(Foo.defaultProps.foo).toBe(defaultProps.foo)
383383
})
384+
385+
it('should not wrap multiple time if used with already wrapped component with the same key', () => {
386+
const foo = {
387+
foo: 'foo'
388+
}
389+
const bar = {
390+
bar: 'bar'
391+
}
392+
const key = 'Foo'
393+
394+
@themr(key, foo)
395+
class Foo extends Component {
396+
render() {
397+
return <Passthrough {...this.props} />
398+
}
399+
}
400+
const Bar = themr(key, bar)(Foo)
401+
expect(Bar).toBe(Foo)
402+
403+
const tree = TestUtils.renderIntoDocument(<Bar/>)
404+
405+
const stub = TestUtils.findRenderedComponentWithType(tree, Passthrough)
406+
expect(stub.props.theme).toEqual({
407+
...foo,
408+
...bar
409+
})
410+
})
384411
})

0 commit comments

Comments
 (0)