import _extends from '@babel/runtime/helpers/esm/extends'; import isInBrowser from 'is-in-browser'; import warning from 'tiny-warning'; import _createClass from '@babel/runtime/helpers/esm/createClass'; import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose'; import _assertThisInitialized from '@babel/runtime/helpers/esm/assertThisInitialized'; import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/esm/objectWithoutPropertiesLoose'; var plainObjectConstrurctor = {}.constructor; function cloneStyle(style) { if (style == null || typeof style !== 'object') return style; if (Array.isArray(style)) return style.map(cloneStyle); if (style.constructor !== plainObjectConstrurctor) return style; var newStyle = {}; for (var name in style) { newStyle[name] = cloneStyle(style[name]); } return newStyle; } /** * Create a rule instance. */ function createRule(name, decl, options) { if (name === void 0) { name = 'unnamed'; } var jss = options.jss; var declCopy = cloneStyle(decl); var rule = jss.plugins.onCreateRule(name, declCopy, options); if (rule) return rule; // It is an at-rule and it has no instance. if (name[0] === '@') { process.env.NODE_ENV !== "production" ? warning(false, "[JSS] Unknown rule " + name) : void 0; } return null; } var join = function join(value, by) { var result = ''; for (var i = 0; i < value.length; i++) { // Remove !important from the value, it will be readded later. if (value[i] === '!important') break; if (result) result += by; result += value[i]; } return result; }; /** * Converts array values to string. * * `margin: [['5px', '10px']]` > `margin: 5px 10px;` * `border: ['1px', '2px']` > `border: 1px, 2px;` * `margin: [['5px', '10px'], '!important']` > `margin: 5px 10px !important;` * `color: ['red', !important]` > `color: red !important;` */ var toCssValue = function toCssValue(value, ignoreImportant) { if (ignoreImportant === void 0) { ignoreImportant = false; } if (!Array.isArray(value)) return value; var cssValue = ''; // Support space separated values via `[['5px', '10px']]`. if (Array.isArray(value[0])) { for (var i = 0; i < value.length; i++) { if (value[i] === '!important') break; if (cssValue) cssValue += ', '; cssValue += join(value[i], ' '); } } else cssValue = join(value, ', '); // Add !important, because it was ignored. if (!ignoreImportant && value[value.length - 1] === '!important') { cssValue += ' !important'; } return cssValue; }; /** * Indent a string. * http://jsperf.com/array-join-vs-for */ function indentStr(str, indent) { var result = ''; for (var index = 0; index < indent; index++) { result += ' '; } return result + str; } /** * Converts a Rule to CSS string. */ function toCss(selector, style, options) { if (options === void 0) { options = {}; } var result = ''; if (!style) return result; var _options = options, _options$indent = _options.indent, indent = _options$indent === void 0 ? 0 : _options$indent; var fallbacks = style.fallbacks; if (selector) indent++; // Apply fallbacks first. if (fallbacks) { // Array syntax {fallbacks: [{prop: value}]} if (Array.isArray(fallbacks)) { for (var index = 0; index < fallbacks.length; index++) { var fallback = fallbacks[index]; for (var prop in fallback) { var value = fallback[prop]; if (value != null) { if (result) result += '\n'; result += indentStr(prop + ": " + toCssValue(value) + ";", indent); } } } } else { // Object syntax {fallbacks: {prop: value}} for (var _prop in fallbacks) { var _value = fallbacks[_prop]; if (_value != null) { if (result) result += '\n'; result += indentStr(_prop + ": " + toCssValue(_value) + ";", indent); } } } } for (var _prop2 in style) { var _value2 = style[_prop2]; if (_value2 != null && _prop2 !== 'fallbacks') { if (result) result += '\n'; result += indentStr(_prop2 + ": " + toCssValue(_value2) + ";", indent); } } // Allow empty style in this case, because properties will be added dynamically. if (!result && !options.allowEmpty) return result; // When rule is being stringified before selector was defined. if (!selector) return result; indent--; if (result) result = "\n" + result + "\n"; return indentStr(selector + " {" + result, indent) + indentStr('}', indent); } var escapeRegex = /([[\].#*$><+~=|^:(),"'`\s])/g; var nativeEscape = typeof CSS !== 'undefined' && CSS.escape; var escape = (function (str) { return nativeEscape ? nativeEscape(str) : str.replace(escapeRegex, '\\$1'); }); var BaseStyleRule = /*#__PURE__*/ function () { function BaseStyleRule(key, style, options) { this.type = 'style'; this.key = void 0; this.isProcessed = false; this.style = void 0; this.renderer = void 0; this.renderable = void 0; this.options = void 0; var sheet = options.sheet, Renderer = options.Renderer; this.key = key; this.options = options; this.style = style; if (sheet) this.renderer = sheet.renderer;else if (Renderer) this.renderer = new Renderer(); } /** * Get or set a style property. */ var _proto = BaseStyleRule.prototype; _proto.prop = function prop(name, value, options) { // It's a getter. if (value === undefined) return this.style[name]; // Don't do anything if the value has not changed. var force = options ? options.force : false; if (!force && this.style[name] === value) return this; var newValue = value; if (!options || options.process !== false) { newValue = this.options.jss.plugins.onChangeValue(value, name, this); } var isEmpty = newValue == null || newValue === false; var isDefined = name in this.style; // Value is empty and wasn't defined before. if (isEmpty && !isDefined && !force) return this; // We are going to remove this value. var remove = isEmpty && isDefined; if (remove) delete this.style[name];else this.style[name] = newValue; // Renderable is defined if StyleSheet option `link` is true. if (this.renderable && this.renderer) { if (remove) this.renderer.removeProperty(this.renderable, name);else this.renderer.setProperty(this.renderable, name, newValue); return this; } var sheet = this.options.sheet; if (sheet && sheet.attached) { process.env.NODE_ENV !== "production" ? warning(false, '[JSS] Rule is not linked. Missing sheet option "link: true".') : void 0; } return this; }; return BaseStyleRule; }(); var StyleRule = /*#__PURE__*/ function (_BaseStyleRule) { _inheritsLoose(StyleRule, _BaseStyleRule); function StyleRule(key, style, options) { var _this; _this = _BaseStyleRule.call(this, key, style, options) || this; _this.selectorText = void 0; _this.id = void 0; _this.renderable = void 0; var selector = options.selector, scoped = options.scoped, sheet = options.sheet, generateId = options.generateId; if (selector) { _this.selectorText = selector; } else if (scoped !== false) { _this.id = generateId(_assertThisInitialized(_assertThisInitialized(_this)), sheet); _this.selectorText = "." + escape(_this.id); } return _this; } /** * Set selector string. * Attention: use this with caution. Most browsers didn't implement * selectorText setter, so this may result in rerendering of entire Style Sheet. */ var _proto2 = StyleRule.prototype; /** * Apply rule to an element inline. */ _proto2.applyTo = function applyTo(renderable) { var renderer = this.renderer; if (renderer) { var json = this.toJSON(); for (var prop in json) { renderer.setProperty(renderable, prop, json[prop]); } } return this; } /** * Returns JSON representation of the rule. * Fallbacks are not supported. * Useful for inline styles. */ ; _proto2.toJSON = function toJSON() { var json = {}; for (var prop in this.style) { var value = this.style[prop]; if (typeof value !== 'object') json[prop] = value;else if (Array.isArray(value)) json[prop] = toCssValue(value); } return json; } /** * Generates a CSS string. */ ; _proto2.toString = function toString(options) { var sheet = this.options.sheet; var link = sheet ? sheet.options.link : false; var opts = link ? _extends({}, options, { allowEmpty: true }) : options; return toCss(this.selectorText, this.style, opts); }; _createClass(StyleRule, [{ key: "selector", set: function set(selector) { if (selector === this.selectorText) return; this.selectorText = selector; var renderer = this.renderer, renderable = this.renderable; if (!renderable || !renderer) return; var hasChanged = renderer.setSelector(renderable, selector); // If selector setter is not implemented, rerender the rule. if (!hasChanged) { renderer.replaceRule(renderable, this); } } /** * Get selector string. */ , get: function get() { return this.selectorText; } }]); return StyleRule; }(BaseStyleRule); var pluginStyleRule = { onCreateRule: function onCreateRule(name, style, options) { if (name[0] === '@' || options.parent && options.parent.type === 'keyframes') { return null; } return new StyleRule(name, style, options); } }; var defaultToStringOptions = { indent: 1, children: true }; var atRegExp = /@([\w-]+)/; /** * Conditional rule for @media, @supports */ var ConditionalRule = /*#__PURE__*/ function () { function ConditionalRule(key, styles, options) { this.type = 'conditional'; this.at = void 0; this.key = void 0; this.query = void 0; this.rules = void 0; this.options = void 0; this.isProcessed = false; this.renderable = void 0; this.key = key; var atMatch = key.match(atRegExp); this.at = atMatch ? atMatch[1] : 'unknown'; // Key might contain a unique suffix in case the `name` passed by user was duplicate. this.query = options.name || "@" + this.at; this.options = options; this.rules = new RuleList(_extends({}, options, { parent: this })); for (var name in styles) { this.rules.add(name, styles[name]); } this.rules.process(); } /** * Get a rule. */ var _proto = ConditionalRule.prototype; _proto.getRule = function getRule(name) { return this.rules.get(name); } /** * Get index of a rule. */ ; _proto.indexOf = function indexOf(rule) { return this.rules.indexOf(rule); } /** * Create and register rule, run plugins. */ ; _proto.addRule = function addRule(name, style, options) { var rule = this.rules.add(name, style, options); if (!rule) return null; this.options.jss.plugins.onProcessRule(rule); return rule; } /** * Generates a CSS string. */ ; _proto.toString = function toString(options) { if (options === void 0) { options = defaultToStringOptions; } if (options.indent == null) options.indent = defaultToStringOptions.indent; if (options.children == null) options.children = defaultToStringOptions.children; if (options.children === false) { return this.query + " {}"; } var children = this.rules.toString(options); return children ? this.query + " {\n" + children + "\n}" : ''; }; return ConditionalRule; }(); var keyRegExp = /@media|@supports\s+/; var pluginConditionalRule = { onCreateRule: function onCreateRule(key, styles, options) { return keyRegExp.test(key) ? new ConditionalRule(key, styles, options) : null; } }; var defaultToStringOptions$1 = { indent: 1, children: true }; var nameRegExp = /@keyframes\s+([\w-]+)/; /** * Rule for @keyframes */ var KeyframesRule = /*#__PURE__*/ function () { function KeyframesRule(key, frames, options) { this.type = 'keyframes'; this.at = '@keyframes'; this.key = void 0; this.name = void 0; this.id = void 0; this.rules = void 0; this.options = void 0; this.isProcessed = false; this.renderable = void 0; var nameMatch = key.match(nameRegExp); if (nameMatch && nameMatch[1]) { this.name = nameMatch[1]; } else { this.name = 'noname'; process.env.NODE_ENV !== "production" ? warning(false, "[JSS] Bad keyframes name " + key) : void 0; } this.key = this.type + "-" + this.name; this.options = options; var scoped = options.scoped, sheet = options.sheet, generateId = options.generateId; this.id = scoped === false ? this.name : escape(generateId(this, sheet)); this.rules = new RuleList(_extends({}, options, { parent: this })); for (var name in frames) { this.rules.add(name, frames[name], _extends({}, options, { parent: this })); } this.rules.process(); } /** * Generates a CSS string. */ var _proto = KeyframesRule.prototype; _proto.toString = function toString(options) { if (options === void 0) { options = defaultToStringOptions$1; } if (options.indent == null) options.indent = defaultToStringOptions$1.indent; if (options.children == null) options.children = defaultToStringOptions$1.children; if (options.children === false) { return this.at + " " + this.id + " {}"; } var children = this.rules.toString(options); if (children) children = "\n" + children + "\n"; return this.at + " " + this.id + " {" + children + "}"; }; return KeyframesRule; }(); var keyRegExp$1 = /@keyframes\s+/; var refRegExp = /\$([\w-]+)/g; var findReferencedKeyframe = function findReferencedKeyframe(val, keyframes) { if (typeof val === 'string') { return val.replace(refRegExp, function (match, name) { if (name in keyframes) { return keyframes[name]; } process.env.NODE_ENV !== "production" ? warning(false, "[JSS] Referenced keyframes rule \"" + name + "\" is not defined.") : void 0; return match; }); } return val; }; /** * Replace the reference for a animation name. */ var replaceRef = function replaceRef(style, prop, keyframes) { var value = style[prop]; var refKeyframe = findReferencedKeyframe(value, keyframes); if (refKeyframe !== value) { style[prop] = refKeyframe; } }; var plugin = { onCreateRule: function onCreateRule(key, frames, options) { return typeof key === 'string' && keyRegExp$1.test(key) ? new KeyframesRule(key, frames, options) : null; }, // Animation name ref replacer. onProcessStyle: function onProcessStyle(style, rule, sheet) { if (rule.type !== 'style' || !sheet) return style; if ('animation-name' in style) replaceRef(style, 'animation-name', sheet.keyframes); if ('animation' in style) replaceRef(style, 'animation', sheet.keyframes); return style; }, onChangeValue: function onChangeValue(val, prop, rule) { var sheet = rule.options.sheet; if (!sheet) { return val; } switch (prop) { case 'animation': return findReferencedKeyframe(val, sheet.keyframes); case 'animation-name': return findReferencedKeyframe(val, sheet.keyframes); default: return val; } } }; var KeyframeRule = /*#__PURE__*/ function (_BaseStyleRule) { _inheritsLoose(KeyframeRule, _BaseStyleRule); function KeyframeRule() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _BaseStyleRule.call.apply(_BaseStyleRule, [this].concat(args)) || this; _this.renderable = void 0; return _this; } var _proto = KeyframeRule.prototype; /** * Generates a CSS string. */ _proto.toString = function toString(options) { var sheet = this.options.sheet; var link = sheet ? sheet.options.link : false; var opts = link ? _extends({}, options, { allowEmpty: true }) : options; return toCss(this.key, this.style, opts); }; return KeyframeRule; }(BaseStyleRule); var pluginKeyframeRule = { onCreateRule: function onCreateRule(key, style, options) { if (options.parent && options.parent.type === 'keyframes') { return new KeyframeRule(key, style, options); } return null; } }; var FontFaceRule = /*#__PURE__*/ function () { function FontFaceRule(key, style, options) { this.type = 'font-face'; this.at = '@font-face'; this.key = void 0; this.style = void 0; this.options = void 0; this.isProcessed = false; this.renderable = void 0; this.key = key; this.style = style; this.options = options; } /** * Generates a CSS string. */ var _proto = FontFaceRule.prototype; _proto.toString = function toString(options) { if (Array.isArray(this.style)) { var str = ''; for (var index = 0; index < this.style.length; index++) { str += toCss(this.at, this.style[index]); if (this.style[index + 1]) str += '\n'; } return str; } return toCss(this.at, this.style, options); }; return FontFaceRule; }(); var keyRegExp$2 = /@font-face/; var pluginFontFaceRule = { onCreateRule: function onCreateRule(key, style, options) { return keyRegExp$2.test(key) ? new FontFaceRule(key, style, options) : null; } }; var ViewportRule = /*#__PURE__*/ function () { function ViewportRule(key, style, options) { this.type = 'viewport'; this.at = '@viewport'; this.key = void 0; this.style = void 0; this.options = void 0; this.isProcessed = false; this.renderable = void 0; this.key = key; this.style = style; this.options = options; } /** * Generates a CSS string. */ var _proto = ViewportRule.prototype; _proto.toString = function toString(options) { return toCss(this.key, this.style, options); }; return ViewportRule; }(); var pluginViewportRule = { onCreateRule: function onCreateRule(key, style, options) { return key === '@viewport' || key === '@-ms-viewport' ? new ViewportRule(key, style, options) : null; } }; var SimpleRule = /*#__PURE__*/ function () { function SimpleRule(key, value, options) { this.type = 'simple'; this.key = void 0; this.value = void 0; this.options = void 0; this.isProcessed = false; this.renderable = void 0; this.key = key; this.value = value; this.options = options; } /** * Generates a CSS string. */ // eslint-disable-next-line no-unused-vars var _proto = SimpleRule.prototype; _proto.toString = function toString(options) { if (Array.isArray(this.value)) { var str = ''; for (var index = 0; index < this.value.length; index++) { str += this.key + " " + this.value[index] + ";"; if (this.value[index + 1]) str += '\n'; } return str; } return this.key + " " + this.value + ";"; }; return SimpleRule; }(); var keysMap = { '@charset': true, '@import': true, '@namespace': true }; var pluginSimpleRule = { onCreateRule: function onCreateRule(key, value, options) { return key in keysMap ? new SimpleRule(key, value, options) : null; } }; var plugins = [pluginStyleRule, pluginConditionalRule, plugin, pluginKeyframeRule, pluginFontFaceRule, pluginViewportRule, pluginSimpleRule]; var defaultUpdateOptions = { process: true }; var forceUpdateOptions = { force: true, process: true /** * Contains rules objects and allows adding/removing etc. * Is used for e.g. by `StyleSheet` or `ConditionalRule`. */ }; var RuleList = /*#__PURE__*/ function () { // Rules registry for access by .get() method. // It contains the same rule registered by name and by selector. // Original styles object. // Used to ensure correct rules order. function RuleList(options) { this.map = {}; this.raw = {}; this.index = []; this.counter = 0; this.options = void 0; this.classes = void 0; this.keyframes = void 0; this.options = options; this.classes = options.classes; this.keyframes = options.keyframes; } /** * Create and register rule. * * Will not render after Style Sheet was rendered the first time. */ var _proto = RuleList.prototype; _proto.add = function add(name, decl, ruleOptions) { var _this$options = this.options, parent = _this$options.parent, sheet = _this$options.sheet, jss = _this$options.jss, Renderer = _this$options.Renderer, generateId = _this$options.generateId, scoped = _this$options.scoped; var options = _extends({ classes: this.classes, parent: parent, sheet: sheet, jss: jss, Renderer: Renderer, generateId: generateId, scoped: scoped, name: name, keyframes: this.keyframes, selector: undefined }, ruleOptions); // When user uses .createStyleSheet(), duplicate names are not possible, but // `sheet.addRule()` opens the door for any duplicate rule name. When this happens // we need to make the key unique within this RuleList instance scope. var key = name; if (name in this.raw) { key = name + "-d" + this.counter++; } // We need to save the original decl before creating the rule // because cache plugin needs to use it as a key to return a cached rule. this.raw[key] = decl; if (key in this.classes) { // E.g. rules inside of @media container options.selector = "." + escape(this.classes[key]); } var rule = createRule(key, decl, options); if (!rule) return null; this.register(rule); var index = options.index === undefined ? this.index.length : options.index; this.index.splice(index, 0, rule); return rule; } /** * Get a rule. */ ; _proto.get = function get(name) { return this.map[name]; } /** * Delete a rule. */ ; _proto.remove = function remove(rule) { this.unregister(rule); delete this.raw[rule.key]; this.index.splice(this.index.indexOf(rule), 1); } /** * Get index of a rule. */ ; _proto.indexOf = function indexOf(rule) { return this.index.indexOf(rule); } /** * Run `onProcessRule()` plugins on every rule. */ ; _proto.process = function process() { var plugins = this.options.jss.plugins; // We need to clone array because if we modify the index somewhere else during a loop // we end up with very hard-to-track-down side effects. this.index.slice(0).forEach(plugins.onProcessRule, plugins); } /** * Register a rule in `.map`, `.classes` and `.keyframes` maps. */ ; _proto.register = function register(rule) { this.map[rule.key] = rule; if (rule instanceof StyleRule) { this.map[rule.selector] = rule; if (rule.id) this.classes[rule.key] = rule.id; } else if (rule instanceof KeyframesRule && this.keyframes) { this.keyframes[rule.name] = rule.id; } } /** * Unregister a rule. */ ; _proto.unregister = function unregister(rule) { delete this.map[rule.key]; if (rule instanceof StyleRule) { delete this.map[rule.selector]; delete this.classes[rule.key]; } else if (rule instanceof KeyframesRule) { delete this.keyframes[rule.name]; } } /** * Update the function values with a new data. */ ; _proto.update = function update() { var name; var data; var options; if (typeof (arguments.length <= 0 ? undefined : arguments[0]) === 'string') { name = arguments.length <= 0 ? undefined : arguments[0]; // $FlowFixMe[invalid-tuple-index] data = arguments.length <= 1 ? undefined : arguments[1]; // $FlowFixMe[invalid-tuple-index] options = arguments.length <= 2 ? undefined : arguments[2]; } else { data = arguments.length <= 0 ? undefined : arguments[0]; // $FlowFixMe[invalid-tuple-index] options = arguments.length <= 1 ? undefined : arguments[1]; name = null; } if (name) { this.updateOne(this.map[name], data, options); } else { for (var index = 0; index < this.index.length; index++) { this.updateOne(this.index[index], data, options); } } } /** * Execute plugins, update rule props. */ ; _proto.updateOne = function updateOne(rule, data, options) { if (options === void 0) { options = defaultUpdateOptions; } var _this$options2 = this.options, plugins = _this$options2.jss.plugins, sheet = _this$options2.sheet; // It is a rules container like for e.g. ConditionalRule. if (rule.rules instanceof RuleList) { rule.rules.update(data, options); return; } var styleRule = rule; var style = styleRule.style; plugins.onUpdate(data, rule, sheet, options); // We rely on a new `style` ref in case it was mutated during onUpdate hook. if (options.process && style && style !== styleRule.style) { // We need to run the plugins in case new `style` relies on syntax plugins. plugins.onProcessStyle(styleRule.style, styleRule, sheet); // Update and add props. for (var prop in styleRule.style) { var nextValue = styleRule.style[prop]; var prevValue = style[prop]; // We need to use `force: true` because `rule.style` has been updated during onUpdate hook, so `rule.prop()` will not update the CSSOM rule. // We do this comparison to avoid unneeded `rule.prop()` calls, since we have the old `style` object here. if (nextValue !== prevValue) { styleRule.prop(prop, nextValue, forceUpdateOptions); } } // Remove props. for (var _prop in style) { var _nextValue = styleRule.style[_prop]; var _prevValue = style[_prop]; // We need to use `force: true` because `rule.style` has been updated during onUpdate hook, so `rule.prop()` will not update the CSSOM rule. // We do this comparison to avoid unneeded `rule.prop()` calls, since we have the old `style` object here. if (_nextValue == null && _nextValue !== _prevValue) { styleRule.prop(_prop, null, forceUpdateOptions); } } } } /** * Convert rules to a CSS string. */ ; _proto.toString = function toString(options) { var str = ''; var sheet = this.options.sheet; var link = sheet ? sheet.options.link : false; for (var index = 0; index < this.index.length; index++) { var rule = this.index[index]; var css = rule.toString(options); // No need to render an empty rule. if (!css && !link) continue; if (str) str += '\n'; str += css; } return str; }; return RuleList; }(); var StyleSheet = /*#__PURE__*/ function () { function StyleSheet(styles, options) { this.options = void 0; this.deployed = void 0; this.attached = void 0; this.rules = void 0; this.renderer = void 0; this.classes = void 0; this.keyframes = void 0; this.queue = void 0; this.attached = false; this.deployed = false; this.classes = {}; this.keyframes = {}; this.options = _extends({}, options, { sheet: this, parent: this, classes: this.classes, keyframes: this.keyframes }); if (options.Renderer) { this.renderer = new options.Renderer(this); } this.rules = new RuleList(this.options); for (var name in styles) { this.rules.add(name, styles[name]); } this.rules.process(); } /** * Attach renderable to the render tree. */ var _proto = StyleSheet.prototype; _proto.attach = function attach() { if (this.attached) return this; if (this.renderer) this.renderer.attach(); this.attached = true; // Order is important, because we can't use insertRule API if style element is not attached. if (!this.deployed) this.deploy(); return this; } /** * Remove renderable from render tree. */ ; _proto.detach = function detach() { if (!this.attached) return this; if (this.renderer) this.renderer.detach(); this.attached = false; return this; } /** * Add a rule to the current stylesheet. * Will insert a rule also after the stylesheet has been rendered first time. */ ; _proto.addRule = function addRule(name, decl, options) { var queue = this.queue; // Plugins can create rules. // In order to preserve the right order, we need to queue all `.addRule` calls, // which happen after the first `rules.add()` call. if (this.attached && !queue) this.queue = []; var rule = this.rules.add(name, decl, options); if (!rule) return null; this.options.jss.plugins.onProcessRule(rule); if (this.attached) { if (!this.deployed) return rule; // Don't insert rule directly if there is no stringified version yet. // It will be inserted all together when .attach is called. if (queue) queue.push(rule);else { this.insertRule(rule); if (this.queue) { this.queue.forEach(this.insertRule, this); this.queue = undefined; } } return rule; } // We can't add rules to a detached style node. // We will redeploy the sheet once user will attach it. this.deployed = false; return rule; } /** * Insert rule into the StyleSheet */ ; _proto.insertRule = function insertRule(rule) { if (this.renderer) { this.renderer.insertRule(rule); } } /** * Create and add rules. * Will render also after Style Sheet was rendered the first time. */ ; _proto.addRules = function addRules(styles, options) { var added = []; for (var name in styles) { var rule = this.addRule(name, styles[name], options); if (rule) added.push(rule); } return added; } /** * Get a rule by name. */ ; _proto.getRule = function getRule(name) { return this.rules.get(name); } /** * Delete a rule by name. * Returns `true`: if rule has been deleted from the DOM. */ ; _proto.deleteRule = function deleteRule(name) { var rule = typeof name === 'object' ? name : this.rules.get(name); if (!rule || // Style sheet was created without link: true and attached, in this case we // won't be able to remove the CSS rule from the DOM. this.attached && !rule.renderable) { return false; } this.rules.remove(rule); if (this.attached && rule.renderable && this.renderer) { return this.renderer.deleteRule(rule.renderable); } return true; } /** * Get index of a rule. */ ; _proto.indexOf = function indexOf(rule) { return this.rules.indexOf(rule); } /** * Deploy pure CSS string to a renderable. */ ; _proto.deploy = function deploy() { if (this.renderer) this.renderer.deploy(); this.deployed = true; return this; } /** * Update the function values with a new data. */ ; _proto.update = function update() { var _this$rules; (_this$rules = this.rules).update.apply(_this$rules, arguments); return this; } /** * Updates a single rule. */ ; _proto.updateOne = function updateOne(rule, data, options) { this.rules.updateOne(rule, data, options); return this; } /** * Convert rules to a CSS string. */ ; _proto.toString = function toString(options) { return this.rules.toString(options); }; return StyleSheet; }(); var PluginsRegistry = /*#__PURE__*/ function () { function PluginsRegistry() { this.plugins = { internal: [], external: [] }; this.registry = void 0; } var _proto = PluginsRegistry.prototype; /** * Call `onCreateRule` hooks and return an object if returned by a hook. */ _proto.onCreateRule = function onCreateRule(name, decl, options) { for (var i = 0; i < this.registry.onCreateRule.length; i++) { var rule = this.registry.onCreateRule[i](name, decl, options); if (rule) return rule; } return null; } /** * Call `onProcessRule` hooks. */ ; _proto.onProcessRule = function onProcessRule(rule) { if (rule.isProcessed) return; var sheet = rule.options.sheet; for (var i = 0; i < this.registry.onProcessRule.length; i++) { this.registry.onProcessRule[i](rule, sheet); } if (rule.style) this.onProcessStyle(rule.style, rule, sheet); rule.isProcessed = true; } /** * Call `onProcessStyle` hooks. */ ; _proto.onProcessStyle = function onProcessStyle(style, rule, sheet) { for (var i = 0; i < this.registry.onProcessStyle.length; i++) { // $FlowFixMe[prop-missing] rule.style = this.registry.onProcessStyle[i](rule.style, rule, sheet); } } /** * Call `onProcessSheet` hooks. */ ; _proto.onProcessSheet = function onProcessSheet(sheet) { for (var i = 0; i < this.registry.onProcessSheet.length; i++) { this.registry.onProcessSheet[i](sheet); } } /** * Call `onUpdate` hooks. */ ; _proto.onUpdate = function onUpdate(data, rule, sheet, options) { for (var i = 0; i < this.registry.onUpdate.length; i++) { this.registry.onUpdate[i](data, rule, sheet, options); } } /** * Call `onChangeValue` hooks. */ ; _proto.onChangeValue = function onChangeValue(value, prop, rule) { var processedValue = value; for (var i = 0; i < this.registry.onChangeValue.length; i++) { processedValue = this.registry.onChangeValue[i](processedValue, prop, rule); } return processedValue; } /** * Register a plugin. */ ; _proto.use = function use(newPlugin, options) { if (options === void 0) { options = { queue: 'external' }; } var plugins = this.plugins[options.queue]; // Avoids applying same plugin twice, at least based on ref. if (plugins.indexOf(newPlugin) !== -1) { return; } plugins.push(newPlugin); this.registry = [].concat(this.plugins.external, this.plugins.internal).reduce(function (registry, plugin) { for (var name in plugin) { if (name in registry) { registry[name].push(plugin[name]); } else { process.env.NODE_ENV !== "production" ? warning(false, "[JSS] Unknown hook \"" + name + "\".") : void 0; } } return registry; }, { onCreateRule: [], onProcessRule: [], onProcessStyle: [], onProcessSheet: [], onChangeValue: [], onUpdate: [] }); }; return PluginsRegistry; }(); /** * Sheets registry to access them all at one place. */ var SheetsRegistry = /*#__PURE__*/ function () { function SheetsRegistry() { this.registry = []; } var _proto = SheetsRegistry.prototype; /** * Register a Style Sheet. */ _proto.add = function add(sheet) { var registry = this.registry; var index = sheet.options.index; if (registry.indexOf(sheet) !== -1) return; if (registry.length === 0 || index >= this.index) { registry.push(sheet); return; } // Find a position. for (var i = 0; i < registry.length; i++) { if (registry[i].options.index > index) { registry.splice(i, 0, sheet); return; } } } /** * Reset the registry. */ ; _proto.reset = function reset() { this.registry = []; } /** * Remove a Style Sheet. */ ; _proto.remove = function remove(sheet) { var index = this.registry.indexOf(sheet); this.registry.splice(index, 1); } /** * Convert all attached sheets to a CSS string. */ ; _proto.toString = function toString(_temp) { var _ref = _temp === void 0 ? {} : _temp, attached = _ref.attached, options = _objectWithoutPropertiesLoose(_ref, ["attached"]); var css = ''; for (var i = 0; i < this.registry.length; i++) { var sheet = this.registry[i]; if (attached != null && sheet.attached !== attached) { continue; } if (css) css += '\n'; css += sheet.toString(options); } return css; }; _createClass(SheetsRegistry, [{ key: "index", /** * Current highest index number. */ get: function get() { return this.registry.length === 0 ? 0 : this.registry[this.registry.length - 1].options.index; } }]); return SheetsRegistry; }(); /** * This is a global sheets registry. Only DomRenderer will add sheets to it. * On the server one should use an own SheetsRegistry instance and add the * sheets to it, because you need to make sure to create a new registry for * each request in order to not leak sheets across requests. */ var registry = new SheetsRegistry(); /* eslint-disable */ /** * Now that `globalThis` is available on most platforms * (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis#browser_compatibility) * we check for `globalThis` first. `globalThis` is necessary for jss * to run in Agoric's secure version of JavaScript (SES). Under SES, * `globalThis` exists, but `window`, `self`, and `Function('return * this')()` are all undefined for security reasons. * * https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 */ var globalThis$1 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' && window.Math === Math ? window : typeof self !== 'undefined' && self.Math === Math ? self : Function('return this')(); var ns = '2f1acc6c3a606b082e5eef5e54414ffb'; if (globalThis$1[ns] == null) globalThis$1[ns] = 0; // Bundle may contain multiple JSS versions at the same time. In order to identify // the current version with just one short number and use it for classes generation // we use a counter. Also it is more accurate, because user can manually reevaluate // the module. var moduleId = globalThis$1[ns]++; var maxRules = 1e10; /** * Returns a function which generates unique class names based on counters. * When new generator function is created, rule counter is reseted. * We need to reset the rule counter for SSR for each request. */ var createGenerateId = function createGenerateId(options) { if (options === void 0) { options = {}; } var ruleCounter = 0; var generateId = function generateId(rule, sheet) { ruleCounter += 1; if (ruleCounter > maxRules) { process.env.NODE_ENV !== "production" ? warning(false, "[JSS] You might have a memory leak. Rule counter is at " + ruleCounter + ".") : void 0; } var jssId = ''; var prefix = ''; if (sheet) { if (sheet.options.classNamePrefix) { prefix = sheet.options.classNamePrefix; } if (sheet.options.jss.id != null) { jssId = String(sheet.options.jss.id); } } if (options.minify) { // Using "c" because a number can't be the first char in a class name. return "" + (prefix || 'c') + moduleId + jssId + ruleCounter; } return prefix + rule.key + "-" + moduleId + (jssId ? "-" + jssId : '') + "-" + ruleCounter; }; return generateId; }; /** * Cache the value from the first time a function is called. */ var memoize = function memoize(fn) { var value; return function () { if (!value) value = fn(); return value; }; }; /** * Get a style property value. */ var getPropertyValue = function getPropertyValue(cssRule, prop) { try { // Support CSSTOM. if (cssRule.attributeStyleMap) { return cssRule.attributeStyleMap.get(prop); } return cssRule.style.getPropertyValue(prop); } catch (err) { // IE may throw if property is unknown. return ''; } }; /** * Set a style property. */ var setProperty = function setProperty(cssRule, prop, value) { try { var cssValue = value; if (Array.isArray(value)) { cssValue = toCssValue(value, true); if (value[value.length - 1] === '!important') { cssRule.style.setProperty(prop, cssValue, 'important'); return true; } } // Support CSSTOM. if (cssRule.attributeStyleMap) { cssRule.attributeStyleMap.set(prop, cssValue); } else { cssRule.style.setProperty(prop, cssValue); } } catch (err) { // IE may throw if property is unknown. return false; } return true; }; /** * Remove a style property. */ var removeProperty = function removeProperty(cssRule, prop) { try { // Support CSSTOM. if (cssRule.attributeStyleMap) { cssRule.attributeStyleMap.delete(prop); } else { cssRule.style.removeProperty(prop); } } catch (err) { process.env.NODE_ENV !== "production" ? warning(false, "[JSS] DOMException \"" + err.message + "\" was thrown. Tried to remove property \"" + prop + "\".") : void 0; } }; /** * Set the selector. */ var setSelector = function setSelector(cssRule, selectorText) { cssRule.selectorText = selectorText; // Return false if setter was not successful. // Currently works in chrome only. return cssRule.selectorText === selectorText; }; /** * Gets the `head` element upon the first call and caches it. * We assume it can't be null. */ var getHead = memoize(function () { return document.querySelector('head'); }); /** * Find attached sheet with an index higher than the passed one. */ function findHigherSheet(registry, options) { for (var i = 0; i < registry.length; i++) { var sheet = registry[i]; if (sheet.attached && sheet.options.index > options.index && sheet.options.insertionPoint === options.insertionPoint) { return sheet; } } return null; } /** * Find attached sheet with the highest index. */ function findHighestSheet(registry, options) { for (var i = registry.length - 1; i >= 0; i--) { var sheet = registry[i]; if (sheet.attached && sheet.options.insertionPoint === options.insertionPoint) { return sheet; } } return null; } /** * Find a comment with "jss" inside. */ function findCommentNode(text) { var head = getHead(); for (var i = 0; i < head.childNodes.length; i++) { var node = head.childNodes[i]; if (node.nodeType === 8 && node.nodeValue.trim() === text) { return node; } } return null; } /** * Find a node before which we can insert the sheet. */ function findPrevNode(options) { var registry$1 = registry.registry; if (registry$1.length > 0) { // Try to insert before the next higher sheet. var sheet = findHigherSheet(registry$1, options); if (sheet && sheet.renderer) { return { parent: sheet.renderer.element.parentNode, node: sheet.renderer.element }; } // Otherwise insert after the last attached. sheet = findHighestSheet(registry$1, options); if (sheet && sheet.renderer) { return { parent: sheet.renderer.element.parentNode, node: sheet.renderer.element.nextSibling }; } } // Try to find a comment placeholder if registry is empty. var insertionPoint = options.insertionPoint; if (insertionPoint && typeof insertionPoint === 'string') { var comment = findCommentNode(insertionPoint); if (comment) { return { parent: comment.parentNode, node: comment.nextSibling }; } // If user specifies an insertion point and it can't be found in the document - // bad specificity issues may appear. process.env.NODE_ENV !== "production" ? warning(false, "[JSS] Insertion point \"" + insertionPoint + "\" not found.") : void 0; } return false; } /** * Insert style element into the DOM. */ function insertStyle(style, options) { var insertionPoint = options.insertionPoint; var nextNode = findPrevNode(options); if (nextNode !== false && nextNode.parent) { nextNode.parent.insertBefore(style, nextNode.node); return; } // Works with iframes and any node types. if (insertionPoint && typeof insertionPoint.nodeType === 'number') { // https://stackoverflow.com/questions/41328728/force-casting-in-flow var insertionPointElement = insertionPoint; var parentNode = insertionPointElement.parentNode; if (parentNode) parentNode.insertBefore(style, insertionPointElement.nextSibling);else process.env.NODE_ENV !== "production" ? warning(false, '[JSS] Insertion point is not in the DOM.') : void 0; return; } getHead().appendChild(style); } /** * Read jss nonce setting from the page if the user has set it. */ var getNonce = memoize(function () { var node = document.querySelector('meta[property="csp-nonce"]'); return node ? node.getAttribute('content') : null; }); var _insertRule = function insertRule(container, rule, index) { try { if ('insertRule' in container) { var c = container; c.insertRule(rule, index); } // Keyframes rule. else if ('appendRule' in container) { var _c = container; _c.appendRule(rule); } } catch (err) { process.env.NODE_ENV !== "production" ? warning(false, "[JSS] " + err.message) : void 0; return false; } return container.cssRules[index]; }; var getValidRuleInsertionIndex = function getValidRuleInsertionIndex(container, index) { var maxIndex = container.cssRules.length; // In case previous insertion fails, passed index might be wrong if (index === undefined || index > maxIndex) { // eslint-disable-next-line no-param-reassign return maxIndex; } return index; }; var createStyle = function createStyle() { var el = document.createElement('style'); // Without it, IE will have a broken source order specificity if we // insert rules after we insert the style tag. // It seems to kick-off the source order specificity algorithm. el.textContent = '\n'; return el; }; var DomRenderer = /*#__PURE__*/ function () { // HTMLStyleElement needs fixing https://github.com/facebook/flow/issues/2696 // Will be empty if link: true option is not set, because // it is only for use together with insertRule API. function DomRenderer(sheet) { this.getPropertyValue = getPropertyValue; this.setProperty = setProperty; this.removeProperty = removeProperty; this.setSelector = setSelector; this.element = void 0; this.sheet = void 0; this.hasInsertedRules = false; this.cssRules = []; // There is no sheet when the renderer is used from a standalone StyleRule. if (sheet) registry.add(sheet); this.sheet = sheet; var _ref = this.sheet ? this.sheet.options : {}, media = _ref.media, meta = _ref.meta, element = _ref.element; this.element = element || createStyle(); this.element.setAttribute('data-jss', ''); if (media) this.element.setAttribute('media', media); if (meta) this.element.setAttribute('data-meta', meta); var nonce = getNonce(); if (nonce) this.element.setAttribute('nonce', nonce); } /** * Insert style element into render tree. */ var _proto = DomRenderer.prototype; _proto.attach = function attach() { // In the case the element node is external and it is already in the DOM. if (this.element.parentNode || !this.sheet) return; insertStyle(this.element, this.sheet.options); // When rules are inserted using `insertRule` API, after `sheet.detach().attach()` // most browsers create a new CSSStyleSheet, except of all IEs. var deployed = Boolean(this.sheet && this.sheet.deployed); if (this.hasInsertedRules && deployed) { this.hasInsertedRules = false; this.deploy(); } } /** * Remove style element from render tree. */ ; _proto.detach = function detach() { if (!this.sheet) return; var parentNode = this.element.parentNode; if (parentNode) parentNode.removeChild(this.element); // In the most browsers, rules inserted using insertRule() API will be lost when style element is removed. // Though IE will keep them and we need a consistent behavior. if (this.sheet.options.link) { this.cssRules = []; this.element.textContent = '\n'; } } /** * Inject CSS string into element. */ ; _proto.deploy = function deploy() { var sheet = this.sheet; if (!sheet) return; if (sheet.options.link) { this.insertRules(sheet.rules); return; } this.element.textContent = "\n" + sheet.toString() + "\n"; } /** * Insert RuleList into an element. */ ; _proto.insertRules = function insertRules(rules, nativeParent) { for (var i = 0; i < rules.index.length; i++) { this.insertRule(rules.index[i], i, nativeParent); } } /** * Insert a rule into element. */ ; _proto.insertRule = function insertRule(rule, index, nativeParent) { if (nativeParent === void 0) { nativeParent = this.element.sheet; } if (rule.rules) { var parent = rule; var latestNativeParent = nativeParent; if (rule.type === 'conditional' || rule.type === 'keyframes') { var _insertionIndex = getValidRuleInsertionIndex(nativeParent, index); // We need to render the container without children first. latestNativeParent = _insertRule(nativeParent, parent.toString({ children: false }), _insertionIndex); if (latestNativeParent === false) { return false; } this.refCssRule(rule, _insertionIndex, latestNativeParent); } this.insertRules(parent.rules, latestNativeParent); return latestNativeParent; } var ruleStr = rule.toString(); if (!ruleStr) return false; var insertionIndex = getValidRuleInsertionIndex(nativeParent, index); var nativeRule = _insertRule(nativeParent, ruleStr, insertionIndex); if (nativeRule === false) { return false; } this.hasInsertedRules = true; this.refCssRule(rule, insertionIndex, nativeRule); return nativeRule; }; _proto.refCssRule = function refCssRule(rule, index, cssRule) { rule.renderable = cssRule; // We only want to reference the top level rules, deleteRule API doesn't support removing nested rules // like rules inside media queries or keyframes if (rule.options.parent instanceof StyleSheet) { this.cssRules[index] = cssRule; } } /** * Delete a rule. */ ; _proto.deleteRule = function deleteRule(cssRule) { var sheet = this.element.sheet; var index = this.indexOf(cssRule); if (index === -1) return false; sheet.deleteRule(index); this.cssRules.splice(index, 1); return true; } /** * Get index of a CSS Rule. */ ; _proto.indexOf = function indexOf(cssRule) { return this.cssRules.indexOf(cssRule); } /** * Generate a new CSS rule and replace the existing one. * * Only used for some old browsers because they can't set a selector. */ ; _proto.replaceRule = function replaceRule(cssRule, rule) { var index = this.indexOf(cssRule); if (index === -1) return false; this.element.sheet.deleteRule(index); this.cssRules.splice(index, 1); return this.insertRule(rule, index); } /** * Get all rules elements. */ ; _proto.getRules = function getRules() { return this.element.sheet.cssRules; }; return DomRenderer; }(); var instanceCounter = 0; var Jss = /*#__PURE__*/ function () { function Jss(options) { this.id = instanceCounter++; this.version = "10.7.1"; this.plugins = new PluginsRegistry(); this.options = { id: { minify: false }, createGenerateId: createGenerateId, Renderer: isInBrowser ? DomRenderer : null, plugins: [] }; this.generateId = createGenerateId({ minify: false }); for (var i = 0; i < plugins.length; i++) { this.plugins.use(plugins[i], { queue: 'internal' }); } this.setup(options); } /** * Prepares various options, applies plugins. * Should not be used twice on the same instance, because there is no plugins * deduplication logic. */ var _proto = Jss.prototype; _proto.setup = function setup(options) { if (options === void 0) { options = {}; } if (options.createGenerateId) { this.options.createGenerateId = options.createGenerateId; } if (options.id) { this.options.id = _extends({}, this.options.id, options.id); } if (options.createGenerateId || options.id) { this.generateId = this.options.createGenerateId(this.options.id); } if (options.insertionPoint != null) this.options.insertionPoint = options.insertionPoint; if ('Renderer' in options) { this.options.Renderer = options.Renderer; } // eslint-disable-next-line prefer-spread if (options.plugins) this.use.apply(this, options.plugins); return this; } /** * Create a Style Sheet. */ ; _proto.createStyleSheet = function createStyleSheet(styles, options) { if (options === void 0) { options = {}; } var _options = options, index = _options.index; if (typeof index !== 'number') { index = registry.index === 0 ? 0 : registry.index + 1; } var sheet = new StyleSheet(styles, _extends({}, options, { jss: this, generateId: options.generateId || this.generateId, insertionPoint: this.options.insertionPoint, Renderer: this.options.Renderer, index: index })); this.plugins.onProcessSheet(sheet); return sheet; } /** * Detach the Style Sheet and remove it from the registry. */ ; _proto.removeStyleSheet = function removeStyleSheet(sheet) { sheet.detach(); registry.remove(sheet); return this; } /** * Create a rule without a Style Sheet. * [Deprecated] will be removed in the next major version. */ ; _proto.createRule = function createRule$1(name, style, options) { if (style === void 0) { style = {}; } if (options === void 0) { options = {}; } // Enable rule without name for inline styles. if (typeof name === 'object') { // $FlowFixMe[incompatible-call] return this.createRule(undefined, name, style); } // $FlowFixMe[incompatible-type] var ruleOptions = _extends({}, options, { name: name, jss: this, Renderer: this.options.Renderer }); if (!ruleOptions.generateId) ruleOptions.generateId = this.generateId; if (!ruleOptions.classes) ruleOptions.classes = {}; if (!ruleOptions.keyframes) ruleOptions.keyframes = {}; var rule = createRule(name, style, ruleOptions); if (rule) this.plugins.onProcessRule(rule); return rule; } /** * Register plugin. Passed function will be invoked with a rule instance. */ ; _proto.use = function use() { var _this = this; for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) { plugins[_key] = arguments[_key]; } plugins.forEach(function (plugin) { _this.plugins.use(plugin); }); return this; }; return Jss; }(); /** * Extracts a styles object with only props that contain function values. */ function getDynamicStyles(styles) { var to = null; for (var key in styles) { var value = styles[key]; var type = typeof value; if (type === 'function') { if (!to) to = {}; to[key] = value; } else if (type === 'object' && value !== null && !Array.isArray(value)) { var extracted = getDynamicStyles(value); if (extracted) { if (!to) to = {}; to[key] = extracted; } } } return to; } /** * SheetsManager is like a WeakMap which is designed to count StyleSheet * instances and attach/detach automatically. */ var SheetsManager = /*#__PURE__*/ function () { function SheetsManager() { this.length = 0; this.sheets = new WeakMap(); } var _proto = SheetsManager.prototype; _proto.get = function get(key) { var entry = this.sheets.get(key); return entry && entry.sheet; }; _proto.add = function add(key, sheet) { if (this.sheets.has(key)) return; this.length++; this.sheets.set(key, { sheet: sheet, refs: 0 }); }; _proto.manage = function manage(key) { var entry = this.sheets.get(key); if (entry) { if (entry.refs === 0) { entry.sheet.attach(); } entry.refs++; return entry.sheet; } warning(false, "[JSS] SheetsManager: can't find sheet to manage"); return undefined; }; _proto.unmanage = function unmanage(key) { var entry = this.sheets.get(key); if (entry) { if (entry.refs > 0) { entry.refs--; if (entry.refs === 0) entry.sheet.detach(); } } else { warning(false, "SheetsManager: can't find sheet to unmanage"); } }; _createClass(SheetsManager, [{ key: "size", get: function get() { return this.length; } }]); return SheetsManager; }(); /** * A better abstraction over CSS. * * @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present * @website https://github.com/cssinjs/jss * @license MIT */ /** * Export a constant indicating if this browser has CSSTOM support. * https://developers.google.com/web/updates/2018/03/cssom */ var hasCSSTOMSupport = typeof CSS === 'object' && CSS != null && 'number' in CSS; /** * Creates a new instance of Jss. */ var create = function create(options) { return new Jss(options); }; /** * A global Jss instance. */ var jss = create(); export default jss; export { RuleList, SheetsManager, SheetsRegistry, create, createGenerateId, createRule, getDynamicStyles, hasCSSTOMSupport, registry as sheets, toCssValue };