UNPKG

jss-plugin-isolate

Version:

True rules isolation through automatic properties reset.

146 lines (110 loc) 4.13 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _extends = require('@babel/runtime/helpers/extends'); var inheritedInitials = require('css-initials/inherited'); var allInitials = require('css-initials/all'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var _extends__default = /*#__PURE__*/_interopDefaultLegacy(_extends); var inheritedInitials__default = /*#__PURE__*/_interopDefaultLegacy(inheritedInitials); var allInitials__default = /*#__PURE__*/_interopDefaultLegacy(allInitials); var resetSheetOptions = { meta: 'jss-plugin-isolate', // Lets make it always the first one in sheets for testing // and specificity. index: -Infinity, link: true }; var initialsMap = { inherited: inheritedInitials__default['default'], all: allInitials__default['default'] }; var getStyle = function getStyle(option) { if (option === void 0) { option = 'inherited'; } // Option is either "inherited" or "all". if (typeof option === 'string') return initialsMap[option]; if (typeof option === 'object') { // Option is ["all/inherited", {...style}] if (Array.isArray(option)) { var type = option[0]; var style = option[1]; return _extends__default['default']({}, initialsMap[type], style); } // Option is a style object, use inherited initials by default. return _extends__default['default']({}, inheritedInitials__default['default'], option); } return inheritedInitials__default['default']; }; var shouldIsolate = function shouldIsolate(rule, sheet, options) { var parent = rule.options.parent; if (parent && (parent.type === 'keyframes' || parent.type === 'conditional')) { 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, delay) { if (delay === void 0) { delay = 3; } var time = Date.now(); return function () { var now = Date.now(); if (now - time < delay) return false; time = now; fn(); return true; }; }; function jssIsolate(options) { if (options === void 0) { options = {}; } var setSelectorDone = false; var selectors = []; var resetSheet; var resetRule; 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; // Type it as a StyleRule var styleRule = rule; if (!shouldIsolate(styleRule, sheet, options)) return; // Create a reset Style Sheet once and use it for all rules. if (!resetRule) { resetSheet = rule.options.jss.createStyleSheet({}, 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 = styleRule.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 }; } exports.default = jssIsolate;