Styled Component Base

by ordette

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.js"></script>
<script src="https://npmcdn.com/[email protected]/dist/react-with-addons.js"></script>
<script src="https://unpkg.com/[email protected]/dist/react-dom.min.js"></script>
<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

CSS

body {
    background: white;
    margin: 0;
    padding: 0;
}

Babel + JSX

const compileCss = (id, props, strings, ...fns) => {
    let css = strings[0];

    if (fns.length) {
        const lastString = strings[strings.length - 1];

        css = fns.reduce((str, fn, index) => {
            str += strings[index];

			if (typeof fn === 'function') {
            	str += fn(props);
            } else {
            	str += fn;
            }

            return str;
        }, '') + lastString;
    }

    return `.${id} { ${css} }`;
}

const genId = (() => {
	let count = 0;
    
    return type => `${type}${++count}`;
})();

const generateElement = (ElementType) => {
	return (strings, ...fns) => {
        return (props) => {
            const id = genId(ElementType);
            const cssJson = compileCss(id, props, strings, ...fns);
            
            const style = document.createElement('style');
            style.textContent = cssJson;
            style.setAttribute('data-styles', id);
            
            document.head.appendChild(style);

            return (
                <ElementType className={id} {...props}>{props.children}</ElementType>
            );
        }
    };
}

const elementTypes = [
  'a',
  'abbr',
  'address',
  'area',
  'article',
  'aside',
  'audio',
  'b',
  'base',
  'bdi',
  'bdo',
  'big',
  'blockquote',
  'body',
  'br',
  'button',
  'canvas',
  'caption',
  'cite',
  'code',
  'col',
  'colgroup',
  'data',
  'datalist',
  'dd',
  'del',
  'details',
  'dfn',
  'dialog',
  'div',
  'dl',
  'dt',
  'em',
  'embed',
  'fieldset',
  'figcaption',
  'figure',
  'footer',
  'form',
  'h1',
  'h2',
  'h3',
  'h4',
  'h5',
  'h6',
  'head',
  'header',
  'hgroup',
  'hr',
  'html',
  'i',
  'iframe',
  'img',
  'input',
  'ins',
  'kbd',
  'keygen',
  'label',
  'legend',
  'li',
  'link',
  'main',
  'map',
  'mark',
  'menu',
  'menuitem',
  'meta',
  'meter',
  'nav',
  'noscript',
  'object',
  'ol',
  'optgroup',
  'option',
  'output',
  'p',
  'param',
  'picture',
  'pre',
  'progress',
 ...