UNPKG

jss-plugin-isolate

Version:

True rules isolation through automatic properties reset.

136 lines (104 loc) 3.57 kB
import _extends from '@babel/runtime/helpers/esm/extends'; import inheritedInitials from 'css-initials/inherited'; import allInitials from 'css-initials/all'; 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, all: allInitials }; 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({}, initialsMap[type], style); } // Option is a style object, use inherited initials by default. return _extends({}, inheritedInitials, option); } return inheritedInitials; }; 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 }; } export default jssIsolate;