Skip to content

Commit

Permalink
feat: add useAntdConfig (#11856)
Browse files Browse the repository at this point in the history
* feat: add useAntdConfig

* refactor: ...

* docs: functional

---------

Co-authored-by: fz6m <[email protected]>
  • Loading branch information
xiaohuoni and fz6m authored Nov 23, 2023
1 parent 50005ae commit 5a75e3d
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 53 deletions.
52 changes: 52 additions & 0 deletions docs/docs/docs/max/antd.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,58 @@ export const antd: RuntimeAntdConfig = (memo) => {
};
```

### 动态切换全局配置

**注意:该功能仅 antd v5 可用**

通过 `useAntdConfig` / `useAntdConfigSetter` 方法来动态获取、修改 antd 的 `ConfigProvider` 配置,通常可用于动态修改主题。

注:此功能需依赖 `ConfigProvider` ,请一并开启 `configProvider: {}`

```tsx
import { Layout, Space, Button, version, theme, MappingAlgorithm } from 'antd';
import { useAntdConfig, useAntdConfigSetter } from 'umi';
const { darkAlgorithm, defaultAlgorithm } = theme;

export default function Page() {
const setAntdConfig = useAntdConfigSetter();
const antdConfig = useAntdConfig();
return (
<Layout>
<h1>with antd@{version}</h1>
<Space>
isDarkTheme
<Switch
checked={antdConfig?.theme?.algorithm.includes(darkAlgorithm)}
onChange={(data) => {
// 此配置会与原配置深合并
setAntdConfig({
theme: {
algorithm: [
data ? darkAlgorithm : defaultAlgorithm,
],
},
});
// or
setAntdConfig((config) => {
const algorithm = config.theme!.algorithm as MappingAlgorithm[];
if (algorithm.includes(darkAlgorithm)) {
config.theme!.algorithm = [defaultAlgorithm]
} else {
config.theme!.algorithm = [darkAlgorithm];
}
return config;
});
}}
></Switch>
</Space>
</Layout>
);
}
```

使用 `setAntdConfig` 可以动态修改 [antd@5 ConfigProvider](https://ant.design/components/config-provider-cn) 组件支持的所有属性。

## FAQ

### 如何使用 antd 的其他版本?
Expand Down
3 changes: 3 additions & 0 deletions examples/with-antd-5/app.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { theme } from 'antd';
import { RuntimeAntdConfig } from 'umi';

export const antd: RuntimeAntdConfig = (memo) => {
memo.appConfig ??= {};
memo.appConfig.message ??= {};
memo.appConfig.message.duration = 5;

memo.theme!.algorithm = theme.darkAlgorithm;

return memo;
};
74 changes: 68 additions & 6 deletions examples/with-antd-5/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
import { App, Button, Space, theme, version } from 'antd';
import React, { useState } from 'react';
import { getLocale, setLocale, useIntl } from 'umi';
import {
App,
Button,
MappingAlgorithm,
Space,
Switch,
theme,
version,
} from 'antd';
import type { ConfigProviderProps } from 'antd/es/config-provider';
import { useState } from 'react';
import {
getLocale,
setLocale,
useAntdConfig,
useAntdConfigSetter,
useIntl,
} from 'umi';
const { useToken, darkAlgorithm, defaultAlgorithm, compactAlgorithm } = theme;

const checkHasAlgorithm = (
antdConfig: ConfigProviderProps,
algorithm: MappingAlgorithm,
) => {
if (!antdConfig?.theme?.algorithm) {
return false;
}
const nowAlgorithm = Array.isArray(antdConfig?.theme?.algorithm)
? antdConfig?.theme?.algorithm
: [antdConfig?.theme?.algorithm];
return nowAlgorithm?.includes(algorithm);
};

export default function Page() {
const setAntdConfig = useAntdConfigSetter();
const antdConfig = useAntdConfig();
const [isZh, setIsZh] = useState(true);
// 若要使用 useApp hook,须先在 antd 插件中配置 appConfig
const { message, modal } = App.useApp();
const locale = getLocale();
const { token } = theme.useToken();
const { token } = useToken();

const showModal = () => {
modal.confirm({
title: 'Hai',
content: '注意 Modal 内的按钮样式应该和页面中的按钮样一致',
content: '注意 Modal 内的按钮样式应该和页面中的按钮样式一致',
maskClosable: true,
});
};
Expand All @@ -25,14 +56,27 @@ export default function Page() {
// app.txt 中配置了 appConfig.message.duration = 5
message.info('Hai');
};

const isDark = checkHasAlgorithm(antdConfig, darkAlgorithm);
const isCompact = checkHasAlgorithm(antdConfig, compactAlgorithm);
const changeTheme = (theme: MappingAlgorithm) => {
setAntdConfig((config) => {
const algorithm = config.theme!.algorithm as MappingAlgorithm[];
if (algorithm.includes(theme)) {
config.theme!.algorithm = algorithm.filter((item) => item !== theme);
} else {
config.theme!.algorithm = [...algorithm, theme];
}
return config;
});
};
return (
<div
style={{
backgroundColor: token.colorBgContainer,
height: '100vh',
}}
>
{Math.random()}
<h1>with antd@{version}</h1>
<Space>
<Button onClick={sayHai}>Say Hai</Button>
Expand All @@ -49,6 +93,24 @@ export default function Page() {
{msg}
</Button>
</Space>
<Space>
isDarkTheme
<Switch
checked={isDark}
onChange={() => {
changeTheme(darkAlgorithm);
}}
></Switch>
</Space>
<Space>
isCompactTheme
<Switch
checked={isCompact}
onChange={(data) => {
changeTheme(compactAlgorithm);
}}
></Switch>
</Space>
</div>
);
}
3 changes: 3 additions & 0 deletions examples/with-antd-5/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "./.umi/tsconfig.json"
}
65 changes: 55 additions & 10 deletions packages/plugins/src/antd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ export default (api: IApi) => {
}
}

// 如果使用静态主题配置,需要搭配 ConfigProvider ,否则无效,我们自动开启它
if (antd.dark || antd.compact) {
antd.configProvider ??= {};
}

return memo;
});

Expand Down Expand Up @@ -202,6 +207,11 @@ export default (api: IApi) => {
return [];
});

const lodashPkg = dirname(require.resolve('lodash/package.json'));
const lodashPath = {
merge: winPath(join(lodashPkg, 'merge')),
};

// antd config provider & app component
api.onGenerateFiles(() => {
const withConfigProvider = !!api.config.antd.configProvider;
Expand All @@ -210,8 +220,6 @@ export default (api: IApi) => {
const userInputCompact = api.config.antd.compact;
const userInputDark = api.config.antd.dark;

// Hack StyleProvider

const ieTarget = !!api.config.targets?.ie || !!api.config.legacy;

let styleProviderConfig: any = false;
Expand Down Expand Up @@ -242,19 +250,27 @@ export default (api: IApi) => {
}

// Template
const configProvider =
withConfigProvider && JSON.stringify(api.config.antd.configProvider);
const appConfig =
appComponentAvailable && JSON.stringify(api.config.antd.appConfig);
const enableV5ThemeAlgorithm =
isV5 && (userInputCompact || userInputDark)
? { compact: userInputCompact, dark: userInputDark }
: false;
const hasConfigProvider = configProvider || enableV5ThemeAlgorithm;
// 拥有 `ConfigProvider` 时,我们默认提供修改 antd 全局配置的便捷方法(仅限 antd 5)
const antdConfigSetter = isV5 && hasConfigProvider;
api.writeTmpFile({
path: `runtime.tsx`,
context: {
configProvider:
withConfigProvider && JSON.stringify(api.config.antd.configProvider),
appConfig:
appComponentAvailable && JSON.stringify(api.config.antd.appConfig),
configProvider,
appConfig,
styleProvider: styleProviderConfig,
// 是否启用了 v5 的 theme algorithm
enableV5ThemeAlgorithm:
isV5 && (userInputCompact || userInputDark)
? { compact: userInputCompact, dark: userInputDark }
: false,
enableV5ThemeAlgorithm,
antdConfigSetter,
lodashPath,
/**
* 是否重构了全局静态配置。 重构后需要在运行时将全局静态配置传入到 ConfigProvider 中。
* 实际上 4.13.0 重构后有一个 bug,真正的 warn 出现在 4.13.1,并且 4.13.1 修复了这个 bug。
Expand Down Expand Up @@ -284,6 +300,35 @@ export type IRuntimeConfig = {
};
`,
});

if (antdConfigSetter) {
api.writeTmpFile({
path: 'index.tsx',
content: `import React from 'react';
import { AntdConfigContext, AntdConfigContextSetter } from './context';
export function useAntdConfig() {
return React.useContext(AntdConfigContext);
}
export function useAntdConfigSetter() {
return React.useContext(AntdConfigContextSetter);
}`,
});
api.writeTmpFile({
path: 'context.tsx',
content: `import React from 'react';
import type { ConfigProviderProps } from 'antd/es/config-provider';
export const AntdConfigContext = React.createContext<ConfigProviderProps>(null!);
export const AntdConfigContextSetter = React.createContext<React.Dispatch<React.SetStateAction<ConfigProviderProps>>>(
() => {
console.error(\`The 'useAntdConfigSetter()' method depends on the antd 'ConfigProvider', requires one of 'antd.configProvider' / 'antd.dark' / 'antd.compact' to be enabled.\`);
}
);
`,
});
}
});

api.addRuntimePlugin(() => {
Expand Down
Loading

1 comment on commit 5a75e3d

@vercel
Copy link

@vercel vercel bot commented on 5a75e3d Nov 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.