nfront/global-styles

View on GitHub
src/models/GlobalStyle.js

Summary

Maintainability
A
0 mins
Test Coverage
import React from 'react';
import flatten from '../utils/flatten';
import stringifyRules from '../utils/stringifyRules';

export default class GlobalStyle {
  constructor(rules, elementId) {
    this.rules = rules;
    this.elementId = elementId;
    this.compiledStyles = '';
    this.ReactStyleComponent = this.ReactStyleComponent.bind(this);
    this.injectStyleInBrowser = this.injectStyleInBrowser.bind(this);
  }

  createStyles(props) {
    const flatCSS = flatten(this.rules, props);
    const css = stringifyRules(flatCSS, '');
    this.compiledStyles = css;
  }

  ReactStyleComponent(props) {
    this.createStyles(props);
    return (
      <style
        id={this.elementId}
        // eslint-disable-next-line react/no-danger
        dangerouslySetInnerHTML={{
          __html: this.compiledStyles,
        }}
      />
    );
  }

  injectStyleInBrowser() {
    if (typeof document === 'undefined') return;
    // Only called by renderStyles,
    // so styles are already created
    // and compiledStyles is available.

    // Replace existing
    if (document.getElementById(this.elementId)) {
      const styleNode = document.getElementById(this.elementId);
      styleNode.innerHTML = this.compiledStyles;
    } else {
      const node = document.createElement('style');
      node.id = this.elementId;
      node.innerHTML = this.compiledStyles;
      const { head } = document;
      const first = head.firstChild;
      first ? head.insertBefore(node, first) : head.appendChild(node);
    }
  }

  renderStyles(props) {
    this.createStyles(props);
    this.injectStyleInBrowser();
  }
}