"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = useCacheToken; exports.getComputedToken = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2")); var _hash = _interopRequireDefault(require("@emotion/hash")); var React = _interopRequireWildcard(require("react")); var _StyleContext = _interopRequireWildcard(require("../StyleContext")); var _util = require("../util"); var _useGlobalCache = _interopRequireDefault(require("./useGlobalCache")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 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(_StyleContext.ATTR_TOKEN, "=\"").concat(key, "\"]")); styles.forEach(function (style) { if (style[_StyleContext.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); }); } } var getComputedToken = function getComputedToken(originToken, overrideToken, theme, format) { var derivativeToken = theme.getDerivativeToken(originToken); // Merge with override var mergedDerivativeToken = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, 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 */ exports.getComputedToken = getComputedToken; function useCacheToken(theme, tokens) { var option = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var _useContext = (0, React.useContext)(_StyleContext.default), 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((0, _toConsumableArray2.default)(tokens))); }, [tokens]); var tokenStr = React.useMemo(function () { return (0, _util.flattenToken)(mergedToken); }, [mergedToken]); var overrideTokenStr = React.useMemo(function () { return (0, _util.flattenToken)(override); }, [override]); var cachedToken = (0, _useGlobalCache.default)('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 = (0, _util.token2key)(mergedDerivativeToken, salt); mergedDerivativeToken._tokenKey = tokenKey; recordCleanToken(tokenKey); var hashId = "".concat(hashPrefix, "-").concat((0, _hash.default)(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; }