Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/modules / ___dist / view-container / styles / StyledComponent.js
Size: Mime:
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.asStyledComponent = asStyledComponent;
exports.default = exports.StyledComponent = void 0;

var _react = _interopRequireDefault(require("react"));

var _exotic = require("../../exotic");

var _index = require("../../chain-able/index.js");

var _types = require("../types");

var _localStorage = _interopRequireDefault(require("../../persistance/local-storage"));

var _identifier = require("../../identifier");

var _fromStringToStyleTag = require("../deps/fromStringToStyleTag");

var _transpileStyles = require("./transpileStyles");

var _jsxFileName = "view-container/styles/StyledComponent.js";

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }

function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

/**
 * @todo - these should be in an mst store to be rehydrated?
 *
 * {String}
 * @type {Map<StyleStringToParse, CSS>}
 */
const styleRegistry = new Map();
/**
 * {Element}
 * @type {Map<CSS, StyledComponent>}
 */

const styleBlockRegistry = new Map();
const globalStyleBlocks = new Set(); // @todo - set keys with fliphash

const metaRegistry = new Map();
const cssStringList = [];
/**
 * @event rehydrate
 * @return {never}
 */

function rehydrateFromPersistance() {
  const persistedStyles = _localStorage.default.get('styles');

  if ((0, _exotic.isString)(persistedStyles)) {
    console.log('saved as string...'); // const hydrated = JSON.parse(persistedStyles)
  }

  if ((0, _exotic.isObj)(persistedStyles)) {
    const hydrated = persistedStyles;

    if (hydrated.length > 100) {
      console.info('cleared local styles');

      _localStorage.default.remove('styles');
    }

    hydrated.forEach(pair => {
      const _pair = _slicedToArray(pair, 2),
            key = _pair[0],
            value = _pair[1];

      styleRegistry.set(key, value);
    });
  }

  return undefined;
}
/**
 * @see styleRegistry
 * @description persistance [key, value]
 *
 * @param {StylesNextGen} styles next-gen styles
 * @param {CSS} css transpiled
 * @return {CSS} same-in-same-out
 */


function saveTranspiledStyles(styles, css) {
  styleRegistry.set(styles, css);

  const savedStyles = _localStorage.default.get('styles');

  if ((0, _exotic.isArray)(savedStyles)) {
    savedStyles.push([styles, css]);

    _localStorage.default.set('styles', savedStyles);
  }

  return css;
}
/**
 * @todo should cache StyledComponents as well as Style
 *
 * @param {String | *} css
 * @return {true | false | JSX.Element<CSSStyleSheet>}
 */


function getElementFromRegistry(css) {
  if (css === '') {
    return false;
  } else if (styleBlockRegistry.has(css)) {
    return styleBlockRegistry.get(css);
  } else {
    return false;
  }
}

let hashed = 0;
const HOT_RELOAD_STYLES = false; // let HOT_RELOAD_STYLES = !IS_PIPELINE_SERVER
// let HOT_RELOAD_STYLES = process.env.HOT === 'true'
// process.env.NODE_ENV === 'development'

rehydrateFromPersistance();
/**
 * @type {JSX.Element<CSSStyleSheet>}
 */

let StyledComponent = class StyledComponent extends _react.default.Component {
  constructor(...args) {
    var _temp;

    return _temp = super(...args), this.css = _exotic.EMPTY_STRING, this.selector = _exotic.EMPTY_STRING, this.state = {
      css: _exotic.EMPTY_STRING
    }, _temp;
  }

  shouldComponentUpdate(nextProps) {
    return HOT_RELOAD_STYLES || nextProps && nextProps.styleseh !== this.props.styleseh;
  } // @todo


  componentWillUnmount() {
    // not sure if we can change props on a component...
    // so we are using a meta registry
    if (metaRegistry.has(this.css) === true) {
      const meta = metaRegistry.get(this.css);
      meta.hasMounted = false;
    }
  } // @todo
  // 1. we render a style
  // 2. we go to another page
  // 3. that style was unmounted
  // 4. we already rendered it
  // 5. we don't show it again <- needs to go in a globals


  componentDidMount() {
    if (metaRegistry.has(this.css) === true) {
      const meta = metaRegistry.get(this.css);
      meta.hasMounted = true;
    }
  } // mucks with deep force
  // componentDidUpdate() {
  //   if (HOT_RELOAD_STYLES === true) {
  //     this.loadStylesIfNeeded(this.props.styleseh)
  //     // this.forceUpdate()
  //   }
  // }


  componentWillMount() {
    this.loadStylesIfNeeded(this.props.styleseh);
    return Promise.resolve(this.css);
  }
  /**
   * @description loads from registry if possible
   *
   * @param {String} styles styles to parse
   * @return {void}
   *
   * @see this.handleStyles
   */


  loadStylesIfNeeded(styles) {
    // if state was loaded server side
    if (this.css === _exotic.EMPTY_STRING && this.css !== this.state.css) {
      this.css = this.state.css;
    } // if observable already is already set up on our instance


    if (this.css !== _exotic.EMPTY_STRING && !HOT_RELOAD_STYLES) {
      return;
    } // load from registry if we've already transpiled


    if (styleRegistry.has(styles)) {
      this.css = styleRegistry.get(styles);
    } // gotta load em


    this.handleStyles(styles);
  }
  /**
   * @description transpile as needed, and updates state
   * @param {String} styles
   * @return {void}
   */


  handleStyles(styles) {
    // console.dir({ handlingStyles: css })
    const css = (0, _transpileStyles.transpileStyles)(styles); // save to global registry cache

    saveTranspiledStyles(this.props.styleseh, css); // set property, if observable

    this.css = css; // if we can set state, do it

    if (this.hasMounted || HOT_RELOAD_STYLES) {
      this.setState({
        css
      });
    }
  } // componentDidUpdate() {
  //   if (metaRegistry.has(this.css)) {
  //     // meta
  //     const meta = Object.seal({
  //       hasMounted: true,
  //       renderCount: 0,
  //       hashed,
  //     })
  //     metaRegistry.set(this.css, meta)
  //   }
  // }

  /* @lint dev */

  /* eslint-disable max-statements */

  /**
   * @see https://github.com/threepointone/glamor/blob/master/docs/server.md
   * @description if HOT_RELOAD_STYLESforce reload
   * @return {JSX.Element<CSSStyleSheet>}
   */


  render() {
    const found = getElementFromRegistry(this.css); // if (HOT_RELOAD_STYLES) {
    //   hashed += 1
    //   const attributes = Object.seal({
    //     key: hashed,
    //   })
    //   const rendered = fromStringToStyle(this.css, attributes)
    //   styleBlockRegistry.set(this.css, rendered)
    //   return rendered
    // }

    if (found === false) {
      hashed += 1; // jsx blocks

      const attributes = Object.seal({
        key: hashed
      });
      const rendered = (0, _fromStringToStyleTag.fromStringToStyle)(this.css, attributes);
      styleBlockRegistry.set(this.css, rendered);
      return rendered;
    } else {
      return found;
    }
  }

};
exports.StyledComponent = StyledComponent;
StyledComponent.propTypes = {
  styleseh: _types.string.isRequired,
  // or #id
  className: _types.string // component: Object.optional,

  /**
   * @type css only
   */

};
let logged = false; // Array.from(stylez.metaRegistry.entries()).filter((kv) => {
//   const [key, value] = kv
//   // console.log({key, value})
//   return value.duplicationCount > 1
// })

