UNPKG

jss-isolate

Version:

True rules isolation through automatic properties reset.

149 lines (114 loc) 4.48 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; exports['default'] = jssIsolate; var _inherited = require('css-initials/inherited'); var _inherited2 = _interopRequireDefault(_inherited); var _all = require('css-initials/all'); var _all2 = _interopRequireDefault(_all); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var resetSheetOptions = { meta: 'jss-isolate', // Lets make it always the first one in sheets for testing // and specificity. index: -Infinity, link: true }; var initialsMap = { inherited: _inherited2['default'], all: _all2['default'] }; var getStyle = function getStyle() { var option = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'inherited'; // Option is either "inherited" or "all". if (typeof option === 'string') return initialsMap[option]; if ((typeof option === 'undefined' ? 'undefined' : _typeof(option)) === 'object') { // Option is ["all/inherited", {...style}] if (Array.isArray(option)) { var type = option[0]; var style = option[1]; return _extends({}, initialsMap[type], style); } // Option is a style object, use inherited initials by default. return _extends({}, _inherited2['default'], option); } return _inherited2['default']; }; var ignoreParents = { keyframes: true, conditional: true }; var shouldIsolate = function shouldIsolate(rule, sheet, options) { var parent = rule.options.parent; if (parent && ignoreParents[parent.type]) { return false; } var isolate = options.isolate == null ? true : options.isolate; if (sheet.options.isolate != null) isolate = sheet.options.isolate; if (rule.style.isolate != null) { isolate = rule.style.isolate; delete rule.style.isolate; } // Option `isolate` may be for e.g. `{isolate: 'root'}`. // In this case it must match the rule name in order to isolate it. if (typeof isolate === 'string') { return isolate === rule.key; } return isolate; }; /** * Performance optimized debounce without using setTimeout. * Returns a function which: * - will execute the passed fn not more than once per delay * - will not execute the passed fn if last try was within delay */ var createDebounced = function createDebounced(fn) { var delay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3; var time = Date.now(); return function () { var now = Date.now(); if (now - time < delay) return false; time = now; fn(); return true; }; }; function jssIsolate() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var setSelectorDone = false; var selectors = []; var resetSheet = void 0; var resetRule = void 0; var setSelector = function setSelector() { resetRule.selector = selectors.join(',\n'); }; var setSelectorDebounced = createDebounced(setSelector); function onProcessRule(rule, sheet) { if (!sheet || sheet === resetSheet || rule.type !== 'style') return; if (!shouldIsolate(rule, sheet, options)) return; // Create a reset Style Sheet once and use it for all rules. if (!resetRule) { resetSheet = rule.options.jss.createStyleSheet(null, resetSheetOptions); resetRule = resetSheet.addRule('reset', getStyle(options.reset)); resetSheet.attach(); } // Add reset rule class name to the classes map of users Style Sheet. var selector = rule.selector; if (selectors.indexOf(selector) === -1) { selectors.push(selector); setSelectorDone = setSelectorDebounced(); } } // We make sure selector is set, because `debaunceMaybe` will not execute // the fn if called within delay. function onProcessSheet() { if (!setSelectorDone && selectors.length) setSelector(); } return { onProcessRule: onProcessRule, onProcessSheet: onProcessSheet }; }