import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray"; import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; import hash from '@emotion/hash'; import * as React from 'react'; import { useContext } from 'react'; import StyleContext, { ATTR_TOKEN, CSS_IN_JS_INSTANCE } from "../StyleContext"; import { flattenToken, token2key } from "../util"; import useGlobalCache from "./useGlobalCache"; var EMPTY_OVERRIDE = {}; // Generate different prefix to make user selector break in production env. // This helps developer not to do style override directly on the hash id. var hashPrefix = process.env.NODE_ENV !== 'production' ? 'css-dev-only-do-not-override' : 'css'; var tokenKeys = new Map(); function recordCleanToken(tokenKey) { tokenKeys.set(tokenKey, (tokenKeys.get(tokenKey) || 0) + 1); } function removeStyleTags(key, instanceId) { if (typeof document !== 'undefined') { var styles = document.querySelectorAll("style[".concat(ATTR_TOKEN, "=\"").concat(key, "\"]")); styles.forEach(function (style) { if (style[CSS_IN_JS_INSTANCE] === instanceId) { var _style$parentNode; (_style$parentNode = style.parentNode) === null || _style$parentNode === void 0 ? void 0 : _style$parentNode.removeChild(style); } }); } } var TOKEN_THRESHOLD = 0; // Remove will check current keys first function cleanTokenStyle(tokenKey, instanceId) { tokenKeys.set(tokenKey, (tokenKeys.get(tokenKey) || 0) - 1); var tokenKeyList = Array.from(tokenKeys.keys()); var cleanableKeyList = tokenKeyList.filter(function (key) { var count = tokenKeys.get(key) || 0; return count <= 0; }); // Should keep tokens under threshold for not to insert style too often if (tokenKeyList.length - cleanableKeyList.length > TOKEN_THRESHOLD) { cleanableKeyList.forEach(function (key) { removeStyleTags(key, instanceId); tokenKeys.delete(key); }); } } export var getComputedToken = function getComputedToken(originToken, overrideToken, theme, format) { var derivativeToken = theme.getDerivativeToken(originToken); // Merge with override var mergedDerivativeToken = _objectSpread(_objectSpread({}, derivativeToken), overrideToken); // Format if needed if (format) { mergedDerivativeToken = format(mergedDerivativeToken); } return mergedDerivativeToken; }; /** * Cache theme derivative token as global shared one * @param theme Theme entity * @param tokens List of tokens, used for cache. Please do not dynamic generate object directly * @param option Additional config * @returns Call Theme.getDerivativeToken(tokenObject) to get token */ export default function useCacheToken(theme, tokens) { var option = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var _useContext = useContext(StyleContext), instanceId = _useContext.cache.instanceId; var _option$salt = option.salt, salt = _option$salt === void 0 ? '' : _option$salt, _option$override = option.override, override = _option$override === void 0 ? EMPTY_OVERRIDE : _option$override, formatToken = option.formatToken, compute = option.getComputedToken; // Basic - We do basic cache here var mergedToken = React.useMemo(function () { return Object.assign.apply(Object, [{}].concat(_toConsumableArray(tokens))); }, [tokens]); var tokenStr = React.useMemo(function () { return flattenToken(mergedToken); }, [mergedToken]); var overrideTokenStr = React.useMemo(function () { return flattenToken(override); }, [override]); var cachedToken = useGlobalCache('token', [salt, theme.id, tokenStr, overrideTokenStr], function () { var mergedDerivativeToken = compute ? compute(mergedToken, override, theme) : getComputedToken(mergedToken, override, theme, formatToken); // Optimize for `useStyleRegister` performance var tokenKey = token2key(mergedDerivativeToken, salt); mergedDerivativeToken._tokenKey = tokenKey; recordCleanToken(tokenKey); var hashId = "".concat(hashPrefix, "-").concat(hash(tokenKey)); mergedDerivativeToken._hashId = hashId; // Not used return [mergedDerivativeToken, hashId]; }, function (cache) { // Remove token will remove all related style cleanTokenStyle(cache[0]._tokenKey, instanceId); }); return cachedToken; }