export default Styles {
constructor(props, state) {
this.props = props;
this.state = state;
this.createGeneric()
}
generic() {
return [];
}
compute(styles) {
computeStyles(styles);
computeStyles(this.genericStyles);
}
computeStyles(styleObj) {
// ignore static styles
// should compare pointer of prev state (assume immutable)
for (let [k, v] of styleObj.state) {
// check state/props dependency and only call if either one changed
styleObj[k] = v({state: this.state});
}
// should compare pointer of prev props (assume immutable)
for (let [k, v] of styleObj.props) {
// check state/props dependency and only call if either one changed
styleObj[k] = v({props: this.props});
}
for (let [k, v] of styleObj.any) {
// check state/props dependency and only call if either one changed
styleObj[k] = v({state: this.state, props: this.props});
}
return styleObj;
}
createGeneric() {
this.genericStyles = () => {
return this.generic.reduce((prev, style) => {
prev[style] = (x) => { return this[style](x};
});
}
}
mixin(target, ...styles) {
return _.merge(target, styles);
}
}
The Styles class of MyComponentStyles
import GlobalStyles from '../GlobalStyles.js'
// styles object allows "mixins"
export const styles = {
// return style object
// dep: state change
// State dependency decorator, will register as state dependent
// actually just a computed property! See aurelia
@computed(state)
title: (x) => {
return {
color: x.state.todo.completed ? 'red' : 'green';
};
}
}.mixin(GlobalStyles.headers);
export default class MyComponentStyles extends Styles
constructor(props, state) {
super(props, state)
}
// declare generic styles
generic() {
return ['header', 'footer'];
}
// we should be smart and only compute when necessary
// - static
// - props dep
// - state dep
// - state + props dep
compute() {
super.compute({
header: subHeader(),
title: bigTitle(),
});
}
}
import Styles from './styles.js';
<!-- props are global (or higher level state)
state is local state (ie. local styling)
to calculate local style state, use global and local state
to compute new style object (one level deep only!)
-->
export default class MyComponent extends Component {
constructor(props) {
super(props); // sets this.props ?
this.createState();
}
createState() {
// also use whatever props you like
this.state = {
x: 2
y: 3
};
}
updateStyles(nextProps, nextState) {
this.state.styles = new Styles(nextProps, nextState).compute();
}
// just before component is rendered after a state update,
// we re-compute styles based on state
componentWillUpdate(nextProps, nextState) {
this.updateStyles(nextProps, nextState);
}
render() {
return (
// perhaps use a JSX pre-processor:
// <header styles={$header, $big} => styles={[this.state.styles.header, this.state.styles.big] }
return (
<header styles={this.state.styles.header} >
<title> styles={this.state.styles.title} />
...
</header>
);
}
}