react-styles-injector
Version:
React component to inject scoped styles into the DOM. Client and server ready.
165 lines • 6.84 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setDevMode = void 0;
var react_1 = __importDefault(require("react"));
// Hashmap containing the hash of all the already injected styles
var existingStyles = {};
/**
* If the server cache is not initialized, the renderer will add
* a style tag per component. If the server cache is initialized
* and reset each time the root component is rendered, only the
* styles that have not already been injected will be.
*/
var useServerCache = false;
// Tell is the code is executed client side or server side
var isClient = !!(typeof window !== 'undefined' &&
window.document &&
window.document.createElement);
// Tell if the mode is development
// Has to be set in NODE_ENV
var isDev = false;
if (isClient &&
(window.location.hostname === 'localhost' ||
window.location.hostname === '127.0.0.1')) {
isDev = true;
}
var setDevMode = function () {
if (isClient) {
isDev = true;
}
};
exports.setDevMode = setDevMode;
var Styled = /** @class */ (function (_super) {
__extends(Styled, _super);
function Styled(props) {
var _this = _super.call(this, props) || this;
/**
* If only one style is passed, enclose in an array
*/
_this.stylesEnsuredAsArray = function (styles) {
if (!styles)
return [];
if (Array.isArray(styles))
return styles;
return [styles];
};
_this.injectStyles = function (props) {
/**
* Ensure client side and document exists
*/
if (!document || !document.head)
return;
/**
* Inject in the head only if the element
* has not already been injected
*/
return _this.stylesEnsuredAsArray(props.styles).forEach(function (style) {
if (!existingStyles[style.hash]) {
existingStyles[style.hash] = true;
var styleTag = document.createElement('style');
styleTag.id = style.hash;
styleTag.innerHTML = style.styles;
document.head.appendChild(styleTag);
}
});
};
/**
* Reset the cache if we are server-side and if
* init is set to true
*/
if (!isClient && props.initCache) {
useServerCache = true;
existingStyles = {};
}
/**
* If we are client side in production mode
* inject the styles only once in the constructor
*/
if (isClient && !isDev)
_this.injectStyles(props);
return _this;
}
Styled.prototype.render = function () {
var _a = this.props, asFragment = _a.asFragment, children = _a.children, className = _a.className, containerRef = _a.containerRef, styles = _a.styles, tag = _a.tag, otherHTMLProps = __rest(_a, ["asFragment", "children", "className", "containerRef", "styles", "tag"]);
var ComponentTag = tag || 'div';
var compiledClasseName = __spreadArray([
className || ''
], this.stylesEnsuredAsArray(styles).map(function (style) { return style.hash; })).join(' ')
.trim();
if (isClient) {
/**
* In dev mode, try to inject at each render since the
* styles may have changed following a hot module replacement
*/
if (isDev)
this.injectStyles(this.props);
if (asFragment) {
return react_1.default.createElement(react_1.default.Fragment, null, children);
}
return react_1.default.createElement(ComponentTag, __assign(__assign({}, otherHTMLProps), { className: compiledClasseName, ref: containerRef }), children);
}
/**
* If we are server side, inject the style tag
* with the styles stringified in a fragment
* and we don't add the container ref
*/
return (react_1.default.createElement(react_1.default.Fragment, null,
this.stylesEnsuredAsArray(styles).map(function (style) {
if (useServerCache && existingStyles[style.hash])
return null;
existingStyles[style.hash] = true;
return (react_1.default.createElement("style", { key: style.hash, dangerouslySetInnerHTML: { __html: style.styles } }));
}),
asFragment
? children
: react_1.default.createElement(ComponentTag, __assign(__assign({}, otherHTMLProps), { className: compiledClasseName, ref: containerRef }), children)));
};
return Styled;
}(react_1.default.PureComponent));
exports.default = Styled;
//# sourceMappingURL=index.js.map