Skip to content

feat(cssvar): Migrate cssvar features of antd v5.13.2 version #7220

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions components/_theme/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import type { ShallowRef, InjectionKey, ExtractPropTypes, ComputedRef } from 'vue';
import {
defineComponent,
inject,
provide,
shallowRef,
unref,
triggerRef,
watch,
computed,
} from 'vue';
import type { Theme } from '../_util/_cssinjs';
import { createTheme } from '../_util/_cssinjs';

import { objectType, someType } from '../_util/type';
import type { AliasToken, MapToken, OverrideToken, SeedToken } from './interface';
import defaultDerivative from './themes/default';
import defaultSeedToken from './themes/seed';

export const defaultTheme = createTheme(defaultDerivative);

// ================================ Context =================================
// To ensure snapshot stable. We disable hashed in test env.
const DesignTokenContextKey: InjectionKey<ShallowRef<Partial<DesignTokenProviderProps>>> =
Symbol('DesignTokenContextKey');

export const globalDesignTokenApi = shallowRef<DesignTokenProviderProps>();

export const defaultConfig = {
token: defaultSeedToken,
override: { override: defaultSeedToken },
hashed: true,
};

export type ComponentsToken = {
[key in keyof OverrideToken]?: OverrideToken[key] & {
theme?: Theme<SeedToken, MapToken>;
};
};
export const styleProviderProps = () => ({
token: objectType<AliasToken>(),
theme: objectType<Theme<SeedToken, MapToken>>(),
components: objectType<ComponentsToken>(),
/** Just merge `token` & `override` at top to save perf */
override: objectType<{ override: Partial<AliasToken> } & ComponentsToken>(),
hashed: someType<string | boolean>(),
cssVar: someType<{
prefix?: string;
key?: string;
}>(),
});

export type StyleProviderProps = Partial<ExtractPropTypes<ReturnType<typeof styleProviderProps>>>;
export interface DesignTokenProviderProps {
token: Partial<AliasToken>;
theme?: Theme<SeedToken, MapToken>;
components?: ComponentsToken;
/** Just merge `token` & `override` at top to save perf */
override?: { override: Partial<AliasToken> } & ComponentsToken;
hashed?: string | boolean;
cssVar?: {
prefix?: string;
key?: string;
};
}

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);
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);
triggerRef(globalDesignTokenApi);
},
{ immediate: true, deep: true },
);
provide(DesignTokenContextKey, context);
return context;
};

export const DesignTokenProvider = defineComponent({
props: {
value: objectType<DesignTokenProviderProps>(),
},
setup(props, { slots }) {
useDesignTokenProvider(computed(() => props.value));
return () => {
return slots.default?.();
};
},
});

export default { useDesignTokenInject, useDesignTokenProvider, DesignTokenProvider };
17 changes: 17 additions & 0 deletions components/_theme/getDesignToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { createTheme, getComputedToken } from '../_util/_cssinjs';
import type { ThemeConfig } from '../config-provider/context';
import type { AliasToken } from './interface';
import defaultDerivative from './themes/default';
import seedToken from './themes/seed';
import formatToken from './util/alias';

const getDesignToken = (config?: ThemeConfig): AliasToken => {
const theme = config?.algorithm ? createTheme(config.algorithm) : createTheme(defaultDerivative);
const mergedToken = {
...seedToken,
...config?.token,
};
return getComputedToken(mergedToken, { override: config?.token }, theme, formatToken);
};

export default getDesignToken;
33 changes: 33 additions & 0 deletions components/_theme/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable import/prefer-default-export */
import getDesignToken from './getDesignToken';
import type { GlobalToken, MappingAlgorithm } from './interface';
import { defaultConfig, useToken as useInternalToken } from './internal';
import compactAlgorithm from './themes/compact';
import darkAlgorithm from './themes/dark';
import defaultAlgorithm from './themes/default';

// ZombieJ: We export as object to user but array in internal.
// This is used to minimize the bundle size for antd package but safe to refactor as object also.
// Please do not export internal `useToken` directly to avoid something export unexpected.
/** Get current context Design Token. Will be different if you are using nest theme config. */
function useToken() {
const [theme, token, hashId] = useInternalToken();

return { theme, token, hashId };
}

export type { GlobalToken, MappingAlgorithm };

export default {
/** @private Test Usage. Do not use in production. */
defaultConfig,

/** Default seedToken */
defaultSeed: defaultConfig.token,

useToken,
defaultAlgorithm,
darkAlgorithm,
compactAlgorithm,
getDesignToken,
};
Loading