This commit is contained in:
2026-05-25 17:07:28 +08:00
parent 30cba5ee96
commit df501f6151
10000 changed files with 276005 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
export type KeyType = string | number;
type ValueType = [number, any];
/** Connect key with `SPLIT` */
export declare function pathKey(keys: KeyType[]): string;
declare class Entity {
instanceId: string;
constructor(instanceId: string);
/** @private Internal cache map. Do not access this directly */
cache: Map<string, ValueType>;
/** @private Record update times for each key */
updateTimes: Map<string, number>;
extracted: Set<string>;
get(keys: KeyType[]): ValueType | null;
/** A fast get cache with `get` concat. */
opGet(keyPathStr: string): ValueType | null;
update(keys: KeyType[], valueFn: (origin: ValueType | null) => ValueType | null): void;
/** A fast get cache with `get` concat. */
opUpdate(keyPathStr: string, valueFn: (origin: ValueType | null) => ValueType | null): void;
}
export default Entity;
+57
View File
@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.pathKey = pathKey;
// [times, realValue]
const SPLIT = '%';
/** Connect key with `SPLIT` */
function pathKey(keys) {
return keys.join(SPLIT);
}
/** Record update id for extract static style order. */
let updateId = 0;
class Entity {
instanceId;
constructor(instanceId) {
this.instanceId = instanceId;
}
/** @private Internal cache map. Do not access this directly */
cache = new Map();
/** @private Record update times for each key */
updateTimes = new Map();
extracted = new Set();
get(keys) {
return this.opGet(pathKey(keys));
}
/** A fast get cache with `get` concat. */
opGet(keyPathStr) {
return this.cache.get(keyPathStr) || null;
}
update(keys, valueFn) {
return this.opUpdate(pathKey(keys), valueFn);
}
/** A fast get cache with `get` concat. */
opUpdate(keyPathStr, valueFn) {
const prevValue = this.cache.get(keyPathStr);
const nextValue = valueFn(prevValue);
if (nextValue === null) {
this.cache.delete(keyPathStr);
this.updateTimes.delete(keyPathStr);
} else {
this.cache.set(keyPathStr, nextValue);
this.updateTimes.set(keyPathStr, updateId);
updateId += 1;
}
}
}
var _default = exports.default = Entity;
+9
View File
@@ -0,0 +1,9 @@
import type { CSSInterpolation } from './hooks/useStyleRegister';
declare class Keyframe {
private name;
style: CSSInterpolation;
constructor(name: string, style: CSSInterpolation);
getName(hashId?: string): string;
_keyframe: boolean;
}
export default Keyframe;
+19
View File
@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
class Keyframe {
name;
style;
constructor(name, style) {
this.name = name;
this.style = style;
}
getName(hashId = '') {
return hashId ? `${hashId}-${this.name}` : this.name;
}
_keyframe = true;
}
var _default = exports.default = Keyframe;
+45
View File
@@ -0,0 +1,45 @@
import * as React from 'react';
import CacheEntity from './Cache';
import type { Linter } from './linters/interface';
import type { Transformer } from './transformers/interface';
export declare const ATTR_TOKEN = "data-token-hash";
export declare const ATTR_MARK = "data-css-hash";
export declare const ATTR_CACHE_PATH = "data-cache-path";
export declare const CSS_IN_JS_INSTANCE = "__cssinjs_instance__";
export declare function createCache(): CacheEntity;
export type HashPriority = 'low' | 'high';
export interface StyleContextProps {
/** @private Test only. Not work in production. */
mock?: 'server' | 'client';
/**
* Only set when you need ssr to extract style on you own.
* If not provided, it will auto create <style /> on the end of Provider in server side.
*/
cache: CacheEntity;
/** Tell children that this context is default generated context */
defaultCache: boolean;
/** Use `:where` selector to reduce hashId css selector priority */
hashPriority?: HashPriority;
/** Tell cssinjs where to inject style in */
container?: Element | ShadowRoot;
/** Component wil render inline `<style />` for fallback in SSR. Not recommend. */
ssrInline?: boolean;
/** Transform css before inject in document. Please note that `transformers` do not support dynamic update */
transformers?: Transformer[];
/**
* Linters to lint css before inject in document.
* Styles will be linted after transforming.
* Please note that `linters` do not support dynamic update.
*/
linters?: Linter[];
/** Wrap css in a layer to avoid global style conflict */
layer?: boolean;
/** Hardcode here since transformer not support take effect on serialize currently */
autoPrefix?: boolean;
}
declare const StyleContext: React.Context<StyleContextProps>;
export type StyleProviderProps = Partial<Omit<StyleContextProps, 'autoPrefix'>> & {
children?: React.ReactNode;
};
export declare const StyleProvider: React.FC<StyleProviderProps>;
export default StyleContext;
+97
View File
@@ -0,0 +1,97 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.StyleProvider = exports.CSS_IN_JS_INSTANCE = exports.ATTR_TOKEN = exports.ATTR_MARK = exports.ATTR_CACHE_PATH = void 0;
exports.createCache = createCache;
exports.default = void 0;
var _useMemo = _interopRequireDefault(require("@rc-component/util/lib/hooks/useMemo"));
var _isEqual = _interopRequireDefault(require("@rc-component/util/lib/isEqual"));
var React = _interopRequireWildcard(require("react"));
var _Cache = _interopRequireDefault(require("./Cache"));
var _autoPrefix = require("./transformers/autoPrefix");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const ATTR_TOKEN = exports.ATTR_TOKEN = 'data-token-hash';
const ATTR_MARK = exports.ATTR_MARK = 'data-css-hash';
const ATTR_CACHE_PATH = exports.ATTR_CACHE_PATH = 'data-cache-path';
// Mark css-in-js instance in style element
const CSS_IN_JS_INSTANCE = exports.CSS_IN_JS_INSTANCE = '__cssinjs_instance__';
function createCache() {
const cssinjsInstanceId = Math.random().toString(12).slice(2);
// Tricky SSR: Move all inline style to the head.
// PS: We do not recommend tricky mode.
if (typeof document !== 'undefined' && document.head && document.body) {
const styles = document.body.querySelectorAll(`style[${ATTR_MARK}]`) || [];
const {
firstChild
} = document.head;
Array.from(styles).forEach(style => {
style[CSS_IN_JS_INSTANCE] ||= cssinjsInstanceId;
// Not force move if no head
if (style[CSS_IN_JS_INSTANCE] === cssinjsInstanceId) {
document.head.insertBefore(style, firstChild);
}
});
// Deduplicate of moved styles
const styleHash = {};
Array.from(document.querySelectorAll(`style[${ATTR_MARK}]`)).forEach(style => {
const hash = style.getAttribute(ATTR_MARK);
if (styleHash[hash]) {
if (style[CSS_IN_JS_INSTANCE] === cssinjsInstanceId) {
style.parentNode?.removeChild(style);
}
} else {
styleHash[hash] = true;
}
});
}
return new _Cache.default(cssinjsInstanceId);
}
const StyleContext = /*#__PURE__*/React.createContext({
hashPriority: 'low',
cache: createCache(),
defaultCache: true,
autoPrefix: false
});
const StyleProvider = props => {
const {
children,
...restProps
} = props;
const parentContext = React.useContext(StyleContext);
const context = (0, _useMemo.default)(() => {
const mergedContext = {
...parentContext
};
Object.keys(restProps).forEach(key => {
const value = restProps[key];
if (restProps[key] !== undefined) {
mergedContext[key] = value;
}
});
const {
cache,
transformers = []
} = restProps;
mergedContext.cache = mergedContext.cache || createCache();
mergedContext.defaultCache = !cache && parentContext.defaultCache;
// autoPrefix
if (transformers.includes(_autoPrefix.AUTO_PREFIX)) {
mergedContext.autoPrefix = true;
}
return mergedContext;
}, [parentContext, restProps], (prev, next) => !(0, _isEqual.default)(prev[0], next[0], true) || !(0, _isEqual.default)(prev[1], next[1], true));
return /*#__PURE__*/React.createElement(StyleContext.Provider, {
value: context
}, children);
};
exports.StyleProvider = StyleProvider;
var _default = exports.default = StyleContext;
+13
View File
@@ -0,0 +1,13 @@
import type Cache from './Cache';
declare const ExtractStyleFns: {
style: import("./hooks/useGlobalCache").ExtractStyle<[styleStr: string, styleId: string, effectStyle: Record<string, string>, clientOnly: boolean | undefined, order: number]>;
token: import("./hooks/useGlobalCache").ExtractStyle<[token: any, hashId: string, realToken: any, cssVarStr: string, cssVarKey: string]>;
cssVar: import("./hooks/useGlobalCache").ExtractStyle<[cssVarToken: import("./util/css-variables").TokenWithCSSVar<any, Record<string, any>>, cssVarStr: string, styleId: string, cssVarKey: string]>;
};
type ExtractStyleType = keyof typeof ExtractStyleFns;
export default function extractStyle(cache: Cache, options?: boolean | {
plain?: boolean;
types?: ExtractStyleType | ExtractStyleType[];
once?: boolean;
}): string;
export {};
+75
View File
@@ -0,0 +1,75 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = extractStyle;
var _useCacheToken = require("./hooks/useCacheToken");
var _useCSSVarRegister = require("./hooks/useCSSVarRegister");
var _useStyleRegister = require("./hooks/useStyleRegister");
var _util = require("./util");
var _cacheMapUtil = require("./util/cacheMapUtil");
const ExtractStyleFns = {
[_useStyleRegister.STYLE_PREFIX]: _useStyleRegister.extract,
[_useCacheToken.TOKEN_PREFIX]: _useCacheToken.extract,
[_useCSSVarRegister.CSS_VAR_PREFIX]: _useCSSVarRegister.extract
};
function isNotNull(value) {
return value !== null;
}
function extractStyle(cache, options) {
const {
plain = false,
types = ['style', 'token', 'cssVar'],
once = false
} = typeof options === 'boolean' ? {
plain: options
} : options || {};
const matchPrefixRegexp = new RegExp(`^(${(typeof types === 'string' ? [types] : types).join('|')})%`);
// prefix with `style` is used for `useStyleRegister` to cache style context
const styleKeys = Array.from(cache.cache.keys()).filter(key => matchPrefixRegexp.test(key));
// Common effect styles like animation
const effectStyles = {};
// Mapping of cachePath to style hash
const cachePathMap = {};
let styleText = '';
styleKeys.map(key => {
if (once && cache.extracted.has(key)) {
return null; // Skip if already extracted
}
const cachePath = key.replace(matchPrefixRegexp, '').replace(/%/g, '|');
const [prefix] = key.split('%');
const extractFn = ExtractStyleFns[prefix];
const extractedStyle = extractFn(cache.cache.get(key)[1], effectStyles, {
plain
});
if (!extractedStyle) {
return null;
}
const updateTime = cache.updateTimes.get(key) || 0;
const [order, styleId, styleStr] = extractedStyle;
if (key.startsWith('style')) {
cachePathMap[cachePath] = styleId;
}
// record that this style has been extracted
cache.extracted.add(key);
return [order, styleStr, updateTime];
}).filter(isNotNull).sort(([o1,, u1], [o2,, u2]) => {
if (o1 !== o2) {
return o1 - o2;
}
return u1 - u2;
}).forEach(([, style]) => {
styleText += style;
});
// ==================== Fill Cache Path ====================
styleText += (0, _util.toStyleStr)(`.${_cacheMapUtil.ATTR_CACHE_MAP}{content:"${(0, _cacheMapUtil.serialize)(cachePathMap)}";}`, undefined, undefined, {
[_cacheMapUtil.ATTR_CACHE_MAP]: _cacheMapUtil.ATTR_CACHE_MAP
}, plain);
return styleText;
}
@@ -0,0 +1,22 @@
import type { TokenWithCSSVar } from '../util/css-variables';
import type { ExtractStyle } from './useGlobalCache';
export declare const CSS_VAR_PREFIX = "cssVar";
type CSSVarCacheValue<V, T extends Record<string, V> = Record<string, V>> = [
cssVarToken: TokenWithCSSVar<V, T>,
cssVarStr: string,
styleId: string,
cssVarKey: string
];
declare const useCSSVarRegister: <V, T extends Record<string, V>>(config: {
path: string[];
key: string;
prefix?: string;
unitless?: Record<string, boolean>;
ignore?: Record<string, boolean>;
scope?: string | string[];
token: any;
hashId?: string;
nonce?: string | (() => string);
}, fn: () => T) => CSSVarCacheValue<V, T>;
export declare const extract: ExtractStyle<CSSVarCacheValue<any>>;
export default useCSSVarRegister;
@@ -0,0 +1,99 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.extract = exports.default = exports.CSS_VAR_PREFIX = void 0;
var _dynamicCSS = require("@rc-component/util/lib/Dom/dynamicCSS");
var _react = require("react");
var _StyleContext = _interopRequireWildcard(require("../StyleContext"));
var _util = require("../util");
var _cssVariables = require("../util/css-variables");
var _useGlobalCache = _interopRequireDefault(require("./useGlobalCache"));
var _useStyleRegister = require("./useStyleRegister");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const CSS_VAR_PREFIX = exports.CSS_VAR_PREFIX = 'cssVar';
const useCSSVarRegister = (config, fn) => {
const {
key,
prefix,
unitless,
ignore,
token,
hashId,
scope,
nonce
} = config;
const {
cache: {
instanceId
},
container,
hashPriority
} = (0, _react.useContext)(_StyleContext.default);
const {
_tokenKey: tokenKey
} = token;
const scopeKey = Array.isArray(scope) ? scope.join('@@') : scope;
const stylePath = [...config.path, key, scopeKey, tokenKey];
const cache = (0, _useGlobalCache.default)(CSS_VAR_PREFIX, stylePath, () => {
const originToken = fn();
const [mergedToken, cssVarsStr] = (0, _cssVariables.transformToken)(originToken, key, {
prefix,
unitless,
ignore,
scope,
hashPriority,
hashCls: hashId
});
const styleId = (0, _useStyleRegister.uniqueHash)(stylePath, cssVarsStr);
return [mergedToken, cssVarsStr, styleId, key];
}, ([,, styleId]) => {
if (_util.isClientSide) {
(0, _dynamicCSS.removeCSS)(styleId, {
mark: _StyleContext.ATTR_MARK,
attachTo: container
});
}
}, ([, cssVarsStr, styleId]) => {
if (!cssVarsStr) {
return;
}
let mergedCSSConfig = {
mark: _StyleContext.ATTR_MARK,
prepend: 'queue',
attachTo: container,
priority: -999
};
mergedCSSConfig = (0, _util.injectCSPNonce)(mergedCSSConfig, nonce);
const style = (0, _dynamicCSS.updateCSS)(cssVarsStr, styleId, mergedCSSConfig);
style[_StyleContext.CSS_IN_JS_INSTANCE] = instanceId;
// Used for `useCacheToken` to remove on batch when token removed
style.setAttribute(_StyleContext.ATTR_TOKEN, key);
});
return cache;
};
const extract = (cache, effectStyles, options) => {
const [, styleStr, styleId, cssVarKey] = cache;
const {
plain
} = options || {};
if (!styleStr) {
return null;
}
const order = -999;
// ====================== Style ======================
// Used for @rc-component/util
const sharedAttrs = {
'data-rc-order': 'prependQueue',
'data-rc-priority': `${order}`
};
const styleText = (0, _util.toStyleStr)(styleStr, cssVarKey, styleId, sharedAttrs, plain);
return [order, styleId, styleText];
};
exports.extract = extract;
var _default = exports.default = useCSSVarRegister;
@@ -0,0 +1,69 @@
import type Theme from '../theme/Theme';
import type { ExtractStyle } from './useGlobalCache';
export interface Option<DerivativeToken, DesignToken> {
/**
* Generate token with salt.
* This is used to generate different hashId even same derivative token for different version.
*/
salt?: string;
override?: object;
/**
* Format token as you need. Such as:
*
* - rename token
* - merge token
* - delete token
*
* This should always be the same since it's one time process.
* It's ok to useMemo outside but this has better cache strategy.
*/
formatToken?: (mergedToken: any) => DerivativeToken;
/**
* Get final token with origin token, override token and theme.
* The parameters do not contain formatToken since it's passed by user.
* @param origin The original token.
* @param override Extra tokens to override.
* @param theme Theme instance. Could get derivative token by `theme.getDerivativeToken`
*/
getComputedToken?: (origin: DesignToken, override: object, theme: Theme<any, any>) => DerivativeToken;
/**
* Transform token to css variables.
*/
cssVar: {
hashed?: boolean;
/** Prefix for css variables */
prefix?: string;
/** Tokens that should not be appended with unit */
unitless?: Record<string, boolean>;
/** Tokens that should not be transformed to css variables */
ignore?: Record<string, boolean>;
/** Tokens that preserves origin value */
preserve?: Record<string, boolean>;
/** Key for current theme. Useful for customizing and should be unique */
key: string;
};
/**
* CSP nonce for style element.
* Can be a string or a function that returns a string.
*/
nonce?: string | (() => string);
}
export declare const getComputedToken: <DerivativeToken = object, DesignToken = DerivativeToken>(originToken: DesignToken, overrideToken: object, theme: Theme<any, any>, format?: ((token: DesignToken) => DerivativeToken) | undefined) => any;
export declare const TOKEN_PREFIX = "token";
type TokenCacheValue<DerivativeToken> = [
token: DerivativeToken,
hashId: string,
realToken: DerivativeToken,
cssVarStr: string,
cssVarKey: string
];
/**
* 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<DerivativeToken = object, DesignToken = DerivativeToken>(theme: Theme<any, any>, tokens: Partial<DesignToken>[], option: Option<DerivativeToken, DesignToken>): TokenCacheValue<DerivativeToken>;
export declare const extract: ExtractStyle<TokenCacheValue<any>>;
export {};
@@ -0,0 +1,168 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TOKEN_PREFIX = void 0;
exports.default = useCacheToken;
exports.getComputedToken = exports.extract = void 0;
var _hash = _interopRequireDefault(require("@emotion/hash"));
var _dynamicCSS = require("@rc-component/util/lib/Dom/dynamicCSS");
var _react = require("react");
var _StyleContext = _interopRequireWildcard(require("../StyleContext"));
var _util = require("../util");
var _cssVariables = require("../util/css-variables");
var _useGlobalCache = _interopRequireDefault(require("./useGlobalCache"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const 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.
const hashPrefix = process.env.NODE_ENV !== 'production' ? 'css-dev-only-do-not-override' : 'css';
const tokenKeys = new Map();
function recordCleanToken(tokenKey) {
tokenKeys.set(tokenKey, (tokenKeys.get(tokenKey) || 0) + 1);
}
function removeStyleTags(key, instanceId) {
if (typeof document !== 'undefined') {
const styles = document.querySelectorAll(`style[${_StyleContext.ATTR_TOKEN}="${key}"]`);
styles.forEach(style => {
if (style[_StyleContext.CSS_IN_JS_INSTANCE] === instanceId) {
style.parentNode?.removeChild(style);
}
});
}
}
const TOKEN_THRESHOLD = -1;
// Remove will check current keys first
function cleanTokenStyle(tokenKey, instanceId) {
tokenKeys.set(tokenKey, (tokenKeys.get(tokenKey) || 0) - 1);
const cleanableKeyList = new Set();
tokenKeys.forEach((value, key) => {
if (value <= 0) cleanableKeyList.add(key);
});
// Should keep tokens under threshold for not to insert style too often
if (tokenKeys.size - cleanableKeyList.size > TOKEN_THRESHOLD) {
cleanableKeyList.forEach(key => {
removeStyleTags(key, instanceId);
tokenKeys.delete(key);
});
}
}
const getComputedToken = (originToken, overrideToken, theme, format) => {
const derivativeToken = theme.getDerivativeToken(originToken);
// Merge with override
let mergedDerivativeToken = {
...derivativeToken,
...overrideToken
};
// Format if needed
if (format) {
mergedDerivativeToken = format(mergedDerivativeToken);
}
return mergedDerivativeToken;
};
exports.getComputedToken = getComputedToken;
const TOKEN_PREFIX = exports.TOKEN_PREFIX = 'token';
/**
* 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
*/
function useCacheToken(theme, tokens, option) {
const {
cache: {
instanceId
},
container,
hashPriority
} = (0, _react.useContext)(_StyleContext.default);
const {
salt = '',
override = EMPTY_OVERRIDE,
formatToken,
getComputedToken: compute,
cssVar,
nonce
} = option;
// Basic - We do basic cache here
const mergedToken = (0, _util.memoResult)(() => Object.assign({}, ...tokens), tokens);
const tokenStr = (0, _util.flattenToken)(mergedToken);
const overrideTokenStr = (0, _util.flattenToken)(override);
const cssVarStr = (0, _util.flattenToken)(cssVar);
const cachedToken = (0, _useGlobalCache.default)(TOKEN_PREFIX, [salt, theme.id, tokenStr, overrideTokenStr, cssVarStr], () => {
const mergedDerivativeToken = compute ? compute(mergedToken, override, theme) : getComputedToken(mergedToken, override, theme, formatToken);
const actualToken = {
...mergedDerivativeToken
};
// Optimize for `useStyleRegister` performance
const mergedSalt = `${salt}_${cssVar.prefix}`;
const hashId = (0, _hash.default)(mergedSalt);
const hashCls = `${hashPrefix}-${hashId}`;
actualToken._tokenKey = (0, _util.token2key)(actualToken, mergedSalt);
// Replace token value with css variables
const [tokenWithCssVar, cssVarsStr] = (0, _cssVariables.transformToken)(mergedDerivativeToken, cssVar.key, {
prefix: cssVar.prefix,
ignore: cssVar.ignore,
unitless: cssVar.unitless,
preserve: cssVar.preserve,
hashPriority,
hashCls: cssVar.hashed ? hashCls : undefined
});
tokenWithCssVar._hashId = hashId;
recordCleanToken(cssVar.key);
return [tokenWithCssVar, hashCls, actualToken, cssVarsStr, cssVar.key];
}, ([,,,, themeKey]) => {
// Remove token will remove all related style
cleanTokenStyle(themeKey, instanceId);
}, ([,,, cssVarsStr, themeKey]) => {
if (!cssVarsStr) {
return;
}
let mergedCSSConfig = {
mark: _StyleContext.ATTR_MARK,
prepend: 'queue',
attachTo: container,
priority: -999
};
mergedCSSConfig = (0, _util.injectCSPNonce)(mergedCSSConfig, nonce);
const style = (0, _dynamicCSS.updateCSS)(cssVarsStr, (0, _hash.default)(`css-var-${themeKey}`), mergedCSSConfig);
style[_StyleContext.CSS_IN_JS_INSTANCE] = instanceId;
// Used for `useCacheToken` to remove on batch when token removed
style.setAttribute(_StyleContext.ATTR_TOKEN, themeKey);
});
return cachedToken;
}
const extract = (cache, effectStyles, options) => {
const [,, realToken, styleStr, cssVarKey] = cache;
const {
plain
} = options || {};
if (!styleStr) {
return null;
}
const styleId = realToken._tokenKey;
const order = -999;
// ====================== Style ======================
// Used for @rc-component/util
const sharedAttrs = {
'data-rc-order': 'prependQueue',
'data-rc-priority': `${order}`
};
const styleText = (0, _util.toStyleStr)(styleStr, cssVarKey, styleId, sharedAttrs, plain);
return [order, styleId, styleText];
};
exports.extract = extract;
@@ -0,0 +1,3 @@
import type { DependencyList } from 'react';
declare const useEffectCleanupRegister: (deps?: DependencyList) => (fn: () => void) => void;
export default useEffectCleanupRegister;
@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _warning = require("@rc-component/util/lib/warning");
var _react = require("react");
// DO NOT register functions in useEffect cleanup function, or functions that registered will never be called.
const useEffectCleanupRegister = deps => {
const effectCleanups = [];
let cleanupFlag = false;
function register(fn) {
if (cleanupFlag) {
if (process.env.NODE_ENV !== 'production') {
(0, _warning.warning)(false, '[Ant Design CSS-in-JS] You are registering a cleanup function after unmount, which will not have any effect.');
}
return;
}
effectCleanups.push(fn);
}
(0, _react.useEffect)(() => {
// Compatible with strict mode
cleanupFlag = false;
return () => {
cleanupFlag = true;
if (effectCleanups.length) {
effectCleanups.forEach(fn => fn());
}
};
}, deps);
return register;
};
var _default = exports.default = useEffectCleanupRegister;
@@ -0,0 +1,6 @@
import { type KeyType } from '../Cache';
export type ExtractStyle<CacheValue> = (cache: CacheValue, effectStyles: Record<string, boolean>, options?: {
plain?: boolean;
autoPrefix?: boolean;
}) => [order: number, styleId: string, style: string] | null;
export default function useGlobalCache<CacheType>(prefix: string, keyPath: KeyType[], cacheFn: () => CacheType, onCacheRemove?: (cache: CacheType, fromHMR: boolean) => void, onCacheEffect?: (cachedValue: CacheType) => void): CacheType;
@@ -0,0 +1,86 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = useGlobalCache;
var _react = _interopRequireWildcard(require("react"));
var React = _react;
var _Cache = require("../Cache");
var _StyleContext = _interopRequireDefault(require("../StyleContext"));
var _useHMR = _interopRequireDefault(require("./useHMR"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const effectMap = new Map();
function useGlobalCache(prefix, keyPath, cacheFn, onCacheRemove,
// Add additional effect trigger by `useInsertionEffect`
onCacheEffect) {
const {
cache: globalCache
} = React.useContext(_StyleContext.default);
const fullPath = [prefix, ...keyPath];
const fullPathStr = (0, _Cache.pathKey)(fullPath);
const HMRUpdate = (0, _useHMR.default)();
const buildCache = updater => {
globalCache.opUpdate(fullPathStr, prevCache => {
const [times = 0, cache] = prevCache || [undefined, undefined];
// HMR should always ignore cache since developer may change it
let tmpCache = cache;
if (process.env.NODE_ENV !== 'production' && cache && HMRUpdate) {
onCacheRemove?.(tmpCache, HMRUpdate);
tmpCache = null;
}
const mergedCache = tmpCache || cacheFn();
const data = [times, mergedCache];
// Call updater if need additional logic
return updater ? updater(data) : data;
});
};
// Create cache
React.useMemo(() => {
buildCache();
}, /* eslint-disable react-hooks/exhaustive-deps */
[fullPathStr]
/* eslint-enable */);
let cacheEntity = globalCache.opGet(fullPathStr);
// HMR clean the cache but not trigger `useMemo` again
// Let's fallback of this
// ref https://github.com/ant-design/cssinjs/issues/127
if (process.env.NODE_ENV !== 'production' && !cacheEntity) {
buildCache();
cacheEntity = globalCache.opGet(fullPathStr);
}
const cacheContent = cacheEntity[1];
// Remove if no need anymore
(0, _react.useInsertionEffect)(() => {
buildCache(([times, cache]) => [times + 1, cache]);
if (!effectMap.has(fullPathStr)) {
onCacheEffect?.(cacheContent);
effectMap.set(fullPathStr, true);
// 微任务清理缓存,可以认为是单次 batch render 中只触发一次 effect
Promise.resolve().then(() => {
effectMap.delete(fullPathStr);
});
}
return () => {
globalCache.opUpdate(fullPathStr, prevCache => {
const [times = 0, cache] = prevCache || [];
const nextCount = times - 1;
if (nextCount === 0) {
onCacheRemove?.(cache, false);
effectMap.delete(fullPathStr);
return null;
}
return [times - 1, cache];
});
};
}, [fullPathStr]);
return cacheContent;
}
@@ -0,0 +1,3 @@
declare function useProdHMR(): boolean;
declare const _default: typeof useProdHMR;
export default _default;
+30
View File
@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
function useProdHMR() {
return false;
}
let webpackHMR = false;
function useDevHMR() {
return webpackHMR;
}
var _default = exports.default = process.env.NODE_ENV === 'production' ? useProdHMR : useDevHMR; // Webpack `module.hot.accept` do not support any deps update trigger
// We have to hack handler to force mark as HRM
if (process.env.NODE_ENV !== 'production' && typeof module !== 'undefined' && module && module.hot && typeof window !== 'undefined') {
// Use `globalThis` first, and `window` for older browsers
// const win = globalThis as any;
const win = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : null;
if (win && typeof win.webpackHotUpdate === 'function') {
const originWebpackHotUpdate = win.webpackHotUpdate;
win.webpackHotUpdate = (...args) => {
webpackHMR = true;
setTimeout(() => {
webpackHMR = false;
}, 0);
return originWebpackHotUpdate(...args);
};
}
}
@@ -0,0 +1,75 @@
import type * as CSS from 'csstype';
import type { Theme, Transformer } from '..';
import type Keyframes from '../Keyframes';
import type { Linter } from '../linters';
import type { HashPriority } from '../StyleContext';
import type { ExtractStyle } from './useGlobalCache';
declare const SKIP_CHECK = "_skip_check_";
declare const MULTI_VALUE = "_multi_value_";
export interface LayerConfig {
name: string;
dependencies?: string[];
}
export type CSSProperties = Omit<CSS.PropertiesFallback<number | string>, 'animationName'> & {
animationName?: CSS.PropertiesFallback<number | string>['animationName'] | Keyframes;
};
export type CSSPropertiesWithMultiValues = {
[K in keyof CSSProperties]: CSSProperties[K] | readonly Extract<CSSProperties[K], string>[] | {
[SKIP_CHECK]?: boolean;
[MULTI_VALUE]?: boolean;
value: CSSProperties[K] | CSSProperties[K][];
};
};
export type CSSPseudos = {
[K in CSS.Pseudos]?: CSSObject;
};
type ArrayCSSInterpolation = readonly CSSInterpolation[];
export type InterpolationPrimitive = null | undefined | boolean | number | string | CSSObject;
export type CSSInterpolation = InterpolationPrimitive | ArrayCSSInterpolation | Keyframes;
export type CSSOthersObject = Record<string, CSSInterpolation>;
export interface CSSObject extends CSSPropertiesWithMultiValues, CSSPseudos, CSSOthersObject {
}
export declare function normalizeStyle(styleStr: string, autoPrefix: boolean): string;
export interface ParseConfig {
hashId?: string;
hashPriority?: HashPriority;
layer?: LayerConfig;
path?: string;
transformers?: Transformer[];
linters?: Linter[];
}
export interface ParseInfo {
root?: boolean;
injectHash?: boolean;
parentSelectors: string[];
}
export declare const parseStyle: (interpolation: CSSInterpolation, config?: ParseConfig, { root, injectHash, parentSelectors }?: ParseInfo) => [parsedStr: string, effectStyle: Record<string, string>];
export declare function uniqueHash(path: (string | number)[], styleStr: string): string;
export declare const STYLE_PREFIX = "style";
type StyleCacheValue = [
styleStr: string,
styleId: string,
effectStyle: Record<string, string>,
clientOnly: boolean | undefined,
order: number
];
/**
* Register a style to the global style sheet.
*/
export default function useStyleRegister(info: {
theme: Theme<any, any>;
token: any;
path: string[];
hashId?: string;
layer?: LayerConfig;
nonce?: string | (() => string);
clientOnly?: boolean;
/**
* Tell cssinjs the insert order of style.
* It's useful when you need to insert style
* before other style to overwrite for the same selector priority.
*/
order?: number;
}, styleFn: () => CSSInterpolation): void;
export declare const extract: ExtractStyle<StyleCacheValue>;
export {};
@@ -0,0 +1,380 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.STYLE_PREFIX = void 0;
exports.default = useStyleRegister;
exports.extract = void 0;
exports.normalizeStyle = normalizeStyle;
exports.parseStyle = void 0;
exports.uniqueHash = uniqueHash;
var _hash = _interopRequireDefault(require("@emotion/hash"));
var _dynamicCSS = require("@rc-component/util/lib/Dom/dynamicCSS");
var React = _interopRequireWildcard(require("react"));
var _unitless = _interopRequireDefault(require("@emotion/unitless"));
var _stylis = require("stylis");
var _linters = require("../linters");
var _StyleContext = _interopRequireWildcard(require("../StyleContext"));
var _util = require("../util");
var _cacheMapUtil = require("../util/cacheMapUtil");
var _useGlobalCache = _interopRequireDefault(require("./useGlobalCache"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
// @ts-ignore
const SKIP_CHECK = '_skip_check_';
const MULTI_VALUE = '_multi_value_';
// ============================================================================
// == Parser ==
// ============================================================================
// Preprocessor style content to browser support one
function normalizeStyle(styleStr, autoPrefix) {
const serialized = autoPrefix ? (0, _stylis.serialize)((0, _stylis.compile)(styleStr), (0, _stylis.middleware)([_stylis.prefixer, _stylis.stringify])) : (0, _stylis.serialize)((0, _stylis.compile)(styleStr), _stylis.stringify);
return serialized.replace(/\{%%%\:[^;];}/g, ';');
}
function isCompoundCSSProperty(value) {
return typeof value === 'object' && value && (SKIP_CHECK in value || MULTI_VALUE in value);
}
// 注入 hash 值
function injectSelectorHash(key, hashId, hashPriority = 'high') {
if (!hashId) {
return key;
}
const hashSelector = (0, _util.where)({
hashCls: hashId,
hashPriority
});
// 注入 hashId
const keys = key.split(',').map(k => {
const fullPath = k.trim().split(/\s+/);
// 如果 Selector 第一个是 HTML Element,那我们就插到它的后面。反之,就插到最前面。
let firstPath = fullPath[0] || '';
const htmlElement = firstPath.match(/^\w+/)?.[0] || '';
firstPath = `${htmlElement}${hashSelector}${firstPath.slice(htmlElement.length)}`;
return [firstPath, ...fullPath.slice(1)].join(' ');
});
return keys.join(',');
}
// Parse CSSObject to style content
const parseStyle = (interpolation, config = {}, {
root,
injectHash,
parentSelectors
} = {
root: true,
parentSelectors: []
}) => {
const {
hashId,
layer,
path,
hashPriority,
transformers = [],
linters = []
} = config;
let styleStr = '';
let effectStyle = {};
function parseKeyframes(keyframes) {
const animationName = keyframes.getName(hashId);
if (!effectStyle[animationName]) {
const [parsedStr] = parseStyle(keyframes.style, config, {
root: false,
parentSelectors
});
effectStyle[animationName] = `@keyframes ${keyframes.getName(hashId)}${parsedStr}`;
}
}
function flattenList(list, fullList = []) {
list.forEach(item => {
if (Array.isArray(item)) {
flattenList(item, fullList);
} else if (item) {
fullList.push(item);
}
});
return fullList;
}
const flattenStyleList = flattenList(Array.isArray(interpolation) ? interpolation : [interpolation]);
flattenStyleList.forEach(originStyle => {
// Only root level can use raw string
const style = typeof originStyle === 'string' && !root ? {} : originStyle;
if (typeof style === 'string') {
styleStr += `${style}\n`;
} else if (style._keyframe) {
// Keyframe
parseKeyframes(style);
} else {
const mergedStyle = transformers.reduce((prev, trans) => trans?.visit?.(prev) || prev, style);
// Normal CSSObject
Object.keys(mergedStyle).forEach(key => {
const value = mergedStyle[key];
if (typeof value === 'object' && value && (key !== 'animationName' || !value._keyframe) && !isCompoundCSSProperty(value)) {
let subInjectHash = false;
// 当成嵌套对象来处理
let mergedKey = key.trim();
// Whether treat child as root. In most case it is false.
let nextRoot = false;
// 拆分多个选择器
if ((root || injectHash) && hashId) {
if (mergedKey.startsWith('@')) {
// 略过媒体查询,交给子节点继续插入 hashId
subInjectHash = true;
} else if (mergedKey === '&') {
// 抹掉 root selector 上的单个 &
mergedKey = injectSelectorHash('', hashId, hashPriority);
} else {
// 注入 hashId
mergedKey = injectSelectorHash(key, hashId, hashPriority);
}
} else if (root && !hashId && (mergedKey === '&' || mergedKey === '')) {
// In case of `{ '&': { a: { color: 'red' } } }` or `{ '': { a: { color: 'red' } } }` without hashId,
// we will get `&{a:{color:red;}}` or `{a:{color:red;}}` string for stylis to compile.
// But it does not conform to stylis syntax,
// and finally we will get `{color:red;}` as css, which is wrong.
// So we need to remove key in root, and treat child `{ a: { color: 'red' } }` as root.
mergedKey = '';
nextRoot = true;
}
const [parsedStr, childEffectStyle] = parseStyle(value, config, {
root: nextRoot,
injectHash: subInjectHash,
parentSelectors: [...parentSelectors, mergedKey]
});
effectStyle = {
...effectStyle,
...childEffectStyle
};
styleStr += `${mergedKey}${parsedStr}`;
} else {
function appendStyle(cssKey, cssValue) {
if (process.env.NODE_ENV !== 'production' && (typeof value !== 'object' || !value?.[SKIP_CHECK])) {
[_linters.contentQuotesLinter, _linters.hashedAnimationLinter, ...linters].forEach(linter => linter(cssKey, cssValue, {
path,
hashId,
parentSelectors
}));
}
// 如果是样式则直接插入
const styleName = cssKey.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
// Auto suffix with px
let formatValue = cssValue;
if (!_unitless.default[cssKey] && typeof formatValue === 'number' && formatValue !== 0) {
formatValue = `${formatValue}px`;
}
// handle animationName & Keyframe value
if (cssKey === 'animationName' && cssValue?._keyframe) {
parseKeyframes(cssValue);
formatValue = cssValue.getName(hashId);
}
styleStr += `${styleName}:${formatValue};`;
}
const actualValue = value?.value ?? value;
if (typeof value === 'object' && value?.[MULTI_VALUE] && Array.isArray(actualValue)) {
actualValue.forEach(item => {
appendStyle(key, item);
});
} else {
if ((0, _util.isNonNullable)(actualValue)) {
appendStyle(key, actualValue);
}
}
}
});
}
});
if (!root) {
styleStr = `{${styleStr}}`;
} else if (layer) {
// fixme: https://github.com/thysultan/stylis/pull/339
if (styleStr) {
styleStr = `@layer ${layer.name} {${styleStr}}`;
}
if (layer.dependencies) {
effectStyle[`@layer ${layer.name}`] = layer.dependencies.map(deps => `@layer ${deps}, ${layer.name};`).join('\n');
}
}
return [styleStr, effectStyle];
};
// ============================================================================
// == Register ==
// ============================================================================
exports.parseStyle = parseStyle;
function uniqueHash(path, styleStr) {
return (0, _hash.default)(`${path.join('%')}${styleStr}`);
}
const STYLE_PREFIX = exports.STYLE_PREFIX = 'style';
/**
* Register a style to the global style sheet.
*/
function useStyleRegister(info, styleFn) {
const {
path,
hashId,
layer,
nonce,
clientOnly,
order = 0
} = info;
const {
mock,
hashPriority,
container,
transformers,
linters,
cache,
layer: enableLayer,
autoPrefix
} = React.useContext(_StyleContext.default);
const fullPath = [hashId || ''];
if (enableLayer) {
fullPath.push('layer');
}
fullPath.push(...path);
// Check if need insert style
let isMergedClientSide = _util.isClientSide;
if (process.env.NODE_ENV !== 'production' && mock !== undefined) {
isMergedClientSide = mock === 'client';
}
(0, _useGlobalCache.default)(STYLE_PREFIX, fullPath,
// Create cache if needed
() => {
const cachePath = fullPath.join('|');
// Get style from SSR inline style directly
if ((0, _cacheMapUtil.existPath)(cachePath)) {
const [inlineCacheStyleStr, styleHash] = (0, _cacheMapUtil.getStyleAndHash)(cachePath);
if (inlineCacheStyleStr) {
return [inlineCacheStyleStr, styleHash, {}, clientOnly, order];
}
}
// Generate style
const styleObj = styleFn();
const [parsedStyle, effectStyle] = parseStyle(styleObj, {
hashId,
hashPriority,
layer: enableLayer ? layer : undefined,
path: path.join('-'),
transformers,
linters
});
const styleStr = normalizeStyle(parsedStyle, autoPrefix || false);
const styleId = uniqueHash(fullPath, styleStr);
return [styleStr, styleId, effectStyle, clientOnly, order];
},
// Remove cache if no need
(cacheValue, fromHMR) => {
const [, styleId] = cacheValue;
if (fromHMR && _util.isClientSide) {
(0, _dynamicCSS.removeCSS)(styleId, {
mark: _StyleContext.ATTR_MARK,
attachTo: container
});
}
},
// Effect: Inject style here
cacheValue => {
const [styleStr, styleId, effectStyle,, priority] = cacheValue;
if (isMergedClientSide && styleStr !== _cacheMapUtil.CSS_FILE_STYLE) {
let mergedCSSConfig = {
mark: _StyleContext.ATTR_MARK,
prepend: enableLayer ? false : 'queue',
attachTo: container,
priority
};
mergedCSSConfig = (0, _util.injectCSPNonce)(mergedCSSConfig, nonce);
// ================= Split Effect Style =================
// We will split effectStyle here since @layer should be at the top level
const effectLayerKeys = [];
const effectRestKeys = [];
Object.keys(effectStyle).forEach(key => {
if (key.startsWith('@layer')) {
effectLayerKeys.push(key);
} else {
effectRestKeys.push(key);
}
});
// ================= Inject Layer Style =================
// Inject layer style
effectLayerKeys.forEach(effectKey => {
(0, _dynamicCSS.updateCSS)(normalizeStyle(effectStyle[effectKey], autoPrefix || false), `_layer-${effectKey}`, {
...mergedCSSConfig,
prepend: true
});
});
// ==================== Inject Style ====================
// Inject style
const style = (0, _dynamicCSS.updateCSS)(styleStr, styleId, mergedCSSConfig);
style[_StyleContext.CSS_IN_JS_INSTANCE] = cache.instanceId;
// Debug usage. Dev only
if (process.env.NODE_ENV !== 'production') {
style.setAttribute(_StyleContext.ATTR_CACHE_PATH, fullPath.join('|'));
}
// ================ Inject Effect Style =================
// Inject client side effect style
effectRestKeys.forEach(effectKey => {
(0, _dynamicCSS.updateCSS)(normalizeStyle(effectStyle[effectKey], autoPrefix || false), `_effect-${effectKey}`, mergedCSSConfig);
});
}
});
}
const extract = (cache, effectStyles, options) => {
const [styleStr, styleId, effectStyle, clientOnly, order] = cache;
const {
plain,
autoPrefix
} = options || {};
// Skip client only style
if (clientOnly) {
return null;
}
let keyStyleText = styleStr;
// ====================== Share ======================
// Used for @rc-component/util
const sharedAttrs = {
'data-rc-order': 'prependQueue',
'data-rc-priority': `${order}`
};
// ====================== Style ======================
keyStyleText = (0, _util.toStyleStr)(styleStr, undefined, styleId, sharedAttrs, plain);
// =============== Create effect style ===============
if (effectStyle) {
Object.keys(effectStyle).forEach(effectKey => {
// Effect style can be reused
if (!effectStyles[effectKey]) {
effectStyles[effectKey] = true;
const effectStyleStr = normalizeStyle(effectStyle[effectKey], autoPrefix || false);
const effectStyleHTML = (0, _util.toStyleStr)(effectStyleStr, undefined, `_effect-${effectKey}`, sharedAttrs, plain);
if (effectKey.startsWith('@layer')) {
keyStyleText = effectStyleHTML + keyStyleText;
} else {
keyStyleText += effectStyleHTML;
}
}
});
}
return [order, styleId, keyStyleText];
};
exports.extract = extract;
+23
View File
@@ -0,0 +1,23 @@
import extractStyle from './extractStyle';
import useCacheToken, { getComputedToken } from './hooks/useCacheToken';
import useCSSVarRegister from './hooks/useCSSVarRegister';
import type { CSSInterpolation, CSSObject } from './hooks/useStyleRegister';
import useStyleRegister from './hooks/useStyleRegister';
import Keyframes from './Keyframes';
import type { Linter } from './linters';
import { legacyNotSelectorLinter, logicalPropertiesLinter, NaNLinter, parentSelectorLinter } from './linters';
import type { StyleProviderProps } from './StyleContext';
import StyleContext, { createCache, StyleProvider } from './StyleContext';
import type { AbstractCalculator, DerivativeFunc, TokenType } from './theme';
import { createTheme, genCalc, Theme } from './theme';
import type { Transformer } from './transformers/interface';
import autoPrefixTransformer from './transformers/autoPrefix';
import legacyLogicalPropertiesTransformer from './transformers/legacyLogicalProperties';
import px2remTransformer from './transformers/px2rem';
import { unit } from './util';
import { token2CSSVar } from './util/css-variables';
export { Theme, createTheme, useStyleRegister, useCSSVarRegister, useCacheToken, createCache, StyleProvider, StyleContext, Keyframes, extractStyle, getComputedToken, autoPrefixTransformer, legacyLogicalPropertiesTransformer, px2remTransformer, logicalPropertiesLinter, legacyNotSelectorLinter, parentSelectorLinter, NaNLinter, token2CSSVar, unit, genCalc, };
export type { TokenType, CSSObject, CSSInterpolation, DerivativeFunc, Transformer, Linter, StyleProviderProps, AbstractCalculator, };
export declare const _experimental: {
supportModernCSS: () => boolean;
};
+151
View File
@@ -0,0 +1,151 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "Keyframes", {
enumerable: true,
get: function () {
return _Keyframes.default;
}
});
Object.defineProperty(exports, "NaNLinter", {
enumerable: true,
get: function () {
return _linters.NaNLinter;
}
});
Object.defineProperty(exports, "StyleContext", {
enumerable: true,
get: function () {
return _StyleContext.default;
}
});
Object.defineProperty(exports, "StyleProvider", {
enumerable: true,
get: function () {
return _StyleContext.StyleProvider;
}
});
Object.defineProperty(exports, "Theme", {
enumerable: true,
get: function () {
return _theme.Theme;
}
});
exports._experimental = void 0;
Object.defineProperty(exports, "autoPrefixTransformer", {
enumerable: true,
get: function () {
return _autoPrefix.default;
}
});
Object.defineProperty(exports, "createCache", {
enumerable: true,
get: function () {
return _StyleContext.createCache;
}
});
Object.defineProperty(exports, "createTheme", {
enumerable: true,
get: function () {
return _theme.createTheme;
}
});
Object.defineProperty(exports, "extractStyle", {
enumerable: true,
get: function () {
return _extractStyle.default;
}
});
Object.defineProperty(exports, "genCalc", {
enumerable: true,
get: function () {
return _theme.genCalc;
}
});
Object.defineProperty(exports, "getComputedToken", {
enumerable: true,
get: function () {
return _useCacheToken.getComputedToken;
}
});
Object.defineProperty(exports, "legacyLogicalPropertiesTransformer", {
enumerable: true,
get: function () {
return _legacyLogicalProperties.default;
}
});
Object.defineProperty(exports, "legacyNotSelectorLinter", {
enumerable: true,
get: function () {
return _linters.legacyNotSelectorLinter;
}
});
Object.defineProperty(exports, "logicalPropertiesLinter", {
enumerable: true,
get: function () {
return _linters.logicalPropertiesLinter;
}
});
Object.defineProperty(exports, "parentSelectorLinter", {
enumerable: true,
get: function () {
return _linters.parentSelectorLinter;
}
});
Object.defineProperty(exports, "px2remTransformer", {
enumerable: true,
get: function () {
return _px2rem.default;
}
});
Object.defineProperty(exports, "token2CSSVar", {
enumerable: true,
get: function () {
return _cssVariables.token2CSSVar;
}
});
Object.defineProperty(exports, "unit", {
enumerable: true,
get: function () {
return _util.unit;
}
});
Object.defineProperty(exports, "useCSSVarRegister", {
enumerable: true,
get: function () {
return _useCSSVarRegister.default;
}
});
Object.defineProperty(exports, "useCacheToken", {
enumerable: true,
get: function () {
return _useCacheToken.default;
}
});
Object.defineProperty(exports, "useStyleRegister", {
enumerable: true,
get: function () {
return _useStyleRegister.default;
}
});
var _extractStyle = _interopRequireDefault(require("./extractStyle"));
var _useCacheToken = _interopRequireWildcard(require("./hooks/useCacheToken"));
var _useCSSVarRegister = _interopRequireDefault(require("./hooks/useCSSVarRegister"));
var _useStyleRegister = _interopRequireDefault(require("./hooks/useStyleRegister"));
var _Keyframes = _interopRequireDefault(require("./Keyframes"));
var _linters = require("./linters");
var _StyleContext = _interopRequireWildcard(require("./StyleContext"));
var _theme = require("./theme");
var _autoPrefix = _interopRequireDefault(require("./transformers/autoPrefix"));
var _legacyLogicalProperties = _interopRequireDefault(require("./transformers/legacyLogicalProperties"));
var _px2rem = _interopRequireDefault(require("./transformers/px2rem"));
var _util = require("./util");
var _cssVariables = require("./util/css-variables");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const _experimental = exports._experimental = {
supportModernCSS: () => (0, _util.supportWhere)() && (0, _util.supportLogicProps)()
};
@@ -0,0 +1,3 @@
import type { Linter } from './interface';
declare const linter: Linter;
export default linter;
@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _utils = require("./utils");
const linter = (key, value, info) => {
if (typeof value === 'string' && /NaN/g.test(value) || Number.isNaN(value)) {
(0, _utils.lintWarning)(`Unexpected 'NaN' in property '${key}: ${value}'.`, info);
}
};
var _default = exports.default = linter;
@@ -0,0 +1,3 @@
import type { Linter } from './interface';
declare const linter: Linter;
export default linter;
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _utils = require("./utils");
const linter = (key, value, info) => {
if (key === 'content') {
// From emotion: https://github.com/emotion-js/emotion/blob/main/packages/serialize/src/index.js#L63
const contentValuePattern = /(attr|counters?|url|(((repeating-)?(linear|radial))|conic)-gradient)\(|(no-)?(open|close)-quote/;
const contentValues = ['normal', 'none', 'initial', 'inherit', 'unset'];
if (typeof value !== 'string' || contentValues.indexOf(value) === -1 && !contentValuePattern.test(value) && !value.startsWith('var(') && (value.charAt(0) !== value.charAt(value.length - 1) || value.charAt(0) !== '"' && value.charAt(0) !== "'")) {
(0, _utils.lintWarning)(`You seem to be using a value for 'content' without quotes, try replacing it with \`content: '"${value}"'\`.`, info);
}
}
};
var _default = exports.default = linter;
@@ -0,0 +1,3 @@
import type { Linter } from './interface';
declare const linter: Linter;
export default linter;
@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _utils = require("./utils");
const linter = (key, value, info) => {
if (key === 'animation') {
if (info.hashId && value !== 'none') {
(0, _utils.lintWarning)(`You seem to be using hashed animation '${value}', in which case 'animationName' with Keyframe as value is recommended.`, info);
}
}
};
var _default = exports.default = linter;
@@ -0,0 +1,7 @@
export { default as contentQuotesLinter } from './contentQuotesLinter';
export { default as hashedAnimationLinter } from './hashedAnimationLinter';
export type { Linter } from './interface';
export { default as legacyNotSelectorLinter } from './legacyNotSelectorLinter';
export { default as logicalPropertiesLinter } from './logicalPropertiesLinter';
export { default as NaNLinter } from './NaNLinter';
export { default as parentSelectorLinter } from './parentSelectorLinter';
+48
View File
@@ -0,0 +1,48 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "NaNLinter", {
enumerable: true,
get: function () {
return _NaNLinter.default;
}
});
Object.defineProperty(exports, "contentQuotesLinter", {
enumerable: true,
get: function () {
return _contentQuotesLinter.default;
}
});
Object.defineProperty(exports, "hashedAnimationLinter", {
enumerable: true,
get: function () {
return _hashedAnimationLinter.default;
}
});
Object.defineProperty(exports, "legacyNotSelectorLinter", {
enumerable: true,
get: function () {
return _legacyNotSelectorLinter.default;
}
});
Object.defineProperty(exports, "logicalPropertiesLinter", {
enumerable: true,
get: function () {
return _logicalPropertiesLinter.default;
}
});
Object.defineProperty(exports, "parentSelectorLinter", {
enumerable: true,
get: function () {
return _parentSelectorLinter.default;
}
});
var _contentQuotesLinter = _interopRequireDefault(require("./contentQuotesLinter"));
var _hashedAnimationLinter = _interopRequireDefault(require("./hashedAnimationLinter"));
var _legacyNotSelectorLinter = _interopRequireDefault(require("./legacyNotSelectorLinter"));
var _logicalPropertiesLinter = _interopRequireDefault(require("./logicalPropertiesLinter"));
var _NaNLinter = _interopRequireDefault(require("./NaNLinter"));
var _parentSelectorLinter = _interopRequireDefault(require("./parentSelectorLinter"));
@@ -0,0 +1,8 @@
export interface LinterInfo {
path?: string;
hashId?: string;
parentSelectors: string[];
}
export interface Linter {
(key: string, value: string | number, info: LinterInfo): void;
}
@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
@@ -0,0 +1,3 @@
import type { Linter } from './interface';
declare const linter: Linter;
export default linter;
@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _utils = require("./utils");
function isConcatSelector(selector) {
const notContent = selector.match(/:not\(([^)]*)\)/)?.[1] || '';
// split selector. e.g.
// `h1#a.b` => ['h1', #a', '.b']
const splitCells = notContent.split(/(\[[^[]*])|(?=[.#])/).filter(str => str);
return splitCells.length > 1;
}
function parsePath(info) {
return info.parentSelectors.reduce((prev, cur) => {
if (!prev) {
return cur;
}
return cur.includes('&') ? cur.replace(/&/g, prev) : `${prev} ${cur}`;
}, '');
}
const linter = (key, value, info) => {
const parentSelectorPath = parsePath(info);
const notList = parentSelectorPath.match(/:not\([^)]*\)/g) || [];
if (notList.length > 0 && notList.some(isConcatSelector)) {
(0, _utils.lintWarning)(`Concat ':not' selector not support in legacy browsers.`, info);
}
};
var _default = exports.default = linter;
@@ -0,0 +1,3 @@
import type { Linter } from './interface';
declare const linter: Linter;
export default linter;
@@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _utils = require("./utils");
const linter = (key, value, info) => {
switch (key) {
case 'marginLeft':
case 'marginRight':
case 'paddingLeft':
case 'paddingRight':
case 'left':
case 'right':
case 'borderLeft':
case 'borderLeftWidth':
case 'borderLeftStyle':
case 'borderLeftColor':
case 'borderRight':
case 'borderRightWidth':
case 'borderRightStyle':
case 'borderRightColor':
case 'borderTopLeftRadius':
case 'borderTopRightRadius':
case 'borderBottomLeftRadius':
case 'borderBottomRightRadius':
(0, _utils.lintWarning)(`You seem to be using non-logical property '${key}' which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`, info);
return;
case 'margin':
case 'padding':
case 'borderWidth':
case 'borderStyle':
// case 'borderColor':
if (typeof value === 'string') {
const valueArr = value.split(' ').map(item => item.trim());
if (valueArr.length === 4 && valueArr[1] !== valueArr[3]) {
(0, _utils.lintWarning)(`You seem to be using '${key}' property with different left ${key} and right ${key}, which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`, info);
}
}
return;
case 'clear':
case 'textAlign':
if (value === 'left' || value === 'right') {
(0, _utils.lintWarning)(`You seem to be using non-logical value '${value}' of ${key}, which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`, info);
}
return;
case 'borderRadius':
if (typeof value === 'string') {
const radiusGroups = value.split('/').map(item => item.trim());
const invalid = radiusGroups.reduce((result, group) => {
if (result) {
return result;
}
const radiusArr = group.split(' ').map(item => item.trim());
// borderRadius: '2px 4px'
if (radiusArr.length >= 2 && radiusArr[0] !== radiusArr[1]) {
return true;
}
// borderRadius: '4px 4px 2px'
if (radiusArr.length === 3 && radiusArr[1] !== radiusArr[2]) {
return true;
}
// borderRadius: '4px 4px 2px 4px'
if (radiusArr.length === 4 && radiusArr[2] !== radiusArr[3]) {
return true;
}
return result;
}, false);
if (invalid) {
(0, _utils.lintWarning)(`You seem to be using non-logical value '${value}' of ${key}, which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`, info);
}
}
return;
default:
}
};
var _default = exports.default = linter;
@@ -0,0 +1,3 @@
import type { Linter } from '..';
declare const linter: Linter;
export default linter;
@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _utils = require("./utils");
const linter = (key, value, info) => {
if (info.parentSelectors.some(selector => {
const selectors = selector.split(',');
return selectors.some(item => item.split('&').length > 2);
})) {
(0, _utils.lintWarning)('Should not use more than one `&` in a selector.', info);
}
};
var _default = exports.default = linter;
@@ -0,0 +1,2 @@
import type { LinterInfo } from './interface';
export declare function lintWarning(message: string, info: LinterInfo): void;
+15
View File
@@ -0,0 +1,15 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.lintWarning = lintWarning;
var _warning = _interopRequireDefault(require("@rc-component/util/lib/warning"));
function lintWarning(message, info) {
const {
path,
parentSelectors
} = info;
(0, _warning.default)(false, `[Ant Design CSS-in-JS] ${path ? `Error in ${path}: ` : ''}${message}${parentSelectors.length ? ` Selector: ${parentSelectors.join(' | ')}` : ''}`);
}
+11
View File
@@ -0,0 +1,11 @@
import type { DerivativeFunc, TokenType } from './interface';
/**
* Theme with algorithms to derive tokens from design tokens.
* Use `createTheme` first which will help to manage the theme instance cache.
*/
export default class Theme<DesignToken extends TokenType, DerivativeToken extends TokenType> {
private derivatives;
readonly id: number;
constructor(derivatives: DerivativeFunc<DesignToken, DerivativeToken> | DerivativeFunc<DesignToken, DerivativeToken>[]);
getDerivativeToken(token: DesignToken): DerivativeToken;
}
+29
View File
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _warning = require("@rc-component/util/lib/warning");
let uuid = 0;
/**
* Theme with algorithms to derive tokens from design tokens.
* Use `createTheme` first which will help to manage the theme instance cache.
*/
class Theme {
derivatives;
id;
constructor(derivatives) {
this.derivatives = Array.isArray(derivatives) ? derivatives : [derivatives];
this.id = uuid;
if (derivatives.length === 0) {
(0, _warning.warning)(derivatives.length > 0, '[Ant Design CSS-in-JS] Theme should have at least one derivative function.');
}
uuid += 1;
}
getDerivativeToken(token) {
return this.derivatives.reduce((result, derivative) => derivative(token, result), undefined);
}
}
exports.default = Theme;
@@ -0,0 +1,20 @@
import type Theme from './Theme';
import type { DerivativeFunc } from './interface';
type DerivativeOptions = DerivativeFunc<any, any>[];
export declare function sameDerivativeOption(left: DerivativeOptions, right: DerivativeOptions): boolean;
export default class ThemeCache {
static MAX_CACHE_SIZE: number;
static MAX_CACHE_OFFSET: number;
private readonly cache;
private keys;
private cacheCallTimes;
constructor();
size(): number;
private internalGet;
get(derivativeOption: DerivativeOptions): Theme<any, any> | undefined;
has(derivativeOption: DerivativeOptions): boolean;
set(derivativeOption: DerivativeOptions, value: Theme<any, any>): void;
private deleteByPath;
delete(derivativeOption: DerivativeOptions): Theme<any, any> | undefined;
}
export {};
@@ -0,0 +1,118 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.sameDerivativeOption = sameDerivativeOption;
// ================================== Cache ==================================
function sameDerivativeOption(left, right) {
if (left.length !== right.length) {
return false;
}
for (let i = 0; i < left.length; i++) {
if (left[i] !== right[i]) {
return false;
}
}
return true;
}
class ThemeCache {
static MAX_CACHE_SIZE = 20;
static MAX_CACHE_OFFSET = 5;
cache;
keys;
cacheCallTimes;
constructor() {
this.cache = new Map();
this.keys = [];
this.cacheCallTimes = 0;
}
size() {
return this.keys.length;
}
internalGet(derivativeOption, updateCallTimes = false) {
let cache = {
map: this.cache
};
derivativeOption.forEach(derivative => {
if (!cache) {
cache = undefined;
} else {
cache = cache?.map?.get(derivative);
}
});
if (cache?.value && updateCallTimes) {
cache.value[1] = this.cacheCallTimes++;
}
return cache?.value;
}
get(derivativeOption) {
return this.internalGet(derivativeOption, true)?.[0];
}
has(derivativeOption) {
return !!this.internalGet(derivativeOption);
}
set(derivativeOption, value) {
// New cache
if (!this.has(derivativeOption)) {
if (this.size() + 1 > ThemeCache.MAX_CACHE_SIZE + ThemeCache.MAX_CACHE_OFFSET) {
const [targetKey] = this.keys.reduce((result, key) => {
const [, callTimes] = result;
if (this.internalGet(key)[1] < callTimes) {
return [key, this.internalGet(key)[1]];
}
return result;
}, [this.keys[0], this.cacheCallTimes]);
this.delete(targetKey);
}
this.keys.push(derivativeOption);
}
let cache = this.cache;
derivativeOption.forEach((derivative, index) => {
if (index === derivativeOption.length - 1) {
cache.set(derivative, {
value: [value, this.cacheCallTimes++]
});
} else {
const cacheValue = cache.get(derivative);
if (!cacheValue) {
cache.set(derivative, {
map: new Map()
});
} else if (!cacheValue.map) {
cacheValue.map = new Map();
}
cache = cache.get(derivative).map;
}
});
}
deleteByPath(currentCache, derivatives) {
const cache = currentCache.get(derivatives[0]);
if (derivatives.length === 1) {
if (!cache.map) {
currentCache.delete(derivatives[0]);
} else {
currentCache.set(derivatives[0], {
map: cache.map
});
}
return cache.value?.[0];
}
const result = this.deleteByPath(cache.map, derivatives.slice(1));
if ((!cache.map || cache.map.size === 0) && !cache.value) {
currentCache.delete(derivatives[0]);
}
return result;
}
delete(derivativeOption) {
// If cache exists
if (this.has(derivativeOption)) {
this.keys = this.keys.filter(item => !sameDerivativeOption(item, derivativeOption));
return this.deleteByPath(this.cache, derivativeOption);
}
return undefined;
}
}
exports.default = ThemeCache;
@@ -0,0 +1,15 @@
import AbstractCalculator from './calculator';
export default class CSSCalculator extends AbstractCalculator {
result: string;
unitlessCssVar: Set<string>;
lowPriority?: boolean;
constructor(num: number | string | AbstractCalculator, unitlessCssVar: Set<string>);
add(num: number | string | AbstractCalculator): this;
sub(num: number | string | AbstractCalculator): this;
mul(num: number | string | AbstractCalculator): this;
div(num: number | string | AbstractCalculator): this;
getResult(force?: boolean): string;
equal(options?: {
unit?: boolean;
}): string;
}
@@ -0,0 +1,95 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _calculator = _interopRequireDefault(require("./calculator"));
const CALC_UNIT = 'CALC_UNIT';
const regexp = new RegExp(CALC_UNIT, 'g');
function unit(value) {
if (typeof value === 'number') {
return `${value}${CALC_UNIT}`;
}
return value;
}
class CSSCalculator extends _calculator.default {
result = '';
unitlessCssVar;
lowPriority;
constructor(num, unitlessCssVar) {
super();
const numType = typeof num;
this.unitlessCssVar = unitlessCssVar;
if (num instanceof CSSCalculator) {
this.result = `(${num.result})`;
} else if (numType === 'number') {
this.result = unit(num);
} else if (numType === 'string') {
this.result = num;
}
}
add(num) {
if (num instanceof CSSCalculator) {
this.result = `${this.result} + ${num.getResult()}`;
} else if (typeof num === 'number' || typeof num === 'string') {
this.result = `${this.result} + ${unit(num)}`;
}
this.lowPriority = true;
return this;
}
sub(num) {
if (num instanceof CSSCalculator) {
this.result = `${this.result} - ${num.getResult()}`;
} else if (typeof num === 'number' || typeof num === 'string') {
this.result = `${this.result} - ${unit(num)}`;
}
this.lowPriority = true;
return this;
}
mul(num) {
if (this.lowPriority) {
this.result = `(${this.result})`;
}
if (num instanceof CSSCalculator) {
this.result = `${this.result} * ${num.getResult(true)}`;
} else if (typeof num === 'number' || typeof num === 'string') {
this.result = `${this.result} * ${num}`;
}
this.lowPriority = false;
return this;
}
div(num) {
if (this.lowPriority) {
this.result = `(${this.result})`;
}
if (num instanceof CSSCalculator) {
this.result = `${this.result} / ${num.getResult(true)}`;
} else if (typeof num === 'number' || typeof num === 'string') {
this.result = `${this.result} / ${num}`;
}
this.lowPriority = false;
return this;
}
getResult(force) {
return this.lowPriority || force ? `(${this.result})` : this.result;
}
equal(options) {
const {
unit: cssUnit
} = options || {};
let mergedUnit = true;
if (typeof cssUnit === 'boolean') {
mergedUnit = cssUnit;
} else if (Array.from(this.unitlessCssVar).some(cssVar => this.result.includes(cssVar))) {
mergedUnit = false;
}
this.result = this.result.replace(regexp, mergedUnit ? 'px' : '');
if (typeof this.lowPriority !== 'undefined') {
return `calc(${this.result})`;
}
return this.result;
}
}
exports.default = CSSCalculator;
@@ -0,0 +1,10 @@
import AbstractCalculator from './calculator';
export default class NumCalculator extends AbstractCalculator {
result: number;
constructor(num: number | string | AbstractCalculator);
add(num: number | string | AbstractCalculator): this;
sub(num: number | string | AbstractCalculator): this;
mul(num: number | string | AbstractCalculator): this;
div(num: number | string | AbstractCalculator): this;
equal(): number;
}
@@ -0,0 +1,55 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _calculator = _interopRequireDefault(require("./calculator"));
class NumCalculator extends _calculator.default {
result = 0;
constructor(num) {
super();
if (num instanceof NumCalculator) {
this.result = num.result;
} else if (typeof num === 'number') {
this.result = num;
}
}
add(num) {
if (num instanceof NumCalculator) {
this.result += num.result;
} else if (typeof num === 'number') {
this.result += num;
}
return this;
}
sub(num) {
if (num instanceof NumCalculator) {
this.result -= num.result;
} else if (typeof num === 'number') {
this.result -= num;
}
return this;
}
mul(num) {
if (num instanceof NumCalculator) {
this.result *= num.result;
} else if (typeof num === 'number') {
this.result *= num;
}
return this;
}
div(num) {
if (num instanceof NumCalculator) {
this.result /= num.result;
} else if (typeof num === 'number') {
this.result /= num;
}
return this;
}
equal() {
return this.result;
}
}
exports.default = NumCalculator;
@@ -0,0 +1,30 @@
declare abstract class AbstractCalculator {
/**
* @descCN 计算两数的和,例如:1 + 2
* @descEN Calculate the sum of two numbers, e.g. 1 + 2
*/
abstract add(num: number | string | AbstractCalculator): this;
/**
* @descCN 计算两数的差,例如:1 - 2
* @descEN Calculate the difference between two numbers, e.g. 1 - 2
*/
abstract sub(num: number | string | AbstractCalculator): this;
/**
* @descCN 计算两数的积,例如:1 * 2
* @descEN Calculate the product of two numbers, e.g. 1 * 2
*/
abstract mul(num: number | string | AbstractCalculator): this;
/**
* @descCN 计算两数的商,例如:1 / 2
* @descEN Calculate the quotient of two numbers, e.g. 1 / 2
*/
abstract div(num: number | string | AbstractCalculator): this;
/**
* @descCN 获取计算结果
* @descEN Get the calculation result
*/
abstract equal(options?: {
unit?: boolean;
}): string | number;
}
export default AbstractCalculator;
@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
class AbstractCalculator {}
var _default = exports.default = AbstractCalculator;
@@ -0,0 +1,5 @@
import type AbstractCalculator from './calculator';
import CSSCalculator from './CSSCalculator';
import NumCalculator from './NumCalculator';
declare const genCalc: (type: 'css' | 'js', unitlessCssVar: Set<string>) => (num: number | string | AbstractCalculator) => CSSCalculator | NumCalculator;
export default genCalc;
@@ -0,0 +1,14 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _CSSCalculator = _interopRequireDefault(require("./CSSCalculator"));
var _NumCalculator = _interopRequireDefault(require("./NumCalculator"));
const genCalc = (type, unitlessCssVar) => {
const Calculator = type === 'css' ? _CSSCalculator.default : _NumCalculator.default;
return num => new Calculator(num, unitlessCssVar);
};
var _default = exports.default = genCalc;
@@ -0,0 +1,6 @@
import Theme from './Theme';
import type { DerivativeFunc, TokenType } from './interface';
/**
* Same as new Theme, but will always return same one if `derivative` not changed.
*/
export default function createTheme<DesignToken extends TokenType, DerivativeToken extends TokenType>(derivatives: DerivativeFunc<DesignToken, DerivativeToken>[] | DerivativeFunc<DesignToken, DerivativeToken>): Theme<any, any>;
@@ -0,0 +1,24 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = createTheme;
var _ThemeCache = _interopRequireDefault(require("./ThemeCache"));
var _Theme = _interopRequireDefault(require("./Theme"));
const cacheThemes = new _ThemeCache.default();
/**
* Same as new Theme, but will always return same one if `derivative` not changed.
*/
function createTheme(derivatives) {
const derivativeArr = Array.isArray(derivatives) ? derivatives : [derivatives];
// Create new theme if not exist
if (!cacheThemes.has(derivativeArr)) {
cacheThemes.set(derivativeArr, new _Theme.default(derivativeArr));
}
// Get theme from cache and return
return cacheThemes.get(derivativeArr);
}
@@ -0,0 +1,6 @@
export { default as genCalc } from './calc';
export type { default as AbstractCalculator } from './calc/calculator';
export { default as createTheme } from './createTheme';
export type { DerivativeFunc, TokenType } from './interface';
export { default as Theme } from './Theme';
export { default as ThemeCache } from './ThemeCache';
+34
View File
@@ -0,0 +1,34 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "Theme", {
enumerable: true,
get: function () {
return _Theme.default;
}
});
Object.defineProperty(exports, "ThemeCache", {
enumerable: true,
get: function () {
return _ThemeCache.default;
}
});
Object.defineProperty(exports, "createTheme", {
enumerable: true,
get: function () {
return _createTheme.default;
}
});
Object.defineProperty(exports, "genCalc", {
enumerable: true,
get: function () {
return _calc.default;
}
});
var _calc = _interopRequireDefault(require("./calc"));
var _createTheme = _interopRequireDefault(require("./createTheme"));
var _Theme = _interopRequireDefault(require("./Theme"));
var _ThemeCache = _interopRequireDefault(require("./ThemeCache"));
@@ -0,0 +1,2 @@
export type TokenType = object;
export type DerivativeFunc<DesignToken extends TokenType, DerivativeToken extends TokenType> = (designToken: DesignToken, derivativeToken?: DerivativeToken) => DerivativeToken;
@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
@@ -0,0 +1,4 @@
import type { Transformer } from './interface';
export declare const AUTO_PREFIX: {};
declare const transform: Transformer;
export default transform;
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.AUTO_PREFIX = void 0;
const AUTO_PREFIX = exports.AUTO_PREFIX = {};
const transform = AUTO_PREFIX;
var _default = exports.default = transform;
@@ -0,0 +1,4 @@
import type { CSSObject } from '..';
export interface Transformer {
visit?: (cssObj: CSSObject) => CSSObject;
}
@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
@@ -0,0 +1,12 @@
import type { Transformer } from './interface';
/**
* Convert css logical properties to legacy properties.
* Such as: `margin-block-start` to `margin-top`.
* Transform list:
* - inset
* - margin
* - padding
* - border
*/
declare const transform: Transformer;
export default transform;
@@ -0,0 +1,149 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
function splitValues(value) {
if (typeof value === 'number') {
return [[value], false];
}
const rawStyle = String(value).trim();
const importantCells = rawStyle.match(/(.*)(!important)/);
const splitStyle = (importantCells ? importantCells[1] : rawStyle).trim().split(/\s+/);
// Combine styles split in brackets, like `calc(1px + 2px)`
let temp = [];
let brackets = 0;
return [splitStyle.reduce((list, item) => {
if (item.includes('(') || item.includes(')')) {
const left = item.split('(').length - 1;
const right = item.split(')').length - 1;
brackets += left - right;
}
if (brackets >= 0) temp.push(item);
if (brackets === 0) {
list.push(temp.join(' '));
temp = [];
}
return list;
}, []), !!importantCells];
}
function noSplit(list) {
list.notSplit = true;
return list;
}
const keyMap = {
// Inset
inset: ['top', 'right', 'bottom', 'left'],
insetBlock: ['top', 'bottom'],
insetBlockStart: ['top'],
insetBlockEnd: ['bottom'],
insetInline: ['left', 'right'],
insetInlineStart: ['left'],
insetInlineEnd: ['right'],
// Margin
marginBlock: ['marginTop', 'marginBottom'],
marginBlockStart: ['marginTop'],
marginBlockEnd: ['marginBottom'],
marginInline: ['marginLeft', 'marginRight'],
marginInlineStart: ['marginLeft'],
marginInlineEnd: ['marginRight'],
// Padding
paddingBlock: ['paddingTop', 'paddingBottom'],
paddingBlockStart: ['paddingTop'],
paddingBlockEnd: ['paddingBottom'],
paddingInline: ['paddingLeft', 'paddingRight'],
paddingInlineStart: ['paddingLeft'],
paddingInlineEnd: ['paddingRight'],
// Border
borderBlock: noSplit(['borderTop', 'borderBottom']),
borderBlockStart: noSplit(['borderTop']),
borderBlockEnd: noSplit(['borderBottom']),
borderInline: noSplit(['borderLeft', 'borderRight']),
borderInlineStart: noSplit(['borderLeft']),
borderInlineEnd: noSplit(['borderRight']),
// Border width
borderBlockWidth: ['borderTopWidth', 'borderBottomWidth'],
borderBlockStartWidth: ['borderTopWidth'],
borderBlockEndWidth: ['borderBottomWidth'],
borderInlineWidth: ['borderLeftWidth', 'borderRightWidth'],
borderInlineStartWidth: ['borderLeftWidth'],
borderInlineEndWidth: ['borderRightWidth'],
// Border style
borderBlockStyle: ['borderTopStyle', 'borderBottomStyle'],
borderBlockStartStyle: ['borderTopStyle'],
borderBlockEndStyle: ['borderBottomStyle'],
borderInlineStyle: ['borderLeftStyle', 'borderRightStyle'],
borderInlineStartStyle: ['borderLeftStyle'],
borderInlineEndStyle: ['borderRightStyle'],
// Border color
borderBlockColor: ['borderTopColor', 'borderBottomColor'],
borderBlockStartColor: ['borderTopColor'],
borderBlockEndColor: ['borderBottomColor'],
borderInlineColor: ['borderLeftColor', 'borderRightColor'],
borderInlineStartColor: ['borderLeftColor'],
borderInlineEndColor: ['borderRightColor'],
// Border radius
borderStartStartRadius: ['borderTopLeftRadius'],
borderStartEndRadius: ['borderTopRightRadius'],
borderEndStartRadius: ['borderBottomLeftRadius'],
borderEndEndRadius: ['borderBottomRightRadius']
};
function wrapImportantAndSkipCheck(value, important) {
let parsedValue = value;
if (important) {
parsedValue = `${parsedValue} !important`;
}
return {
_skip_check_: true,
value: parsedValue
};
}
/**
* Convert css logical properties to legacy properties.
* Such as: `margin-block-start` to `margin-top`.
* Transform list:
* - inset
* - margin
* - padding
* - border
*/
const transform = {
visit: cssObj => {
const clone = {};
Object.keys(cssObj).forEach(key => {
const value = cssObj[key];
const matchValue = keyMap[key];
if (matchValue && (typeof value === 'number' || typeof value === 'string')) {
const [values, important] = splitValues(value);
if (matchValue.length && matchValue.notSplit) {
// not split means always give same value like border
matchValue.forEach(matchKey => {
clone[matchKey] = wrapImportantAndSkipCheck(value, important);
});
} else if (matchValue.length === 1) {
// Handle like `marginBlockStart` => `marginTop`
clone[matchValue[0]] = wrapImportantAndSkipCheck(values[0], important);
} else if (matchValue.length === 2) {
// Handle like `marginBlock` => `marginTop` & `marginBottom`
matchValue.forEach((matchKey, index) => {
clone[matchKey] = wrapImportantAndSkipCheck(values[index] ?? values[0], important);
});
} else if (matchValue.length === 4) {
// Handle like `inset` => `top` & `right` & `bottom` & `left`
matchValue.forEach((matchKey, index) => {
clone[matchKey] = wrapImportantAndSkipCheck(values[index] ?? values[index - 2] ?? values[0], important);
});
} else {
clone[key] = value;
}
} else {
clone[key] = value;
}
});
return clone;
}
};
var _default = exports.default = transform;
@@ -0,0 +1,20 @@
import type { Transformer } from './interface';
interface Options {
/**
* The root font size.
* @default 16
*/
rootValue?: number;
/**
* The decimal numbers to allow the REM units to grow to.
* @default 5
*/
precision?: number;
/**
* Whether to allow px to be converted in media queries.
* @default false
*/
mediaQuery?: boolean;
}
declare const transform: (options?: Options) => Transformer;
export default transform;
@@ -0,0 +1,63 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _unitless = _interopRequireDefault(require("@emotion/unitless"));
/**
* respect https://github.com/cuth/postcss-pxtorem
*/
// @ts-ignore
const pxRegex = /url\([^)]+\)|var\([^)]+\)|(\d*\.?\d+)px/g;
function toFixed(number, precision) {
const multiplier = Math.pow(10, precision + 1),
wholeNumber = Math.floor(number * multiplier);
return Math.round(wholeNumber / 10) * 10 / multiplier;
}
const transform = (options = {}) => {
const {
rootValue = 16,
precision = 5,
mediaQuery = false
} = options;
const pxReplace = (m, $1) => {
if (!$1) return m;
const pixels = parseFloat($1);
// covenant: pixels <= 1, not transform to rem @zombieJ
if (pixels <= 1) return m;
const fixedVal = toFixed(pixels / rootValue, precision);
return `${fixedVal}rem`;
};
const visit = cssObj => {
const clone = {
...cssObj
};
Object.entries(cssObj).forEach(([key, value]) => {
if (typeof value === 'string' && value.includes('px')) {
const newValue = value.replace(pxRegex, pxReplace);
clone[key] = newValue;
}
// no unit
if (!_unitless.default[key] && typeof value === 'number' && value !== 0) {
clone[key] = `${value}px`.replace(pxRegex, pxReplace);
}
// Media queries
const mergedKey = key.trim();
if (mergedKey.startsWith('@') && mergedKey.includes('px') && mediaQuery) {
const newKey = key.replace(pxRegex, pxReplace);
clone[newKey] = clone[key];
delete clone[key];
}
});
return clone;
};
return {
visit
};
};
var _default = exports.default = transform;
@@ -0,0 +1,14 @@
export declare const ATTR_CACHE_MAP = "data-ant-cssinjs-cache-path";
/**
* This marks style from the css file.
* Which means not exist in `<style />` tag.
*/
export declare const CSS_FILE_STYLE = "_FILE_STYLE__";
export declare function serialize(cachePathMap: Record<string, string>): string;
/**
* @private Test usage only. Can save remove if no need.
*/
export declare function reset(mockCache?: Record<string, string>, fromFile?: boolean): void;
export declare function prepare(): void;
export declare function existPath(path: string): boolean;
export declare function getStyleAndHash(path: string): [style: string | null, hash: string];
@@ -0,0 +1,88 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CSS_FILE_STYLE = exports.ATTR_CACHE_MAP = void 0;
exports.existPath = existPath;
exports.getStyleAndHash = getStyleAndHash;
exports.prepare = prepare;
exports.reset = reset;
exports.serialize = serialize;
var _canUseDom = _interopRequireDefault(require("@rc-component/util/lib/Dom/canUseDom"));
var _StyleContext = require("../StyleContext");
const ATTR_CACHE_MAP = exports.ATTR_CACHE_MAP = 'data-ant-cssinjs-cache-path';
/**
* This marks style from the css file.
* Which means not exist in `<style />` tag.
*/
const CSS_FILE_STYLE = exports.CSS_FILE_STYLE = '_FILE_STYLE__';
function serialize(cachePathMap) {
return Object.keys(cachePathMap).map(path => {
const hash = cachePathMap[path];
return `${path}:${hash}`;
}).join(';');
}
let cachePathMap;
let fromCSSFile = true;
/**
* @private Test usage only. Can save remove if no need.
*/
function reset(mockCache, fromFile = true) {
cachePathMap = mockCache;
fromCSSFile = fromFile;
}
function prepare() {
if (!cachePathMap) {
cachePathMap = {};
if ((0, _canUseDom.default)()) {
const div = document.createElement('div');
div.className = ATTR_CACHE_MAP;
div.style.position = 'fixed';
div.style.visibility = 'hidden';
div.style.top = '-9999px';
document.body.appendChild(div);
let content = getComputedStyle(div).content || '';
content = content.replace(/^"/, '').replace(/"$/, '');
// Fill data
content.split(';').forEach(item => {
const [path, hash] = item.split(':');
cachePathMap[path] = hash;
});
// Remove inline record style
const inlineMapStyle = document.querySelector(`style[${ATTR_CACHE_MAP}]`);
if (inlineMapStyle) {
fromCSSFile = false;
inlineMapStyle.parentNode?.removeChild(inlineMapStyle);
}
document.body.removeChild(div);
}
}
}
function existPath(path) {
prepare();
return !!cachePathMap[path];
}
function getStyleAndHash(path) {
const hash = cachePathMap[path];
let styleStr = null;
if (hash && (0, _canUseDom.default)()) {
if (fromCSSFile) {
styleStr = CSS_FILE_STYLE;
} else {
const style = document.querySelector(`style[${_StyleContext.ATTR_MARK}="${cachePathMap[path]}"]`);
if (style) {
styleStr = style.innerHTML;
} else {
// Clean up since not exist anymore
delete cachePathMap[path];
}
}
}
return [styleStr, hash];
}
@@ -0,0 +1,19 @@
import type { HashPriority } from '../StyleContext';
export declare const token2CSSVar: (token: string, prefix?: string) => string;
export declare const serializeCSSVar: <T extends Record<string, any>>(cssVars: T, hashId: string, options?: {
scope?: string | string[];
hashCls?: string;
hashPriority?: HashPriority;
}) => string;
export type TokenWithCSSVar<V, T extends Record<string, V> = Record<string, V>> = {
[key in keyof T]?: string | V;
};
export declare const transformToken: <V, T extends Record<string, V> = Record<string, V>>(token: T, themeKey: string, config?: {
prefix?: string | undefined;
ignore?: { [key in keyof T]?: boolean | undefined; } | undefined;
unitless?: { [key_1 in keyof T]?: boolean | undefined; } | undefined;
preserve?: { [key_2 in keyof T]?: boolean | undefined; } | undefined;
scope?: string | string[] | undefined;
hashCls?: string | undefined;
hashPriority?: HashPriority | undefined;
} | undefined) => [TokenWithCSSVar<V, T>, string];
@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.transformToken = exports.token2CSSVar = exports.serializeCSSVar = void 0;
var _util = require("../util");
const token2CSSVar = (token, prefix = '') => {
return `--${prefix ? `${prefix}-` : ''}${token}`.replace(/([a-z0-9])([A-Z])/g, '$1-$2').replace(/([A-Z]+)([A-Z][a-z0-9]+)/g, '$1-$2').replace(/([a-z])([A-Z0-9])/g, '$1-$2').toLowerCase();
};
exports.token2CSSVar = token2CSSVar;
const serializeCSSVar = (cssVars, hashId, options) => {
const {
hashCls,
hashPriority = 'low',
scope
} = options || {};
if (!Object.keys(cssVars).length) {
return '';
}
const baseSelector = `${(0, _util.where)({
hashCls,
hashPriority
})}.${hashId}`;
const scopes = [scope].flat().filter(Boolean);
const selector = scopes.length ? scopes.map(s => `${baseSelector}.${s}`).join(', ') : baseSelector;
return `${selector}{${Object.entries(cssVars).map(([key, value]) => `${key}:${value};`).join('')}}`;
};
exports.serializeCSSVar = serializeCSSVar;
const transformToken = (token, themeKey, config) => {
const {
hashCls,
hashPriority = 'low',
prefix,
unitless,
ignore,
preserve
} = config || {};
const cssVars = {};
const result = {};
Object.entries(token).forEach(([key, value]) => {
if (preserve?.[key]) {
result[key] = value;
} else if ((typeof value === 'string' || typeof value === 'number') && !ignore?.[key]) {
const cssVar = token2CSSVar(key, prefix);
cssVars[cssVar] = typeof value === 'number' && !unitless?.[key] ? `${value}px` : String(value);
result[key] = `var(${cssVar})`;
}
});
return [result, serializeCSSVar(cssVars, themeKey, {
scope: config?.scope,
hashCls,
hashPriority
})];
};
exports.transformToken = transformToken;
+30
View File
@@ -0,0 +1,30 @@
import type { HashPriority } from '../StyleContext';
export declare function memoResult<T extends object, R>(callback: () => R, deps: T[]): R;
/**
* Flatten token to string, this will auto cache the result when token not change
*/
export declare function flattenToken(token: any): string;
/**
* Convert derivative token to key string
*/
export declare function token2key(token: any, salt: string): string;
export declare function supportLayer(): boolean;
export declare function supportWhere(): boolean;
export declare function supportLogicProps(): boolean;
export declare const isClientSide: boolean;
export declare function unit(num: string | number): string;
export declare function toStyleStr(style: string, tokenKey?: string, styleId?: string, customizeAttrs?: Record<string, string>, plain?: boolean): string;
export declare function where(options?: {
hashPriority?: HashPriority;
hashCls?: string;
}): string;
export declare const isNonNullable: <T>(val: T) => val is NonNullable<T>;
export type Nonce = string | (() => string);
/**
* Get nonce value and inject it into CSS config if available.
*/
export declare function injectCSPNonce<T extends {
csp?: {
nonce?: string;
};
}>(config: T, nonce: Nonce | undefined): T;
+182
View File
@@ -0,0 +1,182 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.flattenToken = flattenToken;
exports.injectCSPNonce = injectCSPNonce;
exports.isNonNullable = exports.isClientSide = void 0;
exports.memoResult = memoResult;
exports.supportLayer = supportLayer;
exports.supportLogicProps = supportLogicProps;
exports.supportWhere = supportWhere;
exports.toStyleStr = toStyleStr;
exports.token2key = token2key;
exports.unit = unit;
exports.where = where;
var _hash = _interopRequireDefault(require("@emotion/hash"));
var _canUseDom = _interopRequireDefault(require("@rc-component/util/lib/Dom/canUseDom"));
var _dynamicCSS = require("@rc-component/util/lib/Dom/dynamicCSS");
var _StyleContext = require("../StyleContext");
var _theme = require("../theme");
// Create a cache for memo concat
const resultCache = new WeakMap();
const RESULT_VALUE = {};
function memoResult(callback, deps) {
let current = resultCache;
for (let i = 0; i < deps.length; i += 1) {
const dep = deps[i];
if (!current.has(dep)) {
current.set(dep, new WeakMap());
}
current = current.get(dep);
}
if (!current.has(RESULT_VALUE)) {
current.set(RESULT_VALUE, callback());
}
return current.get(RESULT_VALUE);
}
// Create a cache here to avoid always loop generate
const flattenTokenCache = new WeakMap();
/**
* Flatten token to string, this will auto cache the result when token not change
*/
function flattenToken(token) {
let str = flattenTokenCache.get(token) || '';
if (!str) {
Object.keys(token).forEach(key => {
const value = token[key];
str += key;
if (value instanceof _theme.Theme) {
str += value.id;
} else if (value && typeof value === 'object') {
str += flattenToken(value);
} else {
str += value;
}
});
// https://github.com/ant-design/ant-design/issues/48386
// Should hash the string to avoid style tag name too long
str = (0, _hash.default)(str);
// Put in cache
flattenTokenCache.set(token, str);
}
return str;
}
/**
* Convert derivative token to key string
*/
function token2key(token, salt) {
return (0, _hash.default)(`${salt}_${flattenToken(token)}`);
}
const randomSelectorKey = `random-${Date.now()}-${Math.random()}`.replace(/\./g, '');
// Magic `content` for detect selector support
const checkContent = '_bAmBoO_';
function supportSelector(styleStr, handleElement, supportCheck) {
if ((0, _canUseDom.default)()) {
(0, _dynamicCSS.updateCSS)(styleStr, randomSelectorKey);
const ele = document.createElement('div');
ele.style.position = 'fixed';
ele.style.left = '0';
ele.style.top = '0';
handleElement?.(ele);
document.body.appendChild(ele);
if (process.env.NODE_ENV !== 'production') {
ele.innerHTML = 'Test';
ele.style.zIndex = '9999999';
}
const support = supportCheck ? supportCheck(ele) : getComputedStyle(ele).content?.includes(checkContent);
ele.parentNode?.removeChild(ele);
(0, _dynamicCSS.removeCSS)(randomSelectorKey);
return support;
}
return false;
}
let canLayer = undefined;
function supportLayer() {
if (canLayer === undefined) {
canLayer = supportSelector(`@layer ${randomSelectorKey} { .${randomSelectorKey} { content: "${checkContent}"!important; } }`, ele => {
ele.className = randomSelectorKey;
});
}
return canLayer;
}
let canWhere = undefined;
function supportWhere() {
if (canWhere === undefined) {
canWhere = supportSelector(`:where(.${randomSelectorKey}) { content: "${checkContent}"!important; }`, ele => {
ele.className = randomSelectorKey;
});
}
return canWhere;
}
let canLogic = undefined;
function supportLogicProps() {
if (canLogic === undefined) {
canLogic = supportSelector(`.${randomSelectorKey} { inset-block: 93px !important; }`, ele => {
ele.className = randomSelectorKey;
}, ele => getComputedStyle(ele).bottom === '93px');
}
return canLogic;
}
const isClientSide = exports.isClientSide = (0, _canUseDom.default)();
function unit(num) {
if (typeof num === 'number') {
return `${num}px`;
}
return num;
}
function toStyleStr(style, tokenKey, styleId, customizeAttrs = {}, plain = false) {
if (plain) {
return style;
}
const attrs = {
...customizeAttrs,
[_StyleContext.ATTR_TOKEN]: tokenKey,
[_StyleContext.ATTR_MARK]: styleId
};
const attrStr = Object.keys(attrs).map(attr => {
const val = attrs[attr];
return val ? `${attr}="${val}"` : null;
}).filter(v => v).join(' ');
return `<style ${attrStr}>${style}</style>`;
}
function where(options) {
const {
hashCls,
hashPriority = 'low'
} = options || {};
if (!hashCls) {
return '';
}
const hashSelector = `.${hashCls}`;
return hashPriority === 'low' ? `:where(${hashSelector})` : hashSelector;
}
const isNonNullable = val => {
return val !== undefined && val !== null;
};
exports.isNonNullable = isNonNullable;
/**
* Get nonce value and inject it into CSS config if available.
*/
function injectCSPNonce(config, nonce) {
const nonceStr = typeof nonce === 'function' ? nonce() : nonce;
if (nonceStr) {
return {
...config,
csp: {
...config.csp,
nonce: nonceStr
}
};
}
return config;
}
+17
View File
@@ -0,0 +1,17 @@
export type KeyType = string | number;
type ValueType = [number, any];
/** Connect key with `SPLIT` */
export declare function pathKey(keys: KeyType[]): string;
declare class Entity {
instanceId: string;
constructor(instanceId: string);
/** @private Internal cache map. Do not access this directly */
cache: Map<string, ValueType>;
get(keys: KeyType[]): ValueType | null;
/** A fast get cache with `get` concat. */
opGet(keyPathStr: string): ValueType | null;
update(keys: KeyType[], valueFn: (origin: ValueType | null) => ValueType | null): void;
/** A fast get cache with `get` concat. */
opUpdate(keyPathStr: string, valueFn: (origin: ValueType | null) => ValueType | null): void;
}
export default Entity;
+47
View File
@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.pathKey = pathKey;
// [times, realValue]
const SPLIT = '%';
/** Connect key with `SPLIT` */
function pathKey(keys) {
return keys.join(SPLIT);
}
class Entity {
instanceId;
constructor(instanceId) {
this.instanceId = instanceId;
}
/** @private Internal cache map. Do not access this directly */
cache = new Map();
get(keys) {
return this.opGet(pathKey(keys));
}
/** A fast get cache with `get` concat. */
opGet(keyPathStr) {
return this.cache.get(keyPathStr) || null;
}
update(keys, valueFn) {
return this.opUpdate(pathKey(keys), valueFn);
}
/** A fast get cache with `get` concat. */
opUpdate(keyPathStr, valueFn) {
const prevValue = this.cache.get(keyPathStr);
const nextValue = valueFn(prevValue);
if (nextValue === null) {
this.cache.delete(keyPathStr);
} else {
this.cache.set(keyPathStr, nextValue);
}
}
}
var _default = exports.default = Entity;