/**
 * @todo !!!!!!!!!!!! should be loading webworker
 *
 * @todo - processing vs memory
 * if we hash every time, more processing, less memory
 * no processing...
 */

function markDuplicationIfNeeded(css, named) {
  const isInStyleStrings = cssStringList.includes(css) === true;
  const isInStyleRegistry = styleRegistry.has(css) === true;

  if (metaRegistry.has(css) === true) {
    const meta = metaRegistry.get(css);

    if (meta.names.includes(named) === false) {
      // !!! USED IN A DIFF COMPONENT !!!
      meta.REQUIRES_SOLUTION = true;
    } else {
      meta.names.push(named);
    } // if (meta.hasMounted === false) {
    //   meta.duplicationCount += 1
    // }


    meta.duplicationCount += 1;
  } else {
    const hash = (0, _index.fliphash)(css); // meta

    const meta = Object.seal({
      REQUIRES_SOLUTION: false,
      names: [named],
      hasMounted: true,
      renderCount: 0,
      duplicationCount: 1,
      hashed,
      hash,
      isInStyleStrings,
      isInStyleRegistry
    });
    metaRegistry.set(css, meta);
  } // return metaRegistry.get(css)

}
/**
 * @see fromStringToStyle
 * @see toComponentName
 *
 * @param {String} css styles to transpile as a <style> tag
 * @param {React.ComponentClass} [Target=undefined]
 * @return {StyledComponent}
 */


function asStyledComponent(css, Target = undefined) {
  // const hash = fliphash(css)
  const name = (0, _identifier.toComponentName)(Target);
  markDuplicationIfNeeded(css, name);
  const meta = metaRegistry.get(css);
  const isInStyleRegistry = meta.isInStyleRegistry,
        isInStyleStrings = meta.isInStyleStrings,
        REQUIRES_SOLUTION = meta.REQUIRES_SOLUTION;
  /**
   * @note it is pulling from registry in the render, but not hoisting
   * @todo if we provide a context per page & large widget, should be easy hoist
   * OR provide `namespace` in the  styled.namespace
   *
   * @todo would also work to use for snapshots to dedupe
   * @todo can use chain includesCount for how many times we have the style to more easily dedupe
   */

  if (isInStyleRegistry && REQUIRES_SOLUTION === false) {
    if (logged === false) {
      console.warn(`
      already had these styles connected.
      update state with an observable,
      or refresh
      (should connect HMR.accept to this module)
    `);
      logged = true;
    } // else


    return '';
  } else if (isInStyleStrings && REQUIRES_SOLUTION === false) {
    /**
     * @todo - this is when we would hoist original
     */
    if (logged === false) {
      console.warn(`already transpiled these styles`);
      logged = true;
    }

    globalStyleBlocks.add(css);
    return '';
  }

  cssStringList.push(css); // @todo - should add fromStyleToKey

  const node = _react.default.createElement(StyledComponent, {
    key: css,
    styleseh: css,
    "data-for-component": name,
    __source: {
      fileName: _jsxFileName,
      lineNumber: 365
    },
    __self: this
  });

  return node;
} // if (typeof window === 'object') {
//   window.React = React
//   window.stylez = {
//     styleRegistry,
//     styleBlockRegistry,
//     globalStyleBlocks,
//     metaRegistry,
//     cssStringList,
//   }
// }


var _default = asStyledComponent;
exports.default = _default;