refactor: ConfigProvider theme API update (#37568)

* refactor: ConfigProvider theme support component alias

* test: fix test case

* chore: code clean

* test: fix lint

* test: fix tsx-demo
This commit is contained in:
MadCcc 2022-09-15 21:26:04 +08:00 committed by GitHub
parent 8bdabe25e0
commit 3515a40706
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 34 additions and 47 deletions

View File

@ -57,12 +57,10 @@ export default function genPurePanel<ComponentProps extends BaseProps>(
return (
<ConfigProvider
theme={{
override: {
derivative: {
motionDurationFast: '0.01s',
motionDurationMid: '0.01s',
motionDurationSlow: '0.01s',
},
token: {
motionDurationFast: '0.01s',
motionDurationMid: '0.01s',
motionDurationSlow: '0.01s',
},
}}
>

View File

@ -52,10 +52,8 @@ describe('ConfigProvider.DynamicTheme', () => {
mount(
<ConfigProvider
theme={{
override: {
alias: {
colorSplit: 'blue',
},
token: {
colorSplit: 'blue',
},
}}
>

View File

@ -69,7 +69,7 @@ describe('ConfigProvider.Theme', () => {
<Demo />
</ConfigProvider>,
);
expect(tokenRef?.colorPrimary).toBe('#177ddc');
expect(tokenRef?.colorPrimaryText).toBe('#177ddc');
});
it('defaultAlgorithmV4 should work', () => {
@ -116,12 +116,12 @@ describe('ConfigProvider.Theme', () => {
<Demo />
</ConfigProvider>,
);
expect(tokenRef?.colorPrimary).toBe('#177ddc');
expect(tokenRef?.colorPrimaryText).toBe('#177ddc');
});
it('overriding component token should work', () => {
render(
<ConfigProvider theme={{ override: { InputNumber: { handleWidth: 50.1234 } } }}>
<ConfigProvider theme={{ components: { InputNumber: { handleWidth: 50.1234 } } }}>
<InputNumber />
</ConfigProvider>,
);

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import type { DerivativeFunc } from '@ant-design/cssinjs';
import type { RequiredMark } from '../form/Form';
import type { Locale } from '../locale-provider';
import type { MapToken, OverrideToken, SeedToken } from '../theme/interface';
import type { AliasToken, MapToken, OverrideToken, SeedToken } from '../theme/interface';
import type { RenderEmptyHandler } from './defaultRenderEmpty';
import type { SizeType } from './SizeContext';
@ -26,8 +26,8 @@ export type DirectionType = 'ltr' | 'rtl' | undefined;
export type MappingAlgorithm = DerivativeFunc<SeedToken, MapToken>;
export interface ThemeConfig {
token?: Partial<SeedToken>;
override?: OverrideToken;
token?: Partial<AliasToken>;
components?: OverrideToken;
algorithm?: MappingAlgorithm | MappingAlgorithm[];
hashed?: boolean;
}

View File

@ -18,13 +18,13 @@ export default function useTheme(
// Override
const mergedOverride = {
...parentThemeConfig.override,
...parentThemeConfig.components,
};
Object.keys(theme.override || {}).forEach((componentName: keyof OverrideToken) => {
Object.keys(theme.components || {}).forEach((componentName: keyof OverrideToken) => {
mergedOverride[componentName] = {
...mergedOverride[componentName],
...theme.override![componentName],
...theme.components![componentName],
} as any;
});

View File

@ -12,7 +12,7 @@ import { ConfigProvider, InputNumber, Space } from 'antd';
export default () => (
<ConfigProvider
theme={{
override: {
components: {
InputNumber: {
handleWidth: 50,
},
@ -24,7 +24,7 @@ export default () => (
<ConfigProvider
theme={{
override: {
components: {
InputNumber: {
handleWidth: 25,
},

View File

@ -78,7 +78,7 @@ const ThemedMenu = forwardRef<MenuRef, MenuProps>(({ theme = 'light', ...rest },
}, [theme]);
return (
<ConfigProvider theme={{ override: { Menu: darkThemeToken } }}>
<ConfigProvider theme={{ components: { Menu: darkThemeToken } }}>
<SiderContext.Consumer>
{(context: SiderContextProps) => <InternalMenu ref={menuRef} {...rest} {...context} />}
</SiderContext.Consumer>

View File

@ -48,9 +48,9 @@ export const defaultConfig = {
};
export const DesignTokenContext = React.createContext<{
token: Partial<SeedToken>;
token: Partial<AliasToken>;
theme?: Theme<SeedToken, MapToken>;
override?: OverrideToken;
components?: OverrideToken;
hashed?: string | boolean;
}>(defaultConfig);
@ -61,7 +61,12 @@ const saltPrefix =
process.env.NODE_ENV === 'production' ? version : `${version}-${new Date().getHours()}`;
export function useToken(): [Theme<SeedToken, MapToken>, GlobalToken, string] {
const { token: rootDesignToken, override, hashed, theme } = React.useContext(DesignTokenContext);
const {
token: rootDesignToken,
hashed,
theme,
components,
} = React.useContext(DesignTokenContext);
const salt = `${saltPrefix}-${hashed || ''}`;
@ -72,7 +77,7 @@ export function useToken(): [Theme<SeedToken, MapToken>, GlobalToken, string] {
[defaultSeedToken, rootDesignToken],
{
salt,
override,
override: { override: rootDesignToken, ...components },
formatToken,
},
);

View File

@ -130,16 +130,10 @@ export interface ComponentTokenMap {
Progress?: ProgressComponentToken;
}
type OverrideComponentToken = {
[key in keyof ComponentTokenMap]: Partial<ComponentTokenMap[key]>;
export type OverrideToken = {
[key in keyof ComponentTokenMap]: Partial<ComponentTokenMap[key]> & Partial<AliasToken>;
};
export interface OverrideToken extends OverrideComponentToken {
derivative?: Partial<MapToken>;
/** @private Internal Usage */
alias?: Partial<AliasToken>;
}
/** Final token which contains the components level override */
export type GlobalToken = AliasToken & ComponentTokenMap;

View File

@ -2,7 +2,7 @@ import { TinyColor } from '@ctrl/tinycolor';
import type { AliasToken, MapToken, OverrideToken } from '../interface';
/** Raw merge of `@ant-design/cssinjs` token. Which need additional process */
type RawMergedToken = MapToken & OverrideToken;
type RawMergedToken = MapToken & OverrideToken & { override: Partial<AliasToken> };
/**
* Seed (designer) > Derivative (designer) > Alias (developer).
@ -10,11 +10,11 @@ type RawMergedToken = MapToken & OverrideToken;
* Merge seed & derivative & override token and generate alias token for developer.
*/
export default function formatToken(derivativeToken: RawMergedToken): AliasToken {
const { derivative, alias, ...restToken } = derivativeToken;
const { override, ...restToken } = derivativeToken;
const mergedToken = {
...restToken,
...derivative,
...override,
};
const { fontSizes, lineHeights } = mergedToken;
@ -193,7 +193,7 @@ export default function formatToken(derivativeToken: RawMergedToken): AliasToken
boxShadowTabsOverflowBottom: `inset 0 -10px 8px -8px rgba(0, 0, 0, 0.08)`,
// Override AliasToken
...alias,
...override,
};
return aliasToken;

View File

@ -77,15 +77,7 @@ export default function genComponentStyleHook<ComponentName extends OverrideComp
const defaultComponentToken =
typeof getDefaultToken === 'function' ? getDefaultToken(proxyToken) : getDefaultToken;
const overrideComponentToken = token[component] as any;
// Only merge token specified in interface
const mergedComponentToken = { ...defaultComponentToken } as any;
if (overrideComponentToken) {
Object.keys(mergedComponentToken).forEach(key => {
mergedComponentToken[key] = overrideComponentToken[key] ?? mergedComponentToken[key];
});
}
const mergedComponentToken = { ...defaultComponentToken, ...token[component] };
const componentCls = `.${prefixCls}`;
const mergedToken = mergeToken<