mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-13 04:28:41 -09:00
70 lines
2.2 KiB
JavaScript
70 lines
2.2 KiB
JavaScript
|
|
import React from 'react';
|
||
|
|
import {StyleSheet, css} from 'aphrodite-simple';
|
||
|
|
|
||
|
|
const decorateBaseComponent = Component => {
|
||
|
|
return class BaseComponent extends Component {
|
||
|
|
constructor() {
|
||
|
|
super();
|
||
|
|
this.styles_ = this.createStyleSheet();
|
||
|
|
this.cssHelper = this.cssHelper.bind(this);
|
||
|
|
}
|
||
|
|
|
||
|
|
createStyleSheet() {
|
||
|
|
if (!this.styles) {
|
||
|
|
return {};
|
||
|
|
}
|
||
|
|
|
||
|
|
const styles = this.styles();
|
||
|
|
|
||
|
|
if (typeof styles !== 'object') {
|
||
|
|
throw new TypeError('Component `styles` returns a non-object');
|
||
|
|
}
|
||
|
|
|
||
|
|
return StyleSheet.create(this.styles());
|
||
|
|
}
|
||
|
|
|
||
|
|
// wrap aphrodite's css helper for two reasons:
|
||
|
|
// - we can give the element an unaltered global classname
|
||
|
|
// that can be used to introduce global css side effects
|
||
|
|
// for example, through the configuration, web inspector
|
||
|
|
// or user agent extensions
|
||
|
|
// - the user doesn't need to keep track of both `css`
|
||
|
|
// and `style`, and we make that whole ordeal easier
|
||
|
|
cssHelper(...args) {
|
||
|
|
const classes = args
|
||
|
|
.map(c => {
|
||
|
|
if (c) {
|
||
|
|
// we compute the global name from the given
|
||
|
|
// css class and we prepend the component name
|
||
|
|
//
|
||
|
|
// it's important classes never get mangled by
|
||
|
|
// uglifiers so that we can avoid collisions
|
||
|
|
const component = this.constructor.name.toString().toLowerCase();
|
||
|
|
const globalName = `${component}_${c}`;
|
||
|
|
return [globalName, css(this.styles_[c])];
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
})
|
||
|
|
// skip nulls
|
||
|
|
.filter(v => Boolean(v))
|
||
|
|
// flatten
|
||
|
|
.reduce((a, b) => a.concat(b));
|
||
|
|
return classes.length ? classes.join(' ') : null;
|
||
|
|
}
|
||
|
|
|
||
|
|
render() {
|
||
|
|
// convert static objects from `babel-plugin-transform-jsx`
|
||
|
|
// to `React.Element`.
|
||
|
|
if (!this.template) {
|
||
|
|
throw new TypeError("Component doesn't define `template`");
|
||
|
|
}
|
||
|
|
|
||
|
|
// invoke the template creator passing our css helper
|
||
|
|
return this.template(this.cssHelper);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
export const PureComponent = decorateBaseComponent(React.PureComponent);
|
||
|
|
export const Component = decorateBaseComponent(React.Component);
|