157 lines
7.5 KiB
JavaScript
157 lines
7.5 KiB
JavaScript
|
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<any, any> = 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
|