Skip to content

Commit 858601d

Browse files
committed
Create basic support for theming out of the box
1 parent ed59cd7 commit 858601d

1 file changed

Lines changed: 29 additions & 10 deletions

File tree

src/styled.js

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import {Component, createElement} from 'react'
2+
import PropTypes from 'prop-types'
3+
import {themeListener, channel} from 'theming'
24

35
import filterProps from './utils/filterProps'
46
import composeClasses from './utils/composeClasses'
@@ -27,18 +29,25 @@ const styled = ({tagName, elementStyle, mountSheet}: StyledArgs) => {
2729
return class StyledElement extends Component {
2830
static tagName: string = tagName
2931
static style: ComponentStyleType = elementStyle
32+
static contextTypes = {
33+
[channel]: PropTypes.object
34+
}
3035

3136
props: StyledElementPropsType
37+
sheet: JssSheet
38+
state: {theme?: Object}
39+
unsubscribe: Function
3240

3341
dynamicTagName = ''
42+
setTheme = (theme: Object) => this.setState({theme})
3443

35-
sheet: JssSheet
36-
37-
constructor(props: StyledElementPropsType) {
38-
super(props)
44+
constructor(props: StyledElementPropsType, context: *) {
45+
super(props, context)
3946
if (!this.dynamicTagName && dynamicStyle) {
4047
this.dynamicTagName = availableDynamicTagNames.pop() || generateTagName(tagName)
4148
}
49+
50+
this.state = context[channel] ? {theme: themeListener.initial(context)} : {}
4251
}
4352

4453
componentWillMount() {
@@ -57,27 +66,37 @@ const styled = ({tagName, elementStyle, mountSheet}: StyledArgs) => {
5766
}
5867

5968
classMap[this.dynamicTagName] = classMap[this.dynamicTagName] || rulesIndex.slice(rulesTotal)
60-
this.updateSheet(this.props)
69+
this.updateSheet(this.props, this.state)
6170
}
6271

63-
componentWillReceiveProps(nextProps: StyledElementPropsType) {
64-
if (dynamicStyle) this.updateSheet(nextProps)
72+
componentWillUpdate(nextProps: StyledElementPropsType, nextState: *) {
73+
if (dynamicStyle) this.updateSheet(nextProps, nextState)
74+
}
75+
76+
componentDidMount() {
77+
if (this.state.theme) {
78+
this.unsubscribe = themeListener.subscribe(this.context, this.setTheme)
79+
}
6580
}
6681

6782
componentWillUnmount() {
6883
availableDynamicTagNames.push(this.dynamicTagName)
84+
85+
if (typeof this.unsubscribe === 'function') this.unsubscribe()
6986
}
7087

71-
updateSheet(props: StyledElementPropsType) {
88+
updateSheet(props: StyledElementPropsType, state: *) {
7289
let rule
7390
let ruleIndex = 0
7491

92+
const styles = Object.assign({}, props, state)
93+
7594
// nested styles become to flatten rules, so we need to update each nested rule
7695
for (ruleIndex; ruleIndex < classMap[this.dynamicTagName].length; ruleIndex++) {
7796
rule = classMap[this.dynamicTagName][ruleIndex]
7897

79-
if (rule.name) this.sheet.update(rule.name, props)
80-
if (rule.rules) rule.rules.update(props)
98+
if (rule.name) this.sheet.update(rule.name, styles)
99+
if (rule.rules) rule.rules.update(styles)
81100
}
82101
}
83102

0 commit comments

Comments
 (0)