define(["require", "exports", "@fluentui/merge-styles", "./rtl", "./dom"], function (require, exports, merge_styles_1, rtl_1, dom_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.classNamesFunction = void 0; var MAX_CACHE_COUNT = 50; var DEFAULT_SPECIFICITY_MULTIPLIER = 5; var _memoizedClassNames = 0; var stylesheet = merge_styles_1.Stylesheet.getInstance(); if (stylesheet && stylesheet.onReset) { stylesheet.onReset(function () { return _memoizedClassNames++; }); } // Note that because of the caching nature within the classNames memoization, // I've disabled this rule to simply be able to work with any types. /* eslint-disable @typescript-eslint/no-explicit-any */ // This represents a prop we attach to each Map to indicate the cached return value // associated with the graph node. var retVal = '__retval__'; /** * Creates a getClassNames function which calls getStyles given the props, and injects them * into mergeStyleSets. * * Note that the props you pass in on every render should be in the same order and * immutable (numbers, strings, and booleans). This will allow the results to be memoized. Violating * these will cause extra recalcs to occur. */ function classNamesFunction(options) { // We build a trie where each node is a Map. The map entry key represents an argument // value, and the entry value is another node (Map). Each node has a `__retval__` // property which is used to hold the cached response. if (options === void 0) { options = {}; } // To derive the response, we can simply ensure the arguments are added or already // exist in the trie. At the last node, if there is a `__retval__` we return that. Otherwise // we call the `getStyles` api to evaluate, cache on the property, and return that. // let map: IRecursiveMemoNode = new Map(); var windowMap = new Map(); var styleCalcCount = 0; var getClassNamesCount = 0; var currentMemoizedClassNames = _memoizedClassNames; var getClassNames = function (styleFunctionOrObject, styleProps) { var _a; if (styleProps === void 0) { styleProps = {}; } // If useStaticStyles is true, styleFunctionOrObject returns slot to classname mappings. // If there is also no style overrides, we can skip merge styles completely and // simply return the result from the style funcion. if (options.useStaticStyles && typeof styleFunctionOrObject === 'function' && styleFunctionOrObject.__noStyleOverride__) { return styleFunctionOrObject(styleProps); } getClassNamesCount++; var shadowConfig = styleFunctionOrObject ? styleFunctionOrObject.__shadowConfig__ : undefined; var key = shadowConfig && shadowConfig.window ? shadowConfig.window : '__default__'; if (!windowMap.has(key)) { windowMap.set(key, new Map()); } var current = windowMap.get(key); // let current: Map = map; var theme = styleProps.theme; var rtl = theme && theme.rtl !== undefined ? theme.rtl : (0, rtl_1.getRTL)(); var disableCaching = options.disableCaching; // On reset of our stylesheet, reset memoized cache. if (currentMemoizedClassNames !== _memoizedClassNames) { currentMemoizedClassNames = _memoizedClassNames; // map = new Map(); windowMap.set(key, new Map()); current = windowMap.get(key); styleCalcCount = 0; } if (!options.disableCaching) { current = _traverseMap(windowMap.get(key), styleFunctionOrObject); current = _traverseMap(current, styleProps); } if (disableCaching || !current[retVal]) { if (styleFunctionOrObject === undefined) { current[retVal] = {}; } else { current[retVal] = (0, merge_styles_1.mergeCssSets)([ (typeof styleFunctionOrObject === 'function' ? styleFunctionOrObject(styleProps) : styleFunctionOrObject), ], { shadowConfig: styleFunctionOrObject.__shadowConfig__, rtl: !!rtl, specificityMultiplier: options.useStaticStyles ? DEFAULT_SPECIFICITY_MULTIPLIER : undefined, }); } if (!disableCaching) { styleCalcCount++; } } if (styleCalcCount > (options.cacheSize || MAX_CACHE_COUNT)) { var win = (0, dom_1.getWindow)(); if ((_a = win === null || win === void 0 ? void 0 : win.FabricConfig) === null || _a === void 0 ? void 0 : _a.enableClassNameCacheFullWarning) { // eslint-disable-next-line no-console console.warn("Styles are being recalculated too frequently. Cache miss rate is ".concat(styleCalcCount, "/").concat(getClassNamesCount, ".")); // eslint-disable-next-line no-console console.trace(); } windowMap.get(key).clear(); styleCalcCount = 0; // Mutate the options passed in, that's all we can do. options.disableCaching = true; } // Note: the retVal is an attached property on the Map; not a key in the Map. We use this attached property to // cache the return value for this branch of the graph. return current[retVal]; }; return getClassNames; } exports.classNamesFunction = classNamesFunction; function _traverseEdge(current, value) { value = _normalizeValue(value); if (!current.has(value)) { current.set(value, new Map()); } return current.get(value); } function _traverseMap(current, inputs) { if (typeof inputs === 'function') { var cachedInputsFromStyled = inputs.__cachedInputs__; if (cachedInputsFromStyled) { // The styled helper will generate the styles function and will attach the cached // inputs (consisting of the default styles, customzied styles, and user provided styles.) // These should be used as cache keys for deriving the memoized value. for (var _i = 0, _a = inputs.__cachedInputs__; _i < _a.length; _i++) { var input = _a[_i]; current = _traverseEdge(current, input); } } else { current = _traverseEdge(current, inputs); } } else if (typeof inputs === 'object') { for (var propName in inputs) { if (inputs.hasOwnProperty(propName)) { current = _traverseEdge(current, inputs[propName]); } } } return current; } function _normalizeValue(value) { switch (value) { case undefined: return '__undefined__'; case null: return '__null__'; default: return value; } } }); //# sourceMappingURL=classNamesFunction.js.map