mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-28 05:05:48 +08:00
fix: global icon style (#38617)
* fix: global icon style * chore: code clean * feat: icon style in CP * chore: code clean * chore: code clean * chore: support ss * feat: wrapSSR only if iconPrefixCls does not equal parent * chore: code clean * chore: fix lint * chore: fix lint * chore: test * chore: wrap children * chore: code clean * chore: fix lint
This commit is contained in:
parent
3639697ba4
commit
6848b23169
@ -1,4 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { SmileOutlined } from '@ant-design/icons';
|
||||
import ConfigProvider from '..';
|
||||
import Button from '../../button';
|
||||
import Divider from '../../divider';
|
||||
@ -6,7 +7,7 @@ import { render } from '../../../tests/utils';
|
||||
|
||||
describe('ConfigProvider.DynamicTheme', () => {
|
||||
beforeEach(() => {
|
||||
Array.from(document.querySelectorAll('style')).forEach(style => {
|
||||
Array.from(document.querySelectorAll('style')).forEach((style) => {
|
||||
style.parentNode?.removeChild(style);
|
||||
});
|
||||
});
|
||||
@ -27,7 +28,7 @@ describe('ConfigProvider.DynamicTheme', () => {
|
||||
const dynamicStyles = Array.from(document.querySelectorAll('style[data-css-hash]'));
|
||||
|
||||
expect(
|
||||
dynamicStyles.some(style => {
|
||||
dynamicStyles.some((style) => {
|
||||
const { innerHTML } = style;
|
||||
return (
|
||||
innerHTML.includes('.ant-btn-primary') && innerHTML.includes('background-color:#f00000')
|
||||
@ -64,7 +65,7 @@ describe('ConfigProvider.DynamicTheme', () => {
|
||||
const dynamicStyles = Array.from(document.querySelectorAll('style[data-css-hash]'));
|
||||
|
||||
expect(
|
||||
dynamicStyles.some(style => {
|
||||
dynamicStyles.some((style) => {
|
||||
const { innerHTML } = style;
|
||||
return (
|
||||
innerHTML.includes('.ant-divider') && innerHTML.includes('border-block-start:0 blue')
|
||||
@ -72,4 +73,22 @@ describe('ConfigProvider.DynamicTheme', () => {
|
||||
}),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support iconPrefixCls', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider iconPrefixCls="test-icon">
|
||||
<SmileOutlined />
|
||||
</ConfigProvider>,
|
||||
);
|
||||
|
||||
expect(container.querySelector('.test-icon')).toBeTruthy();
|
||||
|
||||
const dynamicStyles = Array.from(document.querySelectorAll('style[data-css-hash]'));
|
||||
expect(
|
||||
dynamicStyles.some((style) => {
|
||||
const { innerHTML } = style;
|
||||
return innerHTML.includes('.test-icon');
|
||||
}),
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -4,6 +4,7 @@ import { FormProvider as RcFormProvider } from 'rc-field-form';
|
||||
import type { ValidateMessages } from 'rc-field-form/lib/interface';
|
||||
import useMemo from 'rc-util/lib/hooks/useMemo';
|
||||
import * as React from 'react';
|
||||
import type { ReactElement } from 'react';
|
||||
import type { RequiredMark } from '../form/Form';
|
||||
import type { Locale } from '../locale-provider';
|
||||
import LocaleProvider, { ANT_MARK } from '../locale-provider';
|
||||
@ -19,6 +20,7 @@ import { DisabledContextProvider } from './DisabledContext';
|
||||
import useTheme from './hooks/useTheme';
|
||||
import type { SizeType } from './SizeContext';
|
||||
import SizeContext, { SizeContextProvider } from './SizeContext';
|
||||
import useStyle from './style';
|
||||
|
||||
export {
|
||||
type RenderEmptyHandler,
|
||||
@ -139,7 +141,7 @@ export const globalConfig = () => ({
|
||||
},
|
||||
});
|
||||
|
||||
const ProviderChildren: React.FC<ProviderChildrenProps> = props => {
|
||||
const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
|
||||
const {
|
||||
children,
|
||||
csp: customCsp,
|
||||
@ -172,8 +174,11 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = props => {
|
||||
);
|
||||
|
||||
const iconPrefixCls = customIconPrefixCls || parentContext.iconPrefixCls || defaultIconPrefixCls;
|
||||
const shouldWrapSSR = iconPrefixCls !== parentContext.iconPrefixCls;
|
||||
const csp = customCsp || parentContext.csp;
|
||||
|
||||
const wrapSSR = useStyle(iconPrefixCls);
|
||||
|
||||
const mergedTheme = useTheme(theme, parentContext.theme);
|
||||
|
||||
const config = {
|
||||
@ -192,7 +197,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = props => {
|
||||
|
||||
// Pass the props used by `useContext` directly with child component.
|
||||
// These props should merged into `config`.
|
||||
PASSED_PROPS.forEach(propName => {
|
||||
PASSED_PROPS.forEach((propName) => {
|
||||
const propValue = props[propName];
|
||||
if (propValue) {
|
||||
(config as any)[propName] = propValue;
|
||||
@ -208,7 +213,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = props => {
|
||||
const currentKeys = Object.keys(currentConfig) as Array<keyof typeof config>;
|
||||
return (
|
||||
prevKeys.length !== currentKeys.length ||
|
||||
prevKeys.some(key => prevConfig[key] !== currentConfig[key])
|
||||
prevKeys.some((key) => prevConfig[key] !== currentConfig[key])
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -218,7 +223,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = props => {
|
||||
[iconPrefixCls, csp],
|
||||
);
|
||||
|
||||
let childNode = children;
|
||||
let childNode = shouldWrapSSR ? wrapSSR(children as ReactElement) : children;
|
||||
// Additional Form provider
|
||||
let validateMessages: ValidateMessages = {};
|
||||
|
||||
@ -292,11 +297,11 @@ const ConfigProvider: React.FC<ConfigProviderProps> & {
|
||||
ConfigContext: typeof ConfigContext;
|
||||
SizeContext: typeof SizeContext;
|
||||
config: typeof setGlobalConfig;
|
||||
} = props => (
|
||||
} = (props) => (
|
||||
<LocaleReceiver>
|
||||
{(_, __, legacyLocale) => (
|
||||
<ConfigConsumer>
|
||||
{context => (
|
||||
{(context) => (
|
||||
<ProviderChildren parentContext={context} legacyLocale={legacyLocale} {...props} />
|
||||
)}
|
||||
</ConfigConsumer>
|
||||
|
18
components/config-provider/style/index.tsx
Normal file
18
components/config-provider/style/index.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import { useStyleRegister } from '@ant-design/cssinjs';
|
||||
import { resetIcon } from '../../style';
|
||||
import { useToken } from '../../theme';
|
||||
|
||||
const useStyle = (iconPrefixCls: string) => {
|
||||
const [theme, token] = useToken();
|
||||
// Generate style for icons
|
||||
return useStyleRegister(
|
||||
{ theme, token, hashId: '', path: ['ant-design-icons', iconPrefixCls] },
|
||||
() => [
|
||||
{
|
||||
[`.${iconPrefixCls}`]: resetIcon(),
|
||||
},
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
export default useStyle;
|
@ -80,7 +80,7 @@ describe('message.config', () => {
|
||||
|
||||
const noticeWithoutLeaving = Array.from(
|
||||
document.querySelectorAll('.ant-message-notice'),
|
||||
).filter(ele => !ele.classList.contains('ant-message-move-up-leave'));
|
||||
).filter((ele) => !ele.classList.contains('ant-message-move-up-leave'));
|
||||
|
||||
expect(noticeWithoutLeaving).toHaveLength(5);
|
||||
expect(noticeWithoutLeaving[4].textContent).toEqual('last');
|
||||
|
Loading…
Reference in New Issue
Block a user