glam
Version:
inline css for your jsx
164 lines (138 loc) • 5.45 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function last(arr) {
return arr[arr.length - 1];
}
// import assign from 'object-assign'
/*
high performance StyleSheet for css-in-js systems
- uses multiple style tags behind the scenes for millions of rules
- uses `insertRule` for appending in production for *much* faster performance
- 'polyfills' on server side
// usage
import StyleSheet from 'glamor/lib/sheet'
let styleSheet = new StyleSheet()
styleSheet.inject()
- 'injects' the stylesheet into the page (or into memory if on server)
styleSheet.insert('#box { border: 1px solid red; }')
- appends a css rule into the stylesheet
*/
// const doc = global.document;
var isBrowser = typeof window !== 'undefined';
var oldIE = function () {
if (isBrowser) {
var div = document.createElement('div');
div.innerHTML = '<!--[if lt IE 10]><i></i><![endif]-->';
return div.getElementsByTagName('i').length === 1;
}
return false;
}();
var StyleSheet = function () {
function StyleSheet() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
document = _ref.document,
_ref$speedy = _ref.speedy,
speedy = _ref$speedy === undefined ? !(process.env.NODE_ENV !== 'production') && !(process.env.NODE_ENV === 'test') : _ref$speedy,
_ref$maxLength = _ref.maxLength,
maxLength = _ref$maxLength === undefined ? oldIE ? 4000 : 65000 : _ref$maxLength;
_classCallCheck(this, StyleSheet);
this.document = document;
this.isSpeedy = speedy; // the big drawback here is that the css won't be editable in devtools
// this.sheet = undefined;
this.tags = [];
this.maxLength = maxLength;
this.ctr = 0;
this.inject();
}
_createClass(StyleSheet, [{
key: 'makeStyleTag',
value: function makeStyleTag() {
var tag = this.document.createElement('style');
tag.type = 'text/css';
tag.setAttribute('data-glamor', '');
tag.appendChild(this.document.createTextNode(''));
// todo - use a reference node
(this.document.head || this.document.getElementsByTagName('head')[0]).appendChild(tag);
return tag;
}
}, {
key: 'sheetForTag',
value: function sheetForTag(tag) {
if (tag.sheet) {
return tag.sheet;
}
// this weirdness brought to you by firefox
for (var i = 0; i < this.document.styleSheets.length; i++) {
if (this.document.styleSheets[i].ownerNode === tag) {
return this.document.styleSheets[i];
}
}
}
}, {
key: 'getSheet',
value: function getSheet() {
return this.sheetForTag(last(this.tags));
}
}, {
key: 'inject',
value: function inject() {
if (this.injected) {
throw new Error('already injected');
}
this.tags[0] = this.makeStyleTag();
this.injected = true;
}
}, {
key: '_insert',
value: function _insert(rule) {
// this weirdness for perf, and chrome's weird bug
// https://stackoverflow.com/questions/20007992/chrome-suddenly-stopped-accepting-insertrule
try {
var sheet = this.getSheet();
sheet && sheet.insertRule(rule, rule.indexOf('@import') !== -1 ? 0 : sheet.cssRules.length);
} catch (e) {
if (process.env.NODE_ENV !== 'production') {
// might need beter dx for this
console.warn('whoops, illegal rule inserted', rule); //eslint-disable-line no-console
}
}
}
}, {
key: 'insert',
value: function insert(rule) {
var sheet = this.getSheet();
// this is the ultrafast version, works across browsers
if (this.isSpeedy && sheet && sheet.insertRule) {
this._insert(rule);
} else {
if (rule.indexOf('@import') !== -1) {
var tag = last(this.tags);
tag.insertBefore(this.document.createTextNode(rule), tag.firstChild);
} else {
last(this.tags).appendChild(this.document.createTextNode(rule));
}
}
this.ctr++;
if (this.ctr % this.maxLength === 0) {
this.tags.push(this.makeStyleTag());
}
}
}, {
key: 'rules',
value: function rules() {
var _this = this;
var arr = [];
this.tags.forEach(function (tag) {
return arr.splice.apply(arr, [arr.length, 0].concat(_toConsumableArray(Array.from(_this.sheetForTag(tag).cssRules))));
});
return arr;
}
}]);
return StyleSheet;
}();
exports.default = StyleSheet;