Browse Source

fix: css var

feat-4.3
tangjinzhou 2 weeks ago
parent
commit
a1e029429f
  1. 37
      components/_theme/context.ts
  2. 59
      components/_util/_cssinjs/hooks/useCSSVarRegister.ts
  3. 10
      components/_util/_cssinjs/hooks/useGlobalCache.tsx
  4. 3
      components/config-provider/hooks/useCssVarCls.ts
  5. 6
      components/config-provider/hooks/useTheme.ts
  6. 12
      components/config-provider/hooks/useThemeKey.ts
  7. 2
      package.json

37
components/_theme/context.ts

@ -64,39 +64,24 @@ export interface DesignTokenProviderProps {
};
}
export const useDesignTokenInject = () => {
return inject(
DesignTokenContextKey,
computed(() => globalDesignTokenApi.value || defaultConfig),
);
};
export const useDesignTokenProvider = (props: ComputedRef<DesignTokenProviderProps>) => {
const parentContext = useDesignTokenInject();
const context = shallowRef<Partial<DesignTokenProviderProps>>(defaultConfig);
export const useDesignTokenProvider = (value: ComputedRef<DesignTokenProviderProps>) => {
provide(DesignTokenContextKey, value);
watch(
computed(() => [props.value, parentContext.value]),
([propsValue, parentContextValue]) => {
const mergedContext: Partial<DesignTokenProviderProps> = {
...parentContextValue,
};
Object.keys(propsValue).forEach(key => {
const value = propsValue[key];
if (propsValue[key] !== undefined) {
mergedContext[key] = value;
}
});
context.value = mergedContext;
globalDesignTokenApi.value = unref(mergedContext as any);
value,
() => {
globalDesignTokenApi.value = unref(value);
triggerRef(globalDesignTokenApi);
},
{ immediate: true, deep: true },
);
provide(DesignTokenContextKey, context);
return context;
};
export const useDesignTokenInject = () => {
return inject(
DesignTokenContextKey,
computed(() => globalDesignTokenApi.value || defaultConfig),
);
};
export const DesignTokenProvider = defineComponent({
props: {
value: objectType<DesignTokenProviderProps>(),

59
components/_util/_cssinjs/hooks/useCSSVarRegister.ts

@ -1,6 +1,6 @@
import { updateCSS } from '../../../vc-util/Dom/dynamicCSS';
import { removeCSS, updateCSS } from '../../../vc-util/Dom/dynamicCSS';
import { ATTR_MARK, ATTR_TOKEN, CSS_IN_JS_INSTANCE, useStyleInject } from '../StyleContext';
import { isClientSide, token2key, toStyleStr } from '../util';
import { isClientSide, toStyleStr } from '../util';
import type { TokenWithCSSVar } from '../util/css-variables';
import { transformToken } from '../util/css-variables';
import type { ExtractStyle } from './useGlobalCache';
@ -14,50 +14,10 @@ export const CSS_VAR_PREFIX = 'cssVar';
type CSSVarCacheValue<V, T extends Record<string, V> = Record<string, V>> = [
cssVarToken: TokenWithCSSVar<V, T>,
cssVarStr: string,
tokenKey: string,
styleId: string,
cssVarKey: string,
];
const tokenKeys = new Map<string, number>();
function recordCleanToken(tokenKey: string) {
tokenKeys.set(tokenKey, (tokenKeys.get(tokenKey) || 0) + 1);
}
function removeStyleTags(key: string, instanceId: string) {
if (typeof document !== 'undefined') {
const styles = document.querySelectorAll(`style[${ATTR_MARK}="${key}"]`);
styles.forEach(style => {
if ((style as any)[CSS_IN_JS_INSTANCE] === instanceId) {
style.parentNode?.removeChild(style);
}
});
}
}
const TOKEN_THRESHOLD = 0;
// Remove will check current keys first
function cleanTokenStyle(tokenKey: string, instanceId: string) {
tokenKeys.set(tokenKey, (tokenKeys.get(tokenKey) || 0) - 1);
const tokenKeyList = Array.from(tokenKeys.keys());
const cleanableKeyList = tokenKeyList.filter(key => {
const count = tokenKeys.get(key) || 0;
return count <= 0;
});
// Should keep tokens under threshold for not to insert style too often
if (tokenKeyList.length - cleanableKeyList.length > TOKEN_THRESHOLD) {
cleanableKeyList.forEach(key => {
removeStyleTags(key, instanceId);
tokenKeys.delete(key);
});
}
}
const useCSSVarRegister = <V, T extends Record<string, V>>(
config: ComputedRef<{
path: string[];
@ -93,25 +53,20 @@ const useCSSVarRegister = <V, T extends Record<string, V>>(
scope: config.value.scope || '',
});
const tokenKey = token2key(mergedToken, '');
const styleId = uniqueHash(stylePath.value, cssVarsStr);
recordCleanToken(tokenKey);
return [mergedToken, cssVarsStr, tokenKey, styleId, config.value.key];
return [mergedToken, cssVarsStr, styleId, config.value.key];
},
([, , tokenKey]) => {
([, , styleId]) => {
if (isClientSide) {
// Remove token will remove all related style
cleanTokenStyle(tokenKey, styleContext.value?.cache?.instanceId);
removeCSS(styleId, { mark: ATTR_MARK });
}
},
([, cssVarsStr, tokenKey]) => {
([, cssVarsStr, styleId]) => {
if (!cssVarsStr) {
return;
}
const style = updateCSS(cssVarsStr, tokenKey, {
const style = updateCSS(cssVarsStr, styleId, {
mark: ATTR_MARK,
prepend: 'queue',
attachTo: styleContext.value.container,

10
components/_util/_cssinjs/hooks/useGlobalCache.tsx

@ -49,9 +49,13 @@ export default function useGlobalCache<CacheType>(
});
};
watch(deps, () => {
buildCache();
});
watch(
deps,
() => {
buildCache();
},
{ immediate: true },
);
let cacheEntity = globalCache.value.get(deps.value);

3
components/config-provider/hooks/useCssVarCls.ts

@ -1,5 +1,6 @@
import { useToken } from '../../_theme/internal';
import type { Ref } from 'vue';
import { computed } from 'vue';
/**
* This hook is only for cssVar to add root className for components.
@ -9,7 +10,7 @@ import type { Ref } from 'vue';
const useCSSVarCls = (prefixCls: Ref<string>) => {
const [, , , , cssVar] = useToken();
return cssVar.value ? `${prefixCls.value}-css-var` : '';
return computed(() => (cssVar.value ? `${prefixCls.value}-css-var` : ''));
};
export default useCSSVarCls;

6
components/config-provider/hooks/useTheme.ts

@ -2,17 +2,14 @@ import type { ThemeConfig } from '../context';
import { defaultConfig } from '../../_theme/internal';
import type { Ref } from 'vue';
import { computed } from 'vue';
import useThemeKey from './useThemeKey';
import devWarning from '../../vc-util/warning';
const themeKey = 'antdvtheme';
export default function useTheme(theme?: Ref<ThemeConfig>, parentTheme?: Ref<ThemeConfig>) {
const themeConfig = computed(() => theme?.value || {});
const parentThemeConfig = computed<ThemeConfig>(() =>
themeConfig.value.inherit === false || !parentTheme?.value ? defaultConfig : parentTheme.value,
);
const themeKey = useThemeKey();
if (process.env.NODE_ENV !== 'production') {
const cssVarEnabled = themeConfig.value.cssVar || parentThemeConfig.value.cssVar;
const validKey = !!(
@ -43,6 +40,7 @@ export default function useTheme(theme?: Ref<ThemeConfig>, parentTheme?: Ref<The
});
const cssVarKey = `css-var-${themeKey.replace(/:/g, '')}`;
const mergedCssVar = (themeConfig.value.cssVar ?? parentThemeConfig.value.cssVar) && {
prefix: 'ant', // Default to ant
...(typeof parentThemeConfig.value.cssVar === 'object' ? parentThemeConfig.value.cssVar : {}),

12
components/config-provider/hooks/useThemeKey.ts

@ -1,14 +1,6 @@
import { getCurrentInstance } from 'vue';
import _ from 'lodash';
let uid = 0;
const useThemeKey = () => {
const instance = getCurrentInstance();
if (!instance) {
return _.uniqueId() + '';
}
return instance.uid + '';
return 'themekey' + uid++;
};
export default useThemeKey;

2
package.json

@ -247,7 +247,7 @@
"tinycolor2": "^1.6.0",
"ts-jest": "^28.0.5",
"ts-loader": "^9.1.0",
"tsx": "^3.12.10",
"tsx": "^4.0.0",
"typedoc": "^0.23.25",
"typescript": "~4.9.3",
"umi-request": "^1.3.5",

Loading…
Cancel
Save