Repository URL to install this package:
|
Version:
1.2.8 ▾
|
"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;