Compare commits

..

3 Commits

Author SHA1 Message Date
lijianan
d85e0e0163 Merge branch 'master' into chore/scripts 2025-10-19 11:08:45 +08:00
lijianan
1ab5e38e70 Merge branch 'master' into chore/scripts 2025-08-24 15:31:56 +08:00
MadCcc
52a701b497 chore: add inquirer to skip CI 2025-08-11 17:04:37 +08:00
409 changed files with 4449 additions and 12015 deletions

View File

@@ -20,9 +20,6 @@
html {
scrollbar-width: thin;
scrollbar-color: #eaeaea transparent;
@supports (text-autospace: normal) {
text-autospace: normal;
}
}
.rc-footer {

View File

@@ -1,113 +0,0 @@
import React, { useCallback, useEffect } from 'react';
const ANT_SYNC_STORAGE_EVENT_KEY = 'ANT_SYNC_STORAGE_EVENT_KEY';
const isFunction = (val: any): val is (...args: any[]) => any => {
return typeof val === 'function';
};
interface Options<T> {
defaultValue?: T;
serializer?: (value: T) => string;
deserializer?: (value: string) => T;
onError?: (error: unknown) => void;
}
const useLocalStorage = <T>(key: string, options: Options<T> = {}) => {
const storage = typeof window !== 'undefined' ? localStorage : null;
const { serializer, deserializer, onError, defaultValue } = options;
const mergedSerializer = typeof serializer === 'function' ? serializer : JSON.stringify;
const mergedDeserializer = typeof deserializer === 'function' ? deserializer : JSON.parse;
const handleError = typeof onError === 'function' ? onError : console.error;
const getStoredValue = () => {
try {
const rawData = storage?.getItem(key);
if (rawData) {
return mergedDeserializer(rawData);
}
} catch (e) {
if (process.env.NODE_ENV !== 'production') {
handleError(e);
}
return defaultValue;
}
return defaultValue;
};
const [state, setState] = React.useState<T>(getStoredValue);
useEffect(() => {
setState(getStoredValue());
}, [key]);
const updateState: React.Dispatch<React.SetStateAction<T>> = (value) => {
const currentState = isFunction(value) ? value(state) : value;
setState(currentState);
try {
let newValue: string | null;
const oldValue = storage?.getItem(key);
if (typeof currentState === 'undefined') {
newValue = null;
storage?.removeItem(key);
} else {
newValue = mergedSerializer(currentState);
storage?.setItem(key, newValue);
}
dispatchEvent(
new CustomEvent(ANT_SYNC_STORAGE_EVENT_KEY, {
detail: { key, newValue, oldValue, storageArea: storage },
}),
);
} catch (e) {
if (process.env.NODE_ENV !== 'production') {
handleError(e);
}
}
};
const shouldSync = (ev: StorageEvent) => {
return ev && ev.key === key && ev.storageArea === storage;
};
const onNativeStorage = useCallback(
(event: StorageEvent) => {
if (shouldSync(event)) {
setState(getStoredValue());
}
},
[key],
);
const shouldSyncCustomEvent = (ev: CustomEvent<{ key: string; storageArea: Storage }>) => {
return ev?.detail?.key === key && ev?.detail?.storageArea === storage;
};
const onCustomStorage = useCallback(
(event: Event) => {
const customEvent = event as CustomEvent;
if (shouldSyncCustomEvent(customEvent)) {
setState(getStoredValue());
}
},
[key],
);
useEffect(() => {
window?.addEventListener('storage', onNativeStorage);
window?.addEventListener(ANT_SYNC_STORAGE_EVENT_KEY, onCustomStorage);
return () => {
window?.removeEventListener('storage', onNativeStorage);
window?.removeEventListener(ANT_SYNC_STORAGE_EVENT_KEY, onCustomStorage);
};
}, [key, onNativeStorage, onCustomStorage]);
return [state, updateState] as const;
};
export default useLocalStorage;

View File

@@ -85,6 +85,10 @@ const useThemeAnimation = () => {
);
document
.startViewTransition(async () => {
// wait for theme change end
while (colorBgElevated === animateRef.current.colorBgElevated) {
await new Promise<void>((resolve) => setTimeout(resolve, 1000 / 60));
}
const root = document.documentElement;
root.classList.remove(isDark ? 'dark' : 'light');
root.classList.add(isDark ? 'light' : 'dark');

View File

@@ -31,17 +31,15 @@ const locales = {
const useStyle = createStyles(({ token, css, cx }, siteConfig: SiteContextProps) => {
const textShadow = `0 0 4px ${token.colorBgContainer}`;
const isDark = siteConfig.theme.includes('dark');
const mask = cx(css`
position: absolute;
inset: 0;
backdrop-filter: blur(2px);
opacity: 1;
background-color: rgba(255, 255, 255, 0.2);
background-color: ${isDark ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.2)'};
transition: all 1s ease;
pointer-events: none;
[data-prefers-color='dark'] & {
background-color: rgba(0, 0, 0, 0.2);
}
`);
const block = cx(css`

View File

@@ -389,9 +389,10 @@ const Theme: React.FC = () => {
themeType,
...ThemesInfo[themeType],
};
setThemeData(mergedData);
form.setFieldsValue(mergedData);
}, [form, themeType]);
}, [themeType]);
const isDark = React.use(DarkContext);
@@ -432,14 +433,23 @@ const Theme: React.FC = () => {
token: { ...themeToken, colorPrimary: colorPrimaryValue },
algorithm: algorithmFn,
components: {
Layout: isLight ? { headerBg: 'transparent', bodyBg: 'transparent' } : {},
Layout: isLight
? {
headerBg: 'transparent',
bodyBg: 'transparent',
}
: {},
Menu: isLight
? { itemBg: 'transparent', subMenuItemBg: 'transparent', activeBarBorderWidth: 0 }
? {
itemBg: 'transparent',
subMenuItemBg: 'transparent',
activeBarBorderWidth: 0,
}
: {},
...(themeType === 'v4' ? defaultTheme.components : {}),
},
}),
[themeToken, colorPrimaryValue, algorithmFn, isLight, themeType],
[themeToken, colorPrimaryValue, algorithmFn, themeType],
);
// ================================ Render ================================

View File

@@ -60,15 +60,7 @@ export type Extras = {
export type Icons = Icon[];
export type HeadingBanner = {
[key in 'cn' | 'en']: {
title?: string;
href?: string;
};
};
export type SiteData = {
headingBanner: HeadingBanner;
articles: Articles;
authors: Authors;
recommendations: Recommendations;
@@ -90,31 +82,10 @@ export function preLoad(list: string[]) {
}
}
/**
* Banner 硬编码,以防止页面闪烁问题
* 返回 null 表示不显示
*/
export const getBannerData = (): null | {
title: string;
href: string;
} => {
// return {
// title: 'See Conf 2025 震撼来袭 - 探索 AI 时代的用户体验与工程实践',
// href: 'https://seeconf.antfin.com/',
// };
return null;
};
export const useAntdSiteConfig = () => {
const { data, error, isLoading } = useSWR<Partial<SiteData>, Error>(
`https://render.alipay.com/p/h5data/antd4-config_website-h5data.json`,
(url: string) => fetch(url).then((res) => res.json()),
{
suspense: false,
// revalidateOnMount: false,
revalidateIfStale: false,
revalidateOnFocus: false,
},
);
return { data, error, isLoading };
};

View File

@@ -1,5 +1,5 @@
import React, { Suspense } from 'react';
import { App, Button, ConfigProvider, Skeleton, version } from 'antd';
import React, { Suspense, useEffect } from 'react';
import { App, Button, ConfigProvider, Skeleton } from 'antd';
import { enUS, zhCN } from 'antd-token-previewer';
import type { ThemeConfig } from 'antd/es/config-provider/context';
import { Helmet } from 'dumi';
@@ -33,21 +33,21 @@ const locales = {
},
};
const [antdMajor] = version.split('.');
const ANT_DESIGN_V5_THEME_EDITOR_THEME = `ant-design-v${antdMajor}-theme-editor-theme`;
const ANT_DESIGN_V5_THEME_EDITOR_THEME = 'ant-design-v5-theme-editor-theme';
const CustomTheme: React.FC = () => {
const { message } = App.useApp();
const [locale, lang] = useLocale(locales);
const [theme, setTheme] = React.useState<ThemeConfig>(() => {
try {
const storedConfig = localStorage.getItem(ANT_DESIGN_V5_THEME_EDITOR_THEME);
return storedConfig ? JSON.parse(storedConfig) : {};
} catch {
return {};
const [theme, setTheme] = React.useState<ThemeConfig>({});
useEffect(() => {
const storedConfig = localStorage.getItem(ANT_DESIGN_V5_THEME_EDITOR_THEME);
if (storedConfig) {
const themeConfig = JSON.parse(storedConfig);
setTheme(themeConfig);
}
});
}, []);
const handleSave = () => {
localStorage.setItem(ANT_DESIGN_V5_THEME_EDITOR_THEME, JSON.stringify(theme));

View File

@@ -20,9 +20,7 @@
const isEnabled = always || enabledCondition.every(Boolean);
if (!isEnabled) {
return;
}
if (!isEnabled) return;
const prefixCls = 'antd-mirror-notify';
const primaryColor = '#1677ff';

View File

@@ -48,7 +48,7 @@ const locales = {
},
};
const branchUrl = (repo: string) => `https://github.com/${repo}/edit/5.x-stable/`;
const branchUrl = (repo: string) => `https://github.com/${repo}/edit/master/`;
function isVersionNumber(value?: string) {
return value && /^\d+\.\d+\.\d+$/.test(value);
@@ -126,7 +126,7 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
if (String(source) === 'true') {
const kebabComponent = kebabCase(component);
return [
`https://github.com/${repo}/blob/5.x-stable/components/${kebabComponent}`,
`https://github.com/${repo}/blob/master/components/${kebabComponent}`,
`components/${kebabComponent}`,
];
}
@@ -139,10 +139,7 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
}, [component, repo, source]);
// ======================== Render ========================
const importCode =
component === 'Icon'
? `import { AntDesignOutlined } from '@ant-design/icons';`
: `import { ${transformComponentName(component)} } from 'antd';`;
const importList = `import { ${transformComponentName(component)} } from "antd";`;
return (
<Descriptions
@@ -156,14 +153,14 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
{
label: locale.import,
children: (
<CopyToClipboard text={importCode} onCopy={onCopy}>
<CopyToClipboard text={`import { ${component} } from "antd";`} onCopy={onCopy}>
<Tooltip
placement="right"
title={copied ? locale.copied : locale.copy}
onOpenChange={onOpenChange}
>
<Typography.Text className={styles.code} onClick={onCopy}>
{importCode}
{importList}
</Typography.Text>
</Tooltip>
</CopyToClipboard>

View File

@@ -7,8 +7,8 @@ import classNames from 'classnames';
import ImagePreview from '../ImagePreview';
import type { ImagePreviewProps } from '../ImagePreview';
const isNonNullable = <T,>(val: T): val is NonNullable<T> => {
return val !== undefined && val !== null;
const isNotEmpty = (val: any) => {
return typeof val !== 'undefined' && val !== null && val !== '';
};
const useStyle = createStyles(({ css, token }) => {
@@ -51,8 +51,8 @@ const FlexWithImagePreview: React.FC<
return (
<Flex className={classNames(styles.wrapper, className)} style={style} {...rest}>
<Flex align="flex-start" justify="flex-start" vertical>
{isNonNullable(title) && <div className={styles.title}>{title}</div>}
{isNonNullable(description) && <div className={styles.description}>{description}</div>}
{isNotEmpty(title) && <div className={styles.title}>{title}</div>}
{isNotEmpty(description) && <div className={styles.description}>{description}</div>}
</Flex>
<ImagePreview {...imagePreviewProps}>{children}</ImagePreview>
</Flex>

View File

@@ -48,8 +48,6 @@ const IconSearch: React.FC = () => {
const handleSearchIcon = debounce((e: React.ChangeEvent<HTMLInputElement>) => {
setDisplayState((prevState) => ({ ...prevState, searchKey: e.target.value }));
document.getElementById('list-of-icons')?.scrollIntoView({ behavior: 'smooth' });
}, 300);
const handleChangeTheme = useCallback((value: ThemeType) => {

View File

@@ -164,6 +164,7 @@ const CodePreview: React.FC<CodePreviewProps> = ({
</div>
),
})),
// eslint-disable-next-line react-hooks/exhaustive-deps
[
entryName,
error,

View File

@@ -72,10 +72,10 @@ const Palette: React.FC<PaletteProps> = (props) => {
key={i}
ref={(node) => {
if (node) {
colorNodesRef.current[`${name}-${i + 1}`] = node;
colorNodesRef.current[`${name}-${i}`] = node;
}
}}
className={`main-color-item palette-${name}-${i + 1}`}
className={`main-color-item palette-${name}-${i}`}
style={{
color: (name === 'yellow' ? i > 6 : i > 5) ? firstColor : lastColor,
fontWeight: i === 6 ? 'bold' : 'normal',

View File

@@ -3,7 +3,7 @@ import { EditOutlined } from '@ant-design/icons';
import { Tooltip } from 'antd';
import { createStyles } from 'antd-style';
const branchUrl = 'https://github.com/ant-design/ant-design/edit/5.x-stable/';
const branchUrl = 'https://github.com/ant-design/ant-design/edit/master/';
export interface EditButtonProps {
title: React.ReactNode;

View File

@@ -16,7 +16,6 @@ export interface SemanticPreviewInjectionProps {
const useStyle = createStyles(({ token }) => ({
container: css`
position: relative;
z-index: 0;
`,
colWrap: css`
border-inline-end: 1px solid ${token.colorBorderSecondary};

View File

@@ -11,17 +11,17 @@ import type { MenuProps } from 'antd';
import { CompactTheme, DarkTheme } from 'antd-token-previewer/es/icons';
import { FormattedMessage, useLocation } from 'dumi';
import useLocalStorage from '../../../hooks/useLocalStorage';
import useThemeAnimation from '../../../hooks/useThemeAnimation';
import type { SiteContextProps } from '../../slots/SiteContext';
import SiteContext from '../../slots/SiteContext';
import { getLocalizedPathname, isZhCN } from '../../utils';
import { getLocalizedPathname, isZhCN, isLocalStorageNameSupported } from '../../utils';
import Link from '../Link';
import ThemeIcon from './ThemeIcon';
export type ThemeName = 'light' | 'dark' | 'auto' | 'compact' | 'motion-off' | 'happy-work';
export const ANT_DESIGN_SITE_THEME = 'ant-design-site-theme';
// 主题持久化存储键名
const ANT_DESIGN_SITE_THEME = 'ant-design-site-theme';
export interface ThemeSwitchProps {
value?: ThemeName[];
@@ -33,10 +33,6 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = () => {
const toggleAnimationTheme = useThemeAnimation();
const lastThemeKey = useRef<string>(theme.includes('dark') ? 'dark' : 'light');
const [, setTheme] = useLocalStorage<ThemeName>(ANT_DESIGN_SITE_THEME, {
defaultValue: undefined,
});
const badge = <Badge color="blue" style={{ marginTop: -1 }} />;
// 主题选项配置
@@ -137,9 +133,14 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = () => {
const filteredTheme = theme.filter((t) => !['light', 'dark', 'auto'].includes(t));
const newTheme = [...filteredTheme, themeKey];
setTheme(themeKey);
updateSiteConfig({
theme: newTheme,
});
updateSiteConfig({ theme: newTheme });
// 持久化到 localStorage
if (isLocalStorageNameSupported()) {
localStorage.setItem(ANT_DESIGN_SITE_THEME, themeKey);
}
} else {
// 其他主题选项是开关式的
const hasTheme = theme.includes(themeKey);

View File

@@ -12,18 +12,15 @@ import { getSandpackCssText } from '@codesandbox/sandpack-react';
import { theme as antdTheme, App } from 'antd';
import type { MappingAlgorithm } from 'antd';
import type { DirectionType, ThemeConfig } from 'antd/es/config-provider';
import dayjs from 'dayjs';
import { createSearchParams, useOutlet, useSearchParams, useServerInsertedHTML } from 'dumi';
import { DarkContext } from '../../hooks/useDark';
import useLayoutState from '../../hooks/useLayoutState';
import useLocalStorage from '../../hooks/useLocalStorage';
import { getBannerData } from '../../pages/index/components/util';
import { ANT_DESIGN_SITE_THEME } from '../common/ThemeSwitch';
import type { ThemeName } from '../common/ThemeSwitch';
import SiteThemeProvider from '../SiteThemeProvider';
import type { SiteContextProps } from '../slots/SiteContext';
import SiteContext from '../slots/SiteContext';
import { isLocalStorageNameSupported } from '../utils';
import '@ant-design/v5-patch-for-react-19';
@@ -31,9 +28,11 @@ type Entries<T> = { [K in keyof T]: [K, T[K]] }[keyof T][];
type SiteState = Partial<Omit<SiteContextProps, 'updateSiteConfig'>>;
const RESPONSIVE_MOBILE = 768;
export const ANT_DESIGN_NOT_SHOW_BANNER = 'ANT_DESIGN_NOT_SHOW_BANNER';
// 主题持久化存储键名
const ANT_DESIGN_SITE_THEME = 'ant-design-site-theme';
// Compatible with old anchors
if (typeof window !== 'undefined') {
const hashId = location.hash.slice(1);
@@ -44,13 +43,9 @@ if (typeof window !== 'undefined') {
}
}
const getAlgorithm = (themes: ThemeName[] = [], systemTheme: 'dark' | 'light') =>
const getAlgorithm = (themes: ThemeName[] = []) =>
themes
.map((theme) => {
// auto 模式下根据系统主题切换
if (theme === 'auto' && systemTheme === 'dark') {
return antdTheme.darkAlgorithm;
}
if (theme === 'dark') {
return antdTheme.darkAlgorithm;
}
@@ -61,11 +56,21 @@ const getAlgorithm = (themes: ThemeName[] = [], systemTheme: 'dark' | 'light') =
})
.filter(Boolean);
const getSystemTheme = (): 'light' | 'dark' => {
if (typeof window === 'undefined') {
return 'light';
// 获取最终主题优先级URL Query > Local Storage > Site (Memory)
const getFinalTheme = (urlTheme: ThemeName[]): ThemeName[] => {
// 只认 light/dark
const baseTheme = urlTheme.filter((t) => !['light', 'dark', 'auto'].includes(t));
const urlColor = urlTheme.find((t) => t === 'light' || t === 'dark');
if (urlColor) return [...baseTheme, urlColor];
if (isLocalStorageNameSupported()) {
const stored = localStorage.getItem(ANT_DESIGN_SITE_THEME) as ThemeName;
if (stored && ['light', 'dark', 'auto'].includes(stored)) {
return [...baseTheme, stored];
}
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
// 默认 auto
return [...baseTheme, 'auto'];
};
const GlobalLayout: React.FC = () => {
@@ -79,32 +84,6 @@ const GlobalLayout: React.FC = () => {
bannerVisible: false,
});
const [storedTheme] = useLocalStorage<ThemeName>(ANT_DESIGN_SITE_THEME, {
defaultValue: undefined,
});
const [bannerLastTime] = useLocalStorage<string>(ANT_DESIGN_NOT_SHOW_BANNER, {
defaultValue: undefined,
});
// 获取最终主题优先级URL Query > Local Storage > Site (Memory)
const getFinalTheme = (urlTheme: ThemeName[]): ThemeName[] => {
// 只认 light/dark
const baseTheme = urlTheme.filter((t) => !['light', 'dark', 'auto'].includes(t));
const urlColor = urlTheme.find((t) => t === 'light' || t === 'dark');
if (urlColor) {
return [...baseTheme, urlColor];
}
if (['light', 'dark', 'auto'].includes(storedTheme)) {
return [...baseTheme, storedTheme];
}
return [...baseTheme, 'auto'];
};
const [systemTheme, setSystemTheme] = React.useState<'light' | 'dark'>(() => getSystemTheme());
const bannerData = getBannerData();
// TODO: This can be remove in v6
const useCssVar = searchParams.get('cssVar') !== 'false';
@@ -132,6 +111,10 @@ const GlobalLayout: React.FC = () => {
} else {
nextSearchParams.delete('theme');
}
// 设置 data-prefers-color
if (color) {
document.querySelector('html')?.setAttribute('data-prefers-color', color);
}
}
});
@@ -139,6 +122,7 @@ const GlobalLayout: React.FC = () => {
setSearchParams(nextSearchParams);
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[searchParams, setSearchParams],
);
@@ -146,17 +130,6 @@ const GlobalLayout: React.FC = () => {
updateSiteConfig({ isMobile: window.innerWidth < RESPONSIVE_MOBILE });
}, [updateSiteConfig]);
// 设置 data-prefers-color 属性
useEffect(() => {
const color = theme.find((t) => t === 'light' || t === 'dark');
const html = document.querySelector<HTMLHtmlElement>('html');
if (theme.includes('auto') && systemTheme) {
html?.setAttribute('data-prefers-color', systemTheme);
} else if (color) {
html?.setAttribute('data-prefers-color', color);
}
}, [systemTheme, theme]);
// 监听系统主题变化
useEffect(() => {
if (typeof window === 'undefined') {
@@ -165,10 +138,7 @@ const GlobalLayout: React.FC = () => {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleSystemThemeChange = (e: MediaQueryListEvent) => {
const newSystemTheme = e.matches ? 'dark' : 'light';
setSystemTheme(newSystemTheme);
};
const handleSystemThemeChange = () => {};
mediaQuery.addEventListener('change', handleSystemThemeChange);
@@ -183,18 +153,17 @@ const GlobalLayout: React.FC = () => {
const finalTheme = getFinalTheme(urlTheme);
const _direction = searchParams.get('direction') as DirectionType;
const storedBannerVisible = bannerLastTime && dayjs().diff(dayjs(bannerLastTime), 'day') >= 1;
const isZhCN = typeof window !== 'undefined' && window.location.pathname.includes('-cn');
const hasBannerContent = isZhCN && !!bannerData;
setSiteState({
theme: finalTheme,
direction: _direction === 'rtl' ? 'rtl' : 'ltr',
bannerVisible: hasBannerContent && (bannerLastTime ? !!storedBannerVisible : true),
});
// 设置 data-prefers-color 属性
const colorTheme = finalTheme.find((t) => ['light', 'dark'].includes(t));
if (colorTheme) {
document.documentElement.setAttribute('data-prefers-color', colorTheme);
}
// Handle isMobile
updateMobileMode();
@@ -208,6 +177,7 @@ const GlobalLayout: React.FC = () => {
return () => {
window.removeEventListener('resize', updateMobileMode);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchParams, updateMobileMode]);
const siteContextValue = React.useMemo<SiteContextProps>(
@@ -225,12 +195,12 @@ const GlobalLayout: React.FC = () => {
// 算法优先级auto 时用系统主题算法
const themeForAlgorithm = theme;
return {
algorithm: getAlgorithm(themeForAlgorithm, systemTheme),
algorithm: getAlgorithm(themeForAlgorithm),
token: { motion: !theme.includes('motion-off') },
cssVar: useCssVar,
hashed: !useCssVar,
};
}, [theme, useCssVar, systemTheme]);
}, [theme, useCssVar]);
const styleCache = React.useMemo(() => createCache(), []);
@@ -269,9 +239,7 @@ const GlobalLayout: React.FC = () => {
));
return (
<DarkContext
value={theme.includes('dark') || (theme.includes('auto') && systemTheme === 'dark')}
>
<DarkContext value={theme.includes('dark')}>
<StyleProvider
cache={styleCache}
linters={[legacyNotSelectorLinter, parentSelectorLinter, NaNLinter]}

View File

@@ -157,18 +157,7 @@ const RoutesPlugin = async (api: IApi) => {
api.modifyRoutes((routes) => {
// TODO: append extra routes, such as home, changelog, form-v3
/**
* **important!** Make sure that the `id` and `path` are consistent.
* see: https://github.com/ant-design/ant-design/issues/55960
*/
const extraRoutesList: IRoute[] = [
{
id: 'changelog',
path: 'changelog',
absPath: '/changelog',
parentId: 'DocLayout',
file: resolve('../../CHANGELOG.en-US.md'),
},
{
id: 'changelog-cn',
path: 'changelog-cn',
@@ -177,18 +166,25 @@ const RoutesPlugin = async (api: IApi) => {
file: resolve('../../CHANGELOG.zh-CN.md'),
},
{
id: 'components/changelog',
path: 'components/changelog',
absPath: '/components/changelog',
id: 'components-changelog-cn',
path: 'components/changelog-cn',
absPath: '/changelog-cn',
parentId: 'DocLayout',
file: resolve('../../CHANGELOG.zh-CN.md'),
},
{
id: 'changelog',
path: 'changelog',
absPath: '/changelog',
parentId: 'DocLayout',
file: resolve('../../CHANGELOG.en-US.md'),
},
{
id: 'components/changelog-cn',
path: 'components/changelog-cn',
absPath: '/components/changelog-cn',
id: 'components-changelog',
path: 'components/changelog',
absPath: '/changelog',
parentId: 'DocLayout',
file: resolve('../../CHANGELOG.zh-CN.md'),
file: resolve('../../CHANGELOG.en-US.md'),
},
];

View File

@@ -40,10 +40,12 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
useLayoutEffect(() => {
setShowDebug(process.env.NODE_ENV === 'development' || isDebugDemo);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isDebugDemo]);
const contextValue = useMemo<DemoContextProps>(
() => ({ showDebug, setShowDebug, codeType, setCodeType }),
// eslint-disable-next-line react-hooks/exhaustive-deps
[showDebug, codeType],
);

View File

@@ -8,8 +8,6 @@ import { useLocation, useSiteData } from 'dumi';
import DumiSearchBar from 'dumi/theme-default/slots/SearchBar';
import useLocale from '../../../hooks/useLocale';
import useLocalStorage from '../../../hooks/useLocalStorage';
import { getBannerData } from '../../../pages/index/components/util';
import ThemeSwitch from '../../common/ThemeSwitch';
import DirectionIcon from '../../icons/DirectionIcon';
import { ANT_DESIGN_NOT_SHOW_BANNER } from '../../layouts/GlobalLayout';
@@ -24,7 +22,20 @@ import SwitchBtn from './SwitchBtn';
const RESPONSIVE_XS = 1120;
const RESPONSIVE_SM = 1200;
export const ANT_LOCAL_TYPE_KEY = 'ANT_LOCAL_TYPE_KEY';
const locales = {
cn: {
message: '语雀征文 · 说说你和开源的故事,赢取 Ant Design 精美周边 🎁',
shortMessage: '语雀征文 · 说说你和开源的故事,赢取 Ant Design 精美周边 🎁',
more: '前往了解',
link: 'https://www.yuque.com/opensource2023',
},
en: {
message: '',
shortMessage: '',
more: '',
link: '',
},
};
const useStyle = createStyles(({ token, css }) => {
const searchIconColor = '#ced4d9';
@@ -151,12 +162,11 @@ interface HeaderState {
// ================================= Header =================================
const Header: React.FC = () => {
const [, lang] = useLocale();
const [locale, lang] = useLocale(locales);
const { pkg } = useSiteData();
const themeConfig = getThemeConfig();
const [headerState, setHeaderState] = useState<HeaderState>({
menuVisible: false,
windowWidth: 1400,
@@ -169,33 +179,24 @@ const Header: React.FC = () => {
const { styles } = useStyle();
const [, setTopBannerDay] = useLocalStorage<string>(ANT_DESIGN_NOT_SHOW_BANNER, {
defaultValue: undefined,
});
const [, setLocalType] = useLocalStorage<string>(ANT_LOCAL_TYPE_KEY, {
defaultValue: undefined,
});
const handleHideMenu = useCallback(() => {
setHeaderState((prev) => ({ ...prev, menuVisible: false }));
}, []);
const onWindowResize = useCallback(() => {
setHeaderState((prev) => ({ ...prev, windowWidth: window.innerWidth }));
}, []);
const onMenuVisibleChange = useCallback((visible: boolean) => {
setHeaderState((prev) => ({ ...prev, menuVisible: visible }));
}, []);
const onDirectionChange = () => {
updateSiteConfig({ direction: direction !== 'rtl' ? 'rtl' : 'ltr' });
};
const onBannerClose = () => {
updateSiteConfig({ bannerVisible: false });
setTopBannerDay(dayjs().toISOString());
if (utils.isLocalStorageNameSupported()) {
localStorage.setItem(ANT_DESIGN_NOT_SHOW_BANNER, dayjs().toISOString());
}
};
useEffect(() => {
@@ -237,8 +238,9 @@ const Header: React.FC = () => {
const currentProtocol = `${window.location.protocol}//`;
const currentHref = window.location.href.slice(currentProtocol.length);
setLocalType(utils.isZhCN(pathname) ? 'en-US' : 'zh-CN');
if (utils.isLocalStorageNameSupported()) {
localStorage.setItem('locale', utils.isZhCN(pathname) ? 'en-US' : 'zh-CN');
}
window.location.href =
currentProtocol +
currentHref.replace(
@@ -259,7 +261,6 @@ const Header: React.FC = () => {
const { menuVisible, windowWidth, searching } = headerState;
const docVersions: Record<string, string> = {
...themeConfig?.docNewVersions,
[pkg.version]: pkg.version,
...themeConfig?.docVersions,
};
@@ -271,12 +272,6 @@ const Header: React.FC = () => {
const isHome = ['', 'index', 'index-cn'].includes(pathname);
const isZhCN = lang === 'cn';
const isRTL = direction === 'rtl';
// Get banner data from site config
const bannerData = getBannerData();
const bannerTitle = bannerData?.title || '';
const bannerHref = bannerData?.href || '';
let responsive: null | 'narrow' | 'crowded' = null;
if (windowWidth < RESPONSIVE_XS) {
responsive = 'crowded';
@@ -380,7 +375,7 @@ const Header: React.FC = () => {
<MenuOutlined className="nav-phone-icon" />
</Popover>
)}
{isZhCN && bannerVisible && bannerTitle && bannerHref && (
{isZhCN && bannerVisible && (
<ConfigProvider
theme={{
token: {
@@ -392,25 +387,23 @@ const Header: React.FC = () => {
<Alert
className={styles.banner}
message={
bannerTitle && bannerHref ? (
<>
<span>{bannerTitle}</span>
<a
className={styles.link}
href={bannerHref}
target="_blank"
rel="noreferrer"
onClick={() => {
window.gtag?.('event', '点击', {
event_category: 'top_banner',
event_label: bannerHref,
});
}}
>
</a>
</>
) : null
<>
<span>{isMobile ? locale.shortMessage : locale.message}</span>
<a
className={styles.link}
href={locale.link}
target="_blank"
rel="noreferrer"
onClick={() => {
window.gtag?.('event', '点击', {
event_category: 'top_banner',
event_label: locale.link,
});
}}
>
{locale.more}
</a>
</>
}
type="info"
banner

View File

@@ -2,7 +2,6 @@ import * as React from 'react';
import type { DirectionType } from 'antd/es/config-provider';
import type { ThemeName } from '../common/ThemeSwitch';
import { getBannerData } from '../../pages/index/components/util';
export interface SiteContextProps {
isMobile: boolean;
@@ -14,7 +13,7 @@ export interface SiteContextProps {
const SiteContext = React.createContext<SiteContextProps>({
isMobile: false,
bannerVisible: !!getBannerData(),
bannerVisible: false,
direction: 'ltr',
theme: ['light'],
updateSiteConfig: () => {},

View File

@@ -55,7 +55,4 @@ export default {
'0.10.x': 'https://010x.ant.design',
'0.9.x': 'https://09x.ant.design',
},
docNewVersions: {
'6.x': chineseMirror ? 'https://ant-design.antgroup.com' : 'https://ant.design',
},
};

View File

@@ -1,7 +1,6 @@
import semver from 'semver';
import flatten from 'lodash/flatten';
import flattenDeep from 'lodash/flattenDeep';
import semver from 'semver';
import deprecatedVersions from '../../../BUG_VERSIONS.json';
import themeConfig from '../themeConfig';
@@ -158,6 +157,19 @@ export function getLocalizedPathname(
return { pathname: fullPath, search };
}
export function isLocalStorageNameSupported() {
const testKey = 'test';
const storage = window.localStorage;
try {
storage.setItem(testKey, '1');
storage.removeItem(testKey);
return true;
} catch (error) {
console.error('Your web browser does not support storing settings locally.', error);
return false;
}
}
export function loadScript(src: string) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
@@ -165,7 +177,7 @@ export function loadScript(src: string) {
script.src = src;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
document.head!.appendChild(script);
});
}

View File

@@ -131,6 +131,17 @@ export default defineConfig({
headScripts: [
`
(function () {
function isLocalStorageNameSupported() {
const testKey = 'test';
const storage = window.localStorage;
try {
storage.setItem(testKey, '1');
storage.removeItem(testKey);
return true;
} catch (error) {
return false;
}
}
// 优先级提高到所有静态资源的前面,语言不对,加载其他静态资源没意义
const pathname = location.pathname;
@@ -160,7 +171,7 @@ export default defineConfig({
}
// 首页无视链接里面的语言设置 https://github.com/ant-design/ant-design/issues/4552
if (pathname === '/' || pathname === '/index-cn') {
if (isLocalStorageNameSupported() && (pathname === '/' || pathname === '/index-cn')) {
const lang =
(window.localStorage && localStorage.getItem('locale')) ||
((navigator.language || navigator.browserLanguage).toLowerCase() === 'zh-cn'

View File

@@ -39,9 +39,7 @@ jobs:
const now = new Date();
for (const issue of issues) {
if (issue.pull_request) {
continue;
}
if (issue.pull_request) continue;
const updatedAt = new Date(issue.updated_at);
const daysInactive = (now - updatedAt) / (1000 * 60 * 60 * 24);

View File

@@ -41,9 +41,7 @@ jobs:
}, {});
const total = Object.keys(jobs).length;
if (total === 0) {
core.setFailed('no jobs found');
}
if(total === 0) core.setFailed('no jobs found');
// the name here must be the same as `jobs.xxx.{name}` in preview-build.yml
// set output

View File

@@ -25,9 +25,9 @@ jobs:
with:
trigger: tag
changelogs: 'CHANGELOG.en-US.md, CHANGELOG.zh-CN.md'
branch: 5.x-stable
tag: '5*'
latest: '-1'
branch: 'master, 4.x-stable'
tag: '5*, 4*'
latest: '5*'
dingding-token: ${{ secrets.DINGDING_BOT_TOKEN }} ${{ secrets.DINGDING_BOT_COLLABORATOR_TOKEN }} ${{ secrets.DINGDING_BOT_MAINTAINER_TOKEN }}
dingding-msg: CHANGELOG.zh-CN.md
msg-title: '# Ant Design {{v}} 发布日志'
@@ -41,14 +41,14 @@ jobs:
with:
trigger: tag
changelogs: 'CHANGELOG.en-US.md, CHANGELOG.zh-CN.md'
branch: 5.x-stable
tag: '5*'
latest: '-1'
branch: 'master, 4.x-stable'
tag: '5*, 4*'
latest: '5*'
dingding-token: ${{ secrets.DINGDING_BOT_BIGFISH_TOKEN }} ${{ secrets.DINGDING_BOT_BIGFISH_2_TOKEN }} ${{ secrets.DINGDING_BOT_YUNFENGDIE_TOKEN }}
dingding-msg: CHANGELOG.zh-CN.md
dingding-delay-minute: 10
release: false
conch-tag: conch-v5
conch-tag: 'conch-v5, conch'
antd-conch-msg: 🐟 当前 Bigfish 内嵌 antd 版本:
msg-title: '# Ant Design {{v}} 发布日志'
msg-poster: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zx7LTI_ECSAAAAAAAAAAAABkARQnAQ'

View File

@@ -63,11 +63,28 @@ jobs:
- uses: oven-sh/setup-bun@v2
- name: download site artifact
uses: actions/download-artifact@v6
uses: actions/download-artifact@v5
with:
name: real-site
path: _site
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./_site
exclude_files: ./_site/report.html # 👈 这个功能是 beta, 但即便不排除,也不 care
force_orphan: true
# Since force_orphan will not trigger Sync to Gitee, we need to force run it here
- name: Sync to Gitee
uses: wearerequired/git-mirror-action@v1
env:
SSH_PRIVATE_KEY: ${{ secrets.GITEE_SSH_PRIVATE_KEY }}
with:
source-repo: 'git@github.com:ant-design/ant-design.git'
destination-repo: 'git@gitee.com:ant-design/ant-design.git'
- name: Deploy to Surge (with TAG)
run: |
export DEPLOY_DOMAIN=ant-design-${{ needs.build-site.outputs.formatted_version }}.surge.sh
@@ -88,7 +105,7 @@ jobs:
needs: build-site
steps:
- name: download site artifact
uses: actions/download-artifact@v6
uses: actions/download-artifact@v5
with:
name: real-site
path: _site
@@ -100,7 +117,7 @@ jobs:
cd ..
- name: Upload to Release
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
with:
fail_on_unmatched_files: true
files: website.tar.gz

View File

@@ -9,7 +9,6 @@ on:
- 2.x-stable
- 3.x-stable
- 4.x-stable
- 5.x-stable
create:
workflow_dispatch:

233
.github/workflows/test-v6.yml vendored Normal file
View File

@@ -0,0 +1,233 @@
# Origin Source
# https://github.com/ant-design/ant-design/blob/79f566b7f8abb1012ef55b0d2793bfdf5595b85d/.github/workflows/test.yml
name: ✅ test v6
on:
push:
branches: [next]
pull_request:
branches: [next]
# Cancel prev CI if new commit come
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bun run lint
################################ Test ################################
test-react-legacy:
name: test-react-legacy
strategy:
matrix:
react: ['18']
shard: [1/2, 2/2]
env:
REACT: ${{ matrix.react }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: oven-sh/setup-bun@v2
- run: bun install
- name: install react 18
if: ${{ matrix.react == '18' }}
run: bun run bun-install-react-18
# dom test
- name: dom test
run: bun run test -- --maxWorkers=2 --shard=${{matrix.shard}}
test-node:
name: test-node
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bun run test:node
test-react-latest:
name: test-react-latest
strategy:
matrix:
module: [dom]
shard: [1/2, 2/2]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: oven-sh/setup-bun@v2
- run: bun install
# dom test
- name: dom test
run: bun run test -- --maxWorkers=2 --shard=${{matrix.shard}} --coverage
- name: persist coverages
run: |
mkdir persist-coverage
mv coverage/coverage-final.json persist-coverage/react-test-${{matrix.module}}-${{strategy.job-index}}.json
- uses: actions/upload-artifact@v4
name: upload coverages
with:
name: coverage-artifacts-${{ matrix.module }}-${{ strategy.job-index }}
path: persist-coverage/
test-react-latest-dist:
name: test-react-latest-dist
strategy:
matrix:
module: [dist, dist-min]
shard: [1/2, 2/2]
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v5
- uses: oven-sh/setup-bun@v2
- run: bun install
- name: restore cache from dist
uses: actions/cache@v4
with:
path: dist
key: dist-${{ github.sha }}
- name: dist-min test
if: ${{ matrix.module == 'dist-min' }}
run: bun run test
env:
LIB_DIR: dist-min
- name: dist test
if: ${{ matrix.module == 'dist' }}
run: bun run test
env:
LIB_DIR: dist
############################ Test Coverage ###########################
upload-test-coverage:
name: test-coverage
runs-on: ubuntu-latest
needs: test-react-latest
steps:
- uses: actions/checkout@v5
- uses: oven-sh/setup-bun@v2
- run: bun install
- uses: actions/download-artifact@v5
with:
pattern: coverage-artifacts-*
merge-multiple: true
path: persist-coverage
- name: Merge Code Coverage
run: |
bunx nyc merge persist-coverage/ coverage/coverage-final.json
bunx nyc report --reporter text -t coverage --report-dir coverage
rm -rf persist-coverage
- name: Upload coverage to codecov
uses: codecov/codecov-action@v5
with:
# use own token to upload coverage reports
token: ${{ secrets.CODECOV_TOKEN }}
########################### Compile & Test ###########################
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: oven-sh/setup-bun@v2
- run: bun install
- name: cache lib
uses: actions/cache@v4
with:
path: lib
key: lib-${{ github.sha }}
- name: cache es
uses: actions/cache@v4
with:
path: es
key: es-${{ github.sha }}
- name: compile
run: bun run compile
- name: cache dist
uses: actions/cache@v4
with:
path: dist
key: dist-${{ github.sha }}
- name: dist
run: bun run dist
env:
NODE_OPTIONS: --max_old_space_size=4096
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
CI: 1
- name: check build files
run: bun run test:dekko
# Artifact build files
- uses: actions/upload-artifact@v4
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
with:
name: build artifacts
path: |
dist
locale
es
lib
- name: zip builds
if: github.repository == 'ant-design/ant-design' && github.event_name == 'push' && github.ref == 'refs/heads/master'
env:
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}
HEAD_SHA: ${{ github.sha }}
run: |
zip -r oss-artifacts.zip dist locale es lib
echo "🤖 Uploading"
node scripts/visual-regression/upload.js ./oss-artifacts.zip --ref=$HEAD_SHA
test-lib-es:
name: test lib/es module
runs-on: ubuntu-latest
strategy:
matrix:
module: [lib, es]
shard: [1/2, 2/2]
steps:
- uses: actions/checkout@v5
- uses: oven-sh/setup-bun@v2
- run: bun install
- name: restore cache from ${{ matrix.module }}
# lib only run in master branch not in pull request
if: ${{ github.event_name != 'pull_request' || matrix.module != 'lib' }}
uses: actions/cache@v4
with:
path: ${{ matrix.module }}
key: ${{ matrix.module }}-${{ github.sha }}
- name: compile
# lib only run in master branch not in pull request
if: ${{ github.event_name != 'pull_request' || matrix.module != 'lib' }}
run: bun run compile
- name: test
# lib only run in master branch not in pull request
if: ${{ github.event_name != 'pull_request' || matrix.module != 'lib' }}
run: bun run test -- --maxWorkers=2 --shard=${{matrix.shard}}
env:
LIB_DIR: ${{ matrix.module }}

View File

@@ -4,9 +4,9 @@ name: ✅ test
on:
push:
branches: [master, feature, 5.x-stable]
branches: [master, feature]
pull_request:
branches: [master, feature, 5.x-stable]
branches: [master, feature]
# Cancel prev CI if new commit come
concurrency:
@@ -126,7 +126,7 @@ jobs:
- uses: oven-sh/setup-bun@v2
- run: bun install
- uses: actions/download-artifact@v6
- uses: actions/download-artifact@v5
with:
pattern: coverage-artifacts-*
merge-multiple: true
@@ -183,7 +183,7 @@ jobs:
# Artifact build files
- uses: actions/upload-artifact@v4
if: github.event_name == 'push' && github.ref == 'refs/heads/5.x-stable'
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
with:
name: build artifacts
path: |
@@ -193,7 +193,7 @@ jobs:
lib
- name: zip builds
if: github.repository == 'ant-design/ant-design' && github.event_name == 'push' && github.ref == 'refs/heads/5.x-stable'
if: github.repository == 'ant-design/ant-design' && github.event_name == 'push' && github.ref == 'refs/heads/master'
env:
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}

View File

@@ -4,7 +4,7 @@ name: 👀 Visual Regression Diff Build
on:
pull_request:
branches: [master, feature, next, 5.x-stable]
branches: [master, feature, next]
types: [opened, synchronize, reopened]
# Cancel prev CI if new commit come
@@ -54,7 +54,7 @@ jobs:
- uses: oven-sh/setup-bun@v2
- run: bun install
- uses: actions/download-artifact@v6
- uses: actions/download-artifact@v5
with:
pattern: snapshot-artifacts-*
merge-multiple: true

View File

@@ -43,9 +43,7 @@ jobs:
}, {});
const total = Object.keys(jobs).length;
if (total === 0) {
core.setFailed('no jobs found');
}
if(total === 0) core.setFailed('no jobs found');
// the name here must be the same as `jobs.xxx.{name}`
console.log('visual-diff report job status: %s', jobs['visual-diff report'].status);

View File

@@ -8,7 +8,7 @@ name: 👀 Visual Regression Diff Start
on:
pull_request_target:
branches: [master, feature, next, 5.x-stable]
branches: [master, feature, next]
types: [opened, synchronize, reopened]
permissions:

View File

@@ -40,9 +40,7 @@ jobs:
}, {});
const total = Object.keys(jobs).length;
if (total === 0) {
core.setFailed('no jobs found');
}
if(total === 0) core.setFailed('no jobs found');
// the name here must be the same as `jobs.xxx.{name}`
console.log('visual-diff report job status: %s', jobs['test image']);
@@ -89,7 +87,7 @@ jobs:
path: ./tmp
- name: Persist Image Snapshot to OSS
if: github.repository == 'ant-design/ant-design' && github.event.workflow_run.event == 'push' && (github.event.workflow_run.head_branch == 'master' || github.event.workflow_run.head_branch == 'feature' || github.event.workflow_run.head_branch == 'next' || github.event.workflow_run.head_branch == '5.x-stable')
if: github.repository == 'ant-design/ant-design' && github.event.workflow_run.event == 'push' && (github.event.workflow_run.head_branch == 'master' || github.event.workflow_run.head_branch == 'feature' || github.event.workflow_run.head_branch == 'next')
env:
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}

View File

@@ -8,7 +8,6 @@ on:
- master
- feature
- next
- 5.x-stable
permissions:
contents: read

View File

@@ -77,6 +77,5 @@
],
"5.22.6": ["https://github.com/ant-design/ant-design/issues/52124"],
"5.24.8": ["https://github.com/ant-design/ant-design/issues/53652"],
"5.25.0": ["https://github.com/ant-design/ant-design/issues/53764"],
">= 5.28.1 <= 5.29.0": ["https://github.com/ant-design/ant-design/issues/55755"]
"5.25.0": ["https://github.com/ant-design/ant-design/issues/53764"]
}

View File

@@ -15,87 +15,6 @@ tag: vVERSION
---
## 5.29.3
`2025-12-18`
- 🐞 Fix Breadcrumb link color being overridden when using custom `itemRender`. [#56251](https://github.com/ant-design/ant-design/pull/56251) [@guoyunhe](https://github.com/guoyunhe)
## 5.29.2
`2025-12-15`
- 🐞 Fix notification background colors incorrect when `cssVar` is disabled. [#56133](https://github.com/ant-design/ant-design/pull/56133) [@afc163](https://github.com/afc163)
- 🐞 Raise Breadcrumb link style priority to avoid being overridden by global styles (v5). [#56139](https://github.com/ant-design/ant-design/pull/56139) [@guoyunhe](https://github.com/guoyunhe)
- 🐞 Fix Input.Search should not warn about deprecated `addonAfter`. [#55806](https://github.com/ant-design/ant-design/pull/55806) [@zombieJ](https://github.com/zombieJ)
- 🐞 Fix Splitter failing to fill its container when the sum of panel proportions is not 1. [#56217](https://github.com/ant-design/ant-design/pull/56217) [@zombieJ](https://github.com/zombieJ)
## 5.29.1
`2025-11-18`
- 🐞 Fix Carousel dot can not click when in vertical mode.[#55757](https://github.com/ant-design/ant-design/pull/55757) [@wanpan11](https://github.com/wanpan11)
## 5.29.0
`2025-11-17`
- 🆕 InputNumber component deprecates `addonAfter` and `addonBefore` props, use Space.Compact instead. [#55505](https://github.com/ant-design/ant-design/pull/55505) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- ⌨️ Improve Drawer accessibility by adding `aria-labelledby` when a title is present. [#55697](https://github.com/ant-design/ant-design/pull/55697) [@rxy001](https://github.com/rxy001)
- 🌐 Fixed spacing in Korean localization for “복사됨” message. [#55672](https://github.com/ant-design/ant-design/pull/55672) [@rapsealk](https://github.com/rapsealk)
## 5.28.1
`2025-11-11`
- Carousel
- 🐞 Fix Carousel style issue in vertical mode. [#55615](https://github.com/ant-design/ant-design/pull/55615) [@wanpan11](https://github.com/wanpan11)
- 🐞 Fix Carousel dots animation missing when first render. [#55589](https://github.com/ant-design/ant-design/pull/55589) [@wanpan11](https://github.com/wanpan11)
- 🐞 Fix Descriptions where content style wrongly used `labelStyle`. [#55572](https://github.com/ant-design/ant-design/pull/55572) [@li-jia-nan](https://github.com/li-jia-nan)
- 💄 Adjust the height of the Select component to 32px when `variant="underlined"`. [#55607](https://github.com/ant-design/ant-design/pull/55607) [@ustcfury](https://github.com/ustcfury)
- 💄 When the `underlined` property is enabled for the Input component, the border color changes on mouse hover. [#55609](https://github.com/ant-design/ant-design/pull/55609) [@ustcfury](https://github.com/ustcfury)
- 🌐 Add missing TimePicker translations for locales: ar_EG, en_GB, gl_ES, bg_BG, ca_ES, cs_CZ, el_GR, es_ES, eu_ES, fi_FI, he_IL, hu_HU, is_IS, kn_IN, kmr_IQ, lv_LV, mk_MK, mn_MN, ms_MY, pl_PL, pt_BR, pt_PT, ro_RO, sk_SK, sl_SI, sv_SE, ta_IN, th_TH, zh_TW, et_EE. [#55656](https://github.com/ant-design/ant-design/pull/55656) [@li-jia-nan](https://github.com/li-jia-nan)
- TypeScript
- 🤖 Improve Flex component `gap` prop typing, for better IDE autocomplete and type inference. [#55591](https://github.com/ant-design/ant-design/pull/55591) [@ayangweb](https://github.com/ayangweb)
## 5.28.0
`2025-11-01`
- 🆕 Drawer supports `closable.placement` prop to specify the position of the close button. [#54067](https://github.com/ant-design/ant-design/pull/54067) [@davidhsing](https://github.com/davidhsing)
- 🆕 Image component supports `fallback` global configuration. [#54702](https://github.com/ant-design/ant-design/pull/54702) [@Jiyur](https://github.com/Jiyur)
- 🆕 QRCode component supports `boostLevel` prop. [#55063](https://github.com/ant-design/ant-design/pull/55063) [@li-jia-nan](https://github.com/li-jia-nan)
- 🆕 Splitter supports `onCollapse` prop. [#54673](https://github.com/ant-design/ant-design/pull/54673) [@ug-hero](https://github.com/ug-hero)
- 🆕 Statistic displays animation effect by default when set to `loading`. [#55398](https://github.com/ant-design/ant-design/pull/55398) [@afc163](https://github.com/afc163)
- 🆕 TreeSelect supports global configuration for switcher icon. [#54821](https://github.com/ant-design/ant-design/pull/54821) [@Jiyur](https://github.com/Jiyur)
- Segmented
- 💄 Segmented theme variable `itemSelectedBg` supports background gradient. [#55391](https://github.com/ant-design/ant-design/pull/55391) [@zancheng](https://github.com/zancheng)
- 🐞 Fix Segmented abnormal animation after React DevTools upgrade. [#55438](https://github.com/ant-design/ant-design/pull/55438) [@afc163](https://github.com/afc163)
- 🐞 Fix Tree and Transfer components `disabled` inheritance issue. [#54831](https://github.com/ant-design/ant-design/pull/54831) [@cactuser-Lu](https://github.com/cactuser-Lu)
- 🐞 Fix Tree.DirectoryTree `defaultExpandAll` not working when `fieldNames` is defined. [#55420](https://github.com/ant-design/ant-design/pull/55420) [@Wxh16144](https://github.com/Wxh16144)
- Upload
- 🆕 Upload component adds `info.defaultRequest` in `customRequest` parameters. [#55146](https://github.com/ant-design/ant-design/pull/55146) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 💄 Upload component supports `pictureCardSize` token. [#54756](https://github.com/ant-design/ant-design/pull/54756) [@wanpan11](https://github.com/wanpan11)
- 💄 Notification supports configuring background color token. [#54802](https://github.com/ant-design/ant-design/pull/54802) [@thinkasany](https://github.com/thinkasany)
- 💄 Pagination supports modifying the text color of active items through `itemActiveColor` and `itemActiveColorHover` tokens. [#55195](https://github.com/ant-design/ant-design/pull/55195) [@Renderz](https://github.com/Renderz)
- 🐞 Fix Select, DatePicker, TreeSelect, Cascader and other components not showing default suffix icon when `suffixIcon` is configured as undefined. [#54790](https://github.com/ant-design/ant-design/pull/54790) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🐞 Fix Mentions component not inheriting `disabled` from external Form. [#54829](https://github.com/ant-design/ant-design/pull/54829) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🐞 Fix Watermark component crashing when wrapping Modal with `modalRender`. [#55435](https://github.com/ant-design/ant-design/pull/55435) [@ug-hero](https://github.com/ug-hero)
- 🗑 Input component deprecates `addonAfter` and `addonBefore` props, use Space.Compact instead. [#55315](https://github.com/ant-design/ant-design/pull/55315) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🤖 Row component `gutter` prop supports string type definition. [#54628](https://github.com/ant-design/ant-design/pull/54628) [@ug-hero](https://github.com/ug-hero)
## 5.27.6
`2025-10-20`
- 🐞 Fix Table `pagination.align` is not working. [#55316](https://github.com/ant-design/ant-design/pull/55316)
- 🛠 Refactor Modal useMemo of ConfirmDialog to resolve useMemo invalid where Object.values generates a new array. [#55376](https://github.com/ant-design/ant-design/pull/55376)
- TypeScript
- 🤖 Add ConfigProvider the `Window` type definition in `getTargetContainer` of . [#55313](https://github.com/ant-design/ant-design/pull/55313)
- 🤖 Add ConfigProvider the `ShadowRoot` type definition in `getTargetContainer` and `getPopupContainer`. [#55278](https://github.com/ant-design/ant-design/pull/55278) [@leshalv](https://github.com/leshalv)
- 🤖 Improve Modal type definition. [#55371](https://github.com/ant-design/ant-design/pull/55371)
## 5.27.5
`2025-10-14`

View File

@@ -15,86 +15,6 @@ tag: vVERSION
---
## 5.29.3
`2025-12-18`
- 🐞 修复 Breadcrumb 自定义 `itemRender` 时链接颜色被覆盖的问题。[#56251](https://github.com/ant-design/ant-design/pull/56251) [@guoyunhe](https://github.com/guoyunhe)
## 5.29.2
`2025-12-15`
- 🐞 修复关闭 `cssVar` 时 notification 背景色异常的问题。[#56133](https://github.com/ant-design/ant-design/pull/56133) [@afc163](https://github.com/afc163)
- 🐞 提升 Breadcrumb 链接样式的优先级以避免被全局样式覆盖。[#56139](https://github.com/ant-design/ant-design/pull/56139) [@guoyunhe](https://github.com/guoyunhe)
- 🐞 修复 Input.Search 会报 `addonAfter` 已经废弃的警告信息的问题。[#55806](https://github.com/ant-design/ant-design/pull/55806) [@zombieJ](https://github.com/zombieJ)
- 🐞 修复 Splitter 在 Panel 总占比不为 1 时出现占不满的情况。 [#56217](https://github.com/ant-design/ant-design/pull/56217) [@zombieJ](https://github.com/zombieJ)
## 5.29.1
`2025-11-18`
- 🐞 修复 Carousel 选择器在垂直位置无法点击的问题。 [#55757](https://github.com/ant-design/ant-design/pull/55757) [@wanpan11](https://github.com/wanpan11)
## 5.29.0
`2025-11-17`
- 🆕 InputNumber 组件废弃 `addonAfter``addonBefore` 属性,使用 Space.Compact 替换。 [#55505](https://github.com/ant-design/ant-design/pull/55505) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- ⌨️ 优化 Drawer 组件的可访问性,存在标题时的属性 `aria-labelledby`。[#55697](https://github.com/ant-design/ant-design/pull/55697) [@rxy001](https://github.com/rxy001)
- 🌐 修复韩语本地化中“복사됨”文本的空格规则问题。[#55672](https://github.com/ant-design/ant-design/pull/55672) [@rapsealk](https://github.com/rapsealk)
## 5.28.1
`2025-11-11`
- Carousel
- 🐞 修复 Carousel 组件纵向样式问题。[#55615](https://github.com/ant-design/ant-design/pull/55615) [@wanpan11](https://github.com/wanpan11)
- 🐞 修复 Carousel 首次渲染时指示点动画丢失。[#55589](https://github.com/ant-design/ant-design/pull/55589) [@wanpan11](https://github.com/wanpan11)
- 🐞 修复 Descriptions 组件内容样式错误使用 `labelStyle` 的问题。[#55572](https://github.com/ant-design/ant-design/pull/55572) [@li-jia-nan](https://github.com/li-jia-nan)
- 💄 修正 `underlined` 变体的 Select 组件高度为 32px。[#55607](https://github.com/ant-design/ant-design/pull/55607) [@ustcfury](https://github.com/ustcfury)
- 💄 为 `underlined` 变体的 Input 组件补全 hover 边框颜色样式。[#55609](https://github.com/ant-design/ant-design/pull/55609) [@ustcfury](https://github.com/ustcfury)
- 🌐 补充 TimePicker 多语言翻译覆盖以下语言ar_EG、en_GB、gl_ES、bg_BG、ca_ES、cs_CZ、el_GR、es_ES、eu_ES、fi_FI、he_IL、hu_HU、is_IS、kn_IN、kmr_IQ、lv_LV、mk_MK、mn_MN、ms_MY、pl_PL、pt_BR、pt_PT、ro_RO、sk_SK、sl_SI、sv_SE、ta_IN、th_TH、zh_TW、et_EE。[#55656](https://github.com/ant-design/ant-design/pull/55656) [@li-jia-nan](https://github.com/li-jia-nan)
- TypeScript
- 🤖 优化 Flex 组件 `gap` 属性类型定义,支持更友好的 IDE 类型提示 [#55591](https://github.com/ant-design/ant-design/pull/55591) [@ayangweb](https://github.com/ayangweb)
## 5.28.0
`2025-11-01`
- 🆕 Drawer 支持 `closable.placement` 属性,用于指定关闭按钮的位置。[#54067](https://github.com/ant-design/ant-design/pull/54067) [@davidhsing](https://github.com/davidhsing)
- 🆕 Image 组件支持 `fallback` 全局配置。[#54702](https://github.com/ant-design/ant-design/pull/54702) [@Jiyur](https://github.com/Jiyur)
- 🆕 QRCode 组件支持 `boostLevel` 属性。[#55063](https://github.com/ant-design/ant-design/pull/55063) [@li-jia-nan](https://github.com/li-jia-nan)
- 🆕 Splitter 支持 `onCollapse` 属性。[#54673](https://github.com/ant-design/ant-design/pull/54673) [@ug-hero](https://github.com/ug-hero)
- 🆕 Statistic 设置为 `loading` 时默认展现动画效果。[#55398](https://github.com/ant-design/ant-design/pull/55398) [@afc163](https://github.com/afc163)
- 🆕 TreeSelect 支持切换器图标的全局配置。[#54821](https://github.com/ant-design/ant-design/pull/54821) [@Jiyur](https://github.com/Jiyur)
- Segmented
- 💄 Segmented 的主题变量 `itemSelectedBg` 支持背景渐变。[#55391](https://github.com/ant-design/ant-design/pull/55391) [@zancheng](https://github.com/zancheng)
- 🐞 修复 Segmented 切换动画总是从第一项移动闪烁的问题。[#55438](https://github.com/ant-design/ant-design/pull/55438) [@afc163](https://github.com/afc163)
- 🐞 修复 Tree 和 Transfer 组件的 `disabled` 继承问题。[#54831](https://github.com/ant-design/ant-design/pull/54831) [@cactuser-Lu](https://github.com/cactuser-Lu)
- 🐞 修复 Tree.DirectoryTree 定义 `fieldNames``defaultExpandAll` 不生效的问题。[#55420](https://github.com/ant-design/ant-design/pull/55420) [@Wxh16144](https://github.com/Wxh16144)
- Upload
- 🆕 Upload 组件 `customRequest` 参数中增加 `info.defaultRequest`。[#55146](https://github.com/ant-design/ant-design/pull/55146) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 💄 Upload 组件支持 `pictureCardSize` token。[#54756](https://github.com/ant-design/ant-design/pull/54756) [@wanpan11](https://github.com/wanpan11)
- 💄 Notification 支持配置背景颜色的 token。[#54802](https://github.com/ant-design/ant-design/pull/54802) [@thinkasany](https://github.com/thinkasany)
- 💄 Pagination 支持通过 `itemActiveColor``itemActiveColorHover` token 修改高亮项的文字颜色。[#55195](https://github.com/ant-design/ant-design/pull/55195) [@Renderz](https://github.com/Renderz)
- 🐞 修复 Select、DatePicker、TreeSelect、Cascader 等组件 `suffixIcon` 配置值为 undefined 时没有默认后缀图标的问题。[#54790](https://github.com/ant-design/ant-design/pull/54790) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🐞 修复 Mentions 组件没有继承外部 Form 的 `disabled` 的问题。[#54829](https://github.com/ant-design/ant-design/pull/54829) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🐞 修复 Watermark 组件内包裹 Modal 使用 `modalRender` 会导致崩溃的问题。[#55435](https://github.com/ant-design/ant-design/pull/55435) [@ug-hero](https://github.com/ug-hero)
- 🗑 Input 组件废弃 `addonAfter``addonBefore` 属性,使用 Space.Compact 替换。[#55315](https://github.com/ant-design/ant-design/pull/55315) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🤖 Row 组件 `gutter` 属性支持 string 类型定义。[#54628](https://github.com/ant-design/ant-design/pull/54628) [@ug-hero](https://github.com/ug-hero)
## 5.27.6
`2025-10-20`
- 🐞 修复 Table `pagination.align` 属性失效的问题。[#55316](https://github.com/ant-design/ant-design/pull/55316)
- 🛠 重构 Modal 中 ConfirmDialog 的 useMemo以解决 Object.values 生成新数组导致 useMemo 失效的问题。[#55376](https://github.com/ant-design/ant-design/pull/55376)
- TypeScript
- 🤖 补充 ConfigProvider `getTargetContainer``Window` 类型定义。[#55313](https://github.com/ant-design/ant-design/pull/55313)
- 🤖 补充 ConfigProvider 的 `getTargetContainer``getPopupContainer``ShadowRoot` 类型定义。[#55278](https://github.com/ant-design/ant-design/pull/55278) [@leshalv](https://github.com/leshalv)
- 🤖 优化 Modal 中类型定义。[#55371](https://github.com/ant-design/ant-design/pull/55371)
## 5.27.5
`2025-10-14`
@@ -116,7 +36,7 @@ tag: vVERSION
- 🐞 修复 Table 在使 `sticky` 表头或设置 `scroll.y` 时,筛选下拉与 Tooltip 重复显示的问题。[#54910](https://github.com/ant-design/ant-design/pull/54910) [@afc163](https://github.com/afc163)
- 🐞 修复 Table 表头在首次加载时未正确渲染的问题。[#54910](https://github.com/ant-design/ant-design/pull/54910) [@afc163](https://github.com/afc163)
- 🐞 修复 Table 在启用 `scroll.x` 时,固定列的对齐问题。[#54899](https://github.com/ant-design/ant-design/pull/54899) [@afc163](https://github.com/afc163)
- 🐞 修复 Button 仅图标icon-only按钮的内边距受主题影响的问题。[#54970](https://github.com/ant-design/ant-design/pull/54970) [@guoyunhe](https://github.com/guoyunhe)
- 🐞 修复 Button 仅图标icon-only按钮的内边距受主题影响的问题。 [#54970](https://github.com/ant-design/ant-design/pull/54970) [@guoyunhe](https://github.com/guoyunhe)
- 🐞 修复 Splitter 在非受控模式下初次挂载时,`minSize``maxSize` 未生效的问题。[#54939](https://github.com/ant-design/ant-design/pull/54939) [@zombieJ](https://github.com/zombieJ)
- 🐞 修复 Switch 波纹效果与 Tailwind CSS disabled 变体的兼容性问题。[#54933](https://github.com/ant-design/ant-design/pull/54933) [@Jiyur](https://github.com/Jiyur)
- 🐞 修复 Input.Search 在搜索按钮为 `disabled` 时,悬停仍会导致边框和图标变色的问题。[#54892](https://github.com/ant-design/ant-design/pull/54892) [@Jiyur](https://github.com/Jiyur)

View File

@@ -26,13 +26,13 @@
[download-url]: https://npmjs.org/package/antd
[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield
[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield
[help-wanted-image]: https://img.shields.io/github/issues/ant-design/ant-design/help%20wanted?color=green&style=flat-square
[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open
[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22
[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design
[twitter-url]: https://twitter.com/AntDesignUI
[jsdelivr-image]: https://data.jsdelivr.com/v1/package/npm/antd/badge
[jsdelivr-url]: https://www.jsdelivr.com/package/npm/antd
[bundlephobia-image]: https://img.shields.io/bundlephobia/minzip/antd
[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square
[bundlephobia-url]: https://bundlephobia.com/package/antd
[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
[dumi-url]: https://github.com/umijs/dumi

View File

@@ -26,13 +26,13 @@ An enterprise-class UI design language and React UI library.
[download-url]: https://npmjs.org/package/antd
[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield
[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield
[help-wanted-image]: https://img.shields.io/github/issues/ant-design/ant-design/help%20wanted?color=green&style=flat-square
[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open
[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22
[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design
[twitter-url]: https://twitter.com/AntDesignUI
[jsdelivr-image]: https://data.jsdelivr.com/v1/package/npm/antd/badge
[jsdelivr-url]: https://www.jsdelivr.com/package/npm/antd
[bundlephobia-image]: https://img.shields.io/bundlephobia/minzip/antd?style=flat-square
[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square
[bundlephobia-url]: https://bundlephobia.com/package/antd
[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
[dumi-url]: https://github.com/umijs/dumi

View File

@@ -15,8 +15,7 @@
"!scripts/previewEditor/**/*",
"!**/*.tmp",
"!package.json",
"!components/style/antd.css",
"!scripts/visual-regression/report-template.html"
"!components/style/antd.css"
]
},
"formatter": {
@@ -58,7 +57,6 @@
"noExplicitAny": "off",
"noArrayIndexKey": "off",
"noConfusingVoidType": "off",
"noNonNullAssertedOptionalChain": "off",
"noThenProperty": "off",
"noTemplateCurlyInString": "off",
"useIterableCallbackReturn": "off",

View File

@@ -67,7 +67,7 @@ const genPurePanel = <ComponentProps extends BaseProps = BaseProps>(
resizeObserver.disconnect();
};
}
}, [prefixCls]);
}, []);
let mergedProps: WrapProps = {
...props,

View File

@@ -2,8 +2,8 @@ import React, { useEffect } from 'react';
import { CloseOutlined } from '@ant-design/icons';
import { render } from '@testing-library/react';
import { useClosable } from '../hooks';
import type { UseClosableParams } from '../hooks/useClosable';
import useClosable from '../hooks/useClosable';
type ParamsOfUseClosable = [
closable: UseClosableParams['closable'],

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { fireEvent, render } from '../../../tests/utils';
import { useSyncState } from '../hooks';
import useSyncState from '../hooks/useSyncState';
describe('Table', () => {
it('useSyncState', () => {

View File

@@ -0,0 +1,56 @@
import React from 'react';
import { act, render } from '../../../tests/utils';
import useUniqueMemo from '../hooks/useUniqueMemo';
describe('Table', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.clearAllTimers();
jest.useRealTimers();
});
it('useSyncState', () => {
const sharedObjDeps1 = {};
const sharedObjDeps2 = {};
let calledTimes = 0;
const Test: React.FC<{ depName?: string }> = ({ depName }) => {
useUniqueMemo(() => {
calledTimes += 1;
return depName;
}, [depName, sharedObjDeps1, 'bamboo', sharedObjDeps2]);
return null;
};
// Reuse the same memo
const { rerender } = render(
<>
<Test depName="light" />
<Test depName="light" />
<Test depName="light" />
</>,
);
expect(calledTimes).toBe(1);
// Different deps should clean up the cache
act(() => {
jest.advanceTimersByTime(1000 * 60 * 20);
});
for (let i = 0; i < 20000; i += 1) {
rerender(<Test depName="diff" key={i} />);
}
rerender(<Test depName="clear" />);
calledTimes = 0;
// Back should recompute
rerender(<Test depName="light" />);
expect(calledTimes).toBe(1);
});
});

View File

@@ -300,7 +300,7 @@ describe('Test useZIndex hooks', () => {
if (['SelectLike', 'DatePicker', 'ImagePreview'].includes(key)) {
let comps = document.querySelectorAll<HTMLElement>(selector1);
comps.forEach((comp) => {
expect(comp).toHaveStyle({ zIndex: '' });
expect(comp?.style.zIndex).toBeFalsy();
});
comps = document.querySelectorAll<HTMLElement>(selector2);
comps.forEach((comp) => {
@@ -311,9 +311,9 @@ describe('Test useZIndex hooks', () => {
const operOffset = comp.classList.contains('ant-image-preview-operations-wrapper')
? 1
: 0;
expect(comp).toHaveStyle({
zIndex: 1000 + containerZIndexValue + consumerOffset + operOffset,
});
expect(comp?.style.zIndex).toBe(
String(1000 + containerZIndexValue + consumerOffset + operOffset),
);
});
comps = document.querySelectorAll<HTMLElement>(selector3);
@@ -325,21 +325,21 @@ describe('Test useZIndex hooks', () => {
const operOffset = comp.classList.contains('ant-image-preview-operations-wrapper')
? 1
: 0;
expect(comp).toHaveStyle({
zIndex: 1000 + containerZIndexValue * 2 + consumerOffset + operOffset,
});
expect(comp?.style.zIndex).toBe(
String(1000 + containerZIndexValue * 2 + consumerOffset + operOffset),
);
});
} else {
const element1 = document.querySelector<HTMLElement>(selector1);
const element2 = document.querySelector<HTMLElement>(selector2);
const element3 = document.querySelector<HTMLElement>(selector3);
expect(element1).toHaveStyle({ zIndex: key === 'Tour' ? 1001 : '' });
expect(element2).toHaveStyle({
zIndex: 1000 + containerZIndexValue + consumerZIndexValue,
});
expect(element3).toHaveStyle({
zIndex: 1000 + containerZIndexValue * 2 + consumerZIndexValue,
});
expect(element1?.style.zIndex).toBe(key === 'Tour' ? '1001' : '');
expect(element2?.style.zIndex).toBe(
String(1000 + containerZIndexValue + consumerZIndexValue),
);
expect(element3?.style.zIndex).toBe(
String(1000 + containerZIndexValue * 2 + consumerZIndexValue),
);
}
unmount();
}, 20000);
@@ -399,14 +399,16 @@ describe('Test useZIndex hooks', () => {
<FloatButton />
</WrapWithProvider>,
);
const ele = container.querySelector<HTMLElement>('.ant-float-btn');
expect(ele).toHaveStyle({ zIndex: 1100 + containerBaseZIndexOffset.FloatButton });
expect(container.querySelector<HTMLElement>('.ant-float-btn')?.style.zIndex).toBe(
// parentZIndex + containerBaseZIndexOffset["FloatButton"]
String(1100 + containerBaseZIndexOffset.FloatButton),
);
rerender(
<WrapWithProvider container="FloatButton">
<FloatButton style={{ zIndex: 666 }} />
</WrapWithProvider>,
);
expect(ele).toHaveStyle({ zIndex: 666 });
expect(container.querySelector<HTMLElement>('.ant-float-btn')?.style.zIndex).toBe(String(666));
});
it('not warning for static func', () => {

View File

@@ -1,8 +0,0 @@
export * from './useClosable';
export * from './useForceUpdate';
export * from './useMergeSemantic';
export * from './useMultipleSelect';
export * from './usePatchElement';
export * from './useProxyImperativeHandle';
export * from './useSyncState';
export * from './useZIndex';

View File

@@ -56,7 +56,10 @@ function useClosableConfig(closableCollection?: ClosableCollection | null) {
closeIcon: typeof closeIcon !== 'boolean' && closeIcon !== null ? closeIcon : undefined,
};
if (closable && typeof closable === 'object') {
closableConfig = { ...closableConfig, ...closable };
closableConfig = {
...closableConfig,
...closable,
};
}
return closableConfig;
}, [closable, closeIcon]);
@@ -79,7 +82,7 @@ interface FallbackCloseCollection extends ClosableCollection {
/** Use same object to support `useMemo` optimization */
const EmptyFallbackCloseCollection: FallbackCloseCollection = {};
export const useClosable = (
export default function useClosable(
propCloseCollection?: ClosableCollection,
contextCloseCollection?: ClosableCollection | null,
fallbackCloseCollection: FallbackCloseCollection = EmptyFallbackCloseCollection,
@@ -88,7 +91,7 @@ export const useClosable = (
closeIcon: React.ReactNode,
closeBtnIsDisabled: boolean,
ariaOrDataProps?: HTMLAriaDataAttributes,
] => {
] {
// Align the `props`, `context` `fallback` to config object first
const propCloseConfig = useClosableConfig(propCloseCollection);
const contextCloseConfig = useClosableConfig(contextCloseCollection);
@@ -169,4 +172,4 @@ export const useClosable = (
mergedClosableConfig,
mergedFallbackCloseCollection,
]);
};
}

View File

@@ -1,5 +1,6 @@
import React from 'react';
import * as React from 'react';
export const useForceUpdate = () => {
return React.useReducer((ori) => ori + 1, 0);
};
export default function useForceUpdate() {
const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
return forceUpdate;
}

View File

@@ -1,11 +1,13 @@
import * as React from 'react';
import classnames from 'classnames';
import type { ValidChar } from '../type';
import type { ValidChar } from './interface';
type TemplateSemanticClassNames<T extends string> = Partial<Record<T, string>>;
export type SemanticSchema = { _default?: string } & {
export type SemanticSchema = {
_default?: string;
} & {
[key: `${ValidChar}${string}`]: SemanticSchema;
};
@@ -13,7 +15,7 @@ export type SemanticSchema = { _default?: string } & {
export function mergeClassNames<
T extends string,
SemanticClassNames extends Partial<Record<T, any>> = TemplateSemanticClassNames<T>,
>(schema?: SemanticSchema, ...classNames: (SemanticClassNames | undefined)[]) {
>(schema: SemanticSchema | undefined, ...classNames: (SemanticClassNames | undefined)[]) {
const mergedSchema = schema || {};
return classNames.reduce((acc: any, cur) => {
@@ -29,10 +31,8 @@ export function mergeClassNames<
} else {
// Covert string to object structure
const { _default: defaultField } = keySchema;
if (defaultField) {
acc[key] = acc[key] || {};
acc[key][defaultField] = classnames(acc[key][defaultField], curVal);
}
acc[key] = acc[key] || {};
acc[key][defaultField!] = classnames(acc[key][defaultField!], curVal);
}
} else {
// Flatten fill
@@ -40,16 +40,16 @@ export function mergeClassNames<
}
});
return acc;
}, {} as SemanticClassNames);
}, {} as SemanticClassNames) as SemanticClassNames;
}
function useSemanticClassNames<ClassNamesType extends object>(
schema?: SemanticSchema,
schema: SemanticSchema | undefined,
...classNames: (Partial<ClassNamesType> | undefined)[]
): Partial<ClassNamesType> {
return React.useMemo(
() => mergeClassNames(schema, ...classNames),
[classNames, schema],
[classNames],
) as ClassNamesType;
}
@@ -58,25 +58,31 @@ function useSemanticStyles<StylesType extends object>(
...styles: (Partial<StylesType> | undefined)[]
) {
return React.useMemo(() => {
return styles.reduce<Record<string, React.CSSProperties>>((acc, cur = {}) => {
Object.keys(cur).forEach((key) => {
acc[key] = { ...acc[key], ...(cur as Record<string, React.CSSProperties>)[key] };
});
return acc;
}, {});
return styles.reduce(
(acc, cur = {}) => {
Object.keys(cur).forEach((key) => {
acc[key] = { ...acc[key], ...(cur as Record<string, React.CSSProperties>)[key] };
});
return acc;
},
{} as Record<string, React.CSSProperties>,
);
}, [styles]) as StylesType;
}
// =========================== Export ===========================
function fillObjectBySchema<T extends object>(obj: T, schema: SemanticSchema): T {
const newObj: any = { ...obj };
Object.keys(schema).forEach((key) => {
if (key !== '_default') {
const nestSchema = (schema as any)[key] as SemanticSchema;
const nextValue = newObj[key] || {};
newObj[key] = nestSchema ? fillObjectBySchema(nextValue, nestSchema) : nextValue;
}
});
return newObj;
}
@@ -84,17 +90,18 @@ function fillObjectBySchema<T extends object>(obj: T, schema: SemanticSchema): T
* Merge classNames and styles from multiple sources.
* When `schema` is provided, it will **must** provide the nest object structure.
*/
export const useMergeSemantic = <ClassNamesType extends object, StylesType extends object>(
export default function useMergeSemantic<ClassNamesType extends object, StylesType extends object>(
classNamesList: (ClassNamesType | undefined)[],
stylesList: (StylesType | undefined)[],
schema?: SemanticSchema,
) => {
) {
const mergedClassNames = useSemanticClassNames(schema, ...classNamesList) as ClassNamesType;
const mergedStyles = useSemanticStyles(...stylesList) as StylesType;
return React.useMemo(() => {
return [
fillObjectBySchema(mergedClassNames, schema!) as ClassNamesType,
fillObjectBySchema(mergedStyles, schema!) as StylesType,
] as const;
}, [mergedClassNames, mergedStyles, schema]);
};
}, [mergedClassNames, mergedStyles]);
}

View File

@@ -0,0 +1,27 @@
export type ValidChar =
| 'a'
| 'b'
| 'c'
| 'd'
| 'e'
| 'f'
| 'g'
| 'h'
| 'i'
| 'j'
| 'k'
| 'l'
| 'm'
| 'n'
| 'o'
| 'p'
| 'q'
| 'r'
| 's'
| 't'
| 'u'
| 'v'
| 'w'
| 'x'
| 'y'
| 'z';

View File

@@ -6,7 +6,7 @@ export type PrevSelectedIndex = null | number;
* @title multipleSelect hooks
* @description multipleSelect by hold down shift key
*/
export const useMultipleSelect = <T, K>(getKey: (item: T, index: number, array: T[]) => K) => {
export default function useMultipleSelect<T, K>(getKey: (item: T) => K) {
const [prevSelectedIndex, setPrevSelectedIndex] = useState<PrevSelectedIndex>(null);
const multipleSelect = useCallback(
@@ -16,7 +16,7 @@ export const useMultipleSelect = <T, K>(getKey: (item: T, index: number, array:
// add/delete the selected range
const startIndex = Math.min(configPrevSelectedIndex || 0, currentSelectedIndex);
const endIndex = Math.max(configPrevSelectedIndex || 0, currentSelectedIndex);
const rangeKeys = data.slice(startIndex, endIndex + 1).map<K>(getKey);
const rangeKeys = data.slice(startIndex, endIndex + 1).map((item) => getKey(item));
const shouldSelected = rangeKeys.some((rangeKey) => !selectedKeys.has(rangeKey));
const changedKeys: K[] = [];
@@ -39,5 +39,9 @@ export const useMultipleSelect = <T, K>(getKey: (item: T, index: number, array:
[prevSelectedIndex],
);
return [multipleSelect, setPrevSelectedIndex] as const;
};
const updatePrevSelectedIndex = (val: PrevSelectedIndex) => {
setPrevSelectedIndex(val);
};
return [multipleSelect, updatePrevSelectedIndex] as const;
}

View File

@@ -1,9 +1,9 @@
import * as React from 'react';
export const usePatchElement = (): [
export default function usePatchElement(): [
React.ReactElement[],
(element: React.ReactElement) => () => void,
] => {
] {
const [elements, setElements] = React.useState<React.ReactElement[]>([]);
const patchElement = React.useCallback((element: React.ReactElement) => {
@@ -18,4 +18,4 @@ export const usePatchElement = (): [
}, []);
return [elements, patchElement];
};
}

View File

@@ -22,13 +22,10 @@ function fillProxy(
return element;
}
export const useProxyImperativeHandle = <
export default function useProxyImperativeHandle<
NativeELementType extends HTMLElement,
ReturnRefType extends { nativeElement: NativeELementType },
>(
ref: Ref<any> | undefined,
init: () => ReturnRefType,
) => {
>(ref: Ref<any> | undefined, init: () => ReturnRefType) {
return useImperativeHandle(ref, () => {
const refObj = init();
const { nativeElement } = refObj;
@@ -48,4 +45,4 @@ export const useProxyImperativeHandle = <
// Fallback of IE
return fillProxy(nativeElement, refObj);
});
};
}

View File

@@ -1,12 +1,13 @@
import * as React from 'react';
import { useForceUpdate } from './useForceUpdate';
import useForceUpdate from './useForceUpdate';
type UseSyncStateProps<T> = readonly [() => T, (newValue: T) => void];
export const useSyncState = <T>(initialValue: T): UseSyncStateProps<T> => {
export default function useSyncState<T>(initialValue: T): UseSyncStateProps<T> {
const ref = React.useRef<T>(initialValue);
const [, forceUpdate] = useForceUpdate();
const forceUpdate = useForceUpdate();
return [
() => ref.current,
(newValue: T) => {
@@ -15,4 +16,4 @@ export const useSyncState = <T>(initialValue: T): UseSyncStateProps<T> => {
forceUpdate();
},
] as const;
};
}

View File

@@ -0,0 +1,97 @@
import React from 'react';
const BEAT_LIMIT = 1000 * 60 * 10;
/**
* A helper class to map keys to values.
* It supports both primitive keys and object keys.
*/
class ArrayKeyMap<T> {
map = new Map<string, T>();
// Use WeakMap to avoid memory leak
objectIDMap = new WeakMap<object, number>();
nextID = 0;
lastAccessBeat = new Map<string, number>();
// We will clean up the cache when reach the limit
accessBeat = 0;
set(keys: React.DependencyList, value: any) {
// New set will trigger clear
this.clear();
// Set logic
const compositeKey = this.getCompositeKey(keys);
this.map.set(compositeKey, value);
this.lastAccessBeat.set(compositeKey, Date.now());
}
get(keys: React.DependencyList) {
const compositeKey = this.getCompositeKey(keys);
const cache = this.map.get(compositeKey);
this.lastAccessBeat.set(compositeKey, Date.now());
this.accessBeat += 1;
return cache;
}
getCompositeKey(keys: React.DependencyList) {
const ids = keys.map<string>((key) => {
if (key && typeof key === 'object') {
return `obj_${this.getObjectID(key)}`;
}
return `${typeof key}_${key}`;
});
return ids.join('|');
}
getObjectID(obj: object) {
if (this.objectIDMap.has(obj)) {
return this.objectIDMap.get(obj);
}
const id = this.nextID;
this.objectIDMap.set(obj, id);
this.nextID += 1;
return id;
}
clear() {
if (this.accessBeat > 10000) {
const now = Date.now();
this.lastAccessBeat.forEach((beat, key) => {
if (now - beat > BEAT_LIMIT) {
this.map.delete(key);
this.lastAccessBeat.delete(key);
}
});
this.accessBeat = 0;
}
}
}
const uniqueMap = new ArrayKeyMap();
/**
* Like `useMemo`, but this hook result will be shared across all instances.
*/
function useUniqueMemo<T>(memoFn: () => T, deps: React.DependencyList) {
return React.useMemo<T>(() => {
const cachedValue = uniqueMap.get(deps);
if (cachedValue) {
return cachedValue as T;
}
const newValue = memoFn();
uniqueMap.set(deps, newValue);
return newValue;
}, deps);
}
export default useUniqueMemo;

View File

@@ -140,7 +140,7 @@ const useResponsiveObserver = () => {
subscribers.clear();
},
};
}, [responsiveMap]);
}, [token]);
};
export default useResponsiveObserver;

View File

@@ -1,14 +1,10 @@
import type React from 'react';
export type Primitive = null | undefined | string | number | boolean | symbol | bigint;
/** https://github.com/Microsoft/TypeScript/issues/29729 */
export type LiteralUnion<T, U extends Primitive = string> = T | (U & Record<never, never>);
export type LiteralUnion<T extends string> = T | (string & {});
export type AnyObject = Record<PropertyKey, any>;
export type EmptyObject = Record<never, never>;
export type CustomComponent<P = AnyObject> = React.ComponentType<P> | string;
/**
@@ -82,31 +78,3 @@ export type GetContextProp<
T extends React.Context<any>,
PropName extends keyof GetContextProps<T>,
> = NonNullable<GetContextProps<T>[PropName]>;
export type ValidChar =
| 'a'
| 'b'
| 'c'
| 'd'
| 'e'
| 'f'
| 'g'
| 'h'
| 'i'
| 'j'
| 'k'
| 'l'
| 'm'
| 'n'
| 'o'
| 'p'
| 'q'
| 'r'
| 's'
| 't'
| 'u'
| 'v'
| 'w'
| 'x'
| 'y'
| 'z';

View File

@@ -55,10 +55,7 @@ export interface AffixRef {
updatePosition: ReturnType<typeof throttleByAnimationFrame>;
}
interface InternalAffixProps extends AffixProps {
onTestUpdatePosition?: () => void;
}
type InternalAffixProps = AffixProps & { onTestUpdatePosition?: any };
const Affix = React.forwardRef<AffixRef, InternalAffixProps>((props, ref) => {
const {
style,

View File

@@ -10,7 +10,7 @@ import CSSMotion from 'rc-motion';
import pickAttrs from 'rc-util/lib/pickAttrs';
import { composeRef } from 'rc-util/lib/ref';
import type { ClosableType } from '../_util/hooks';
import type { ClosableType } from '../_util/hooks/useClosable';
import { replaceElement } from '../_util/reactNode';
import { devUseWarning } from '../_util/warning';
import { useComponentConfig } from '../config-provider/context';
@@ -176,9 +176,7 @@ const Alert = React.forwardRef<AlertRef, AlertProps>((props, ref) => {
// closeable when closeText or closeIcon is assigned
const isClosable = React.useMemo<boolean>(() => {
if (typeof closable === 'object' && closable.closeIcon) {
return true;
}
if (typeof closable === 'object' && closable.closeIcon) return true;
if (closeText) {
return true;
}
@@ -228,7 +226,7 @@ const Alert = React.forwardRef<AlertRef, AlertProps>((props, ref) => {
return contextClosable.closeIcon;
}
return contextCloseIcon;
}, [closeIcon, closable, contextClosable, closeText, contextCloseIcon]);
}, [closeIcon, closable, closeText, contextCloseIcon]);
const mergedAriaProps = React.useMemo<React.AriaAttributes>(() => {
const merged = closable ?? contextClosable;

View File

@@ -1,7 +1,7 @@
## zh-CN
友好的 [React 错误处理](https://zh-hans.react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) 包裹组件。
友好的 [React 错误处理](https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html) 包裹组件。
## en-US
ErrorBoundary Component for making error handling easier in [React](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary).
ErrorBoundary Component for making error handling easier in [React](https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html).

View File

@@ -246,7 +246,7 @@ const Anchor: React.FC<AnchorProps> = (props) => {
);
setCurrentActiveLink(currentActiveLink);
}, [links, targetOffset, offsetTop, bounds]);
}, [dependencyListItem, targetOffset, offsetTop]);
const handleScrollTo = React.useCallback<(link: string) => void>(
(link) => {

View File

@@ -185,7 +185,7 @@ describe('Anchor Render', () => {
const link = container.querySelector(`a[href="http://www.example.com/#${hash}"]`)!;
fireEvent.click(link);
await waitFakeTimer();
expect(link).toHaveClass('ant-anchor-link-title-active');
expect(link.classList).toContain('ant-anchor-link-title-active');
});
it('scrolls the page when clicking a link', async () => {
@@ -737,9 +737,11 @@ describe('Anchor Render', () => {
/>,
);
expect(container.querySelectorAll('.ant-anchor-ink').length).toBe(1);
expect(container.querySelector('.ant-anchor-wrapper')).toHaveClass(
'ant-anchor-wrapper-horizontal',
);
expect(
container
.querySelector('.ant-anchor-wrapper')
?.classList.contains('ant-anchor-wrapper-horizontal'),
).toBeTruthy();
});
it('nested children via items should be filtered out when direction is horizontal', () => {
@@ -816,7 +818,7 @@ describe('Anchor Render', () => {
const link = container.querySelector(`a[href="http://www.example.com/#${hash}"]`)!;
fireEvent.click(link);
await waitFakeTimer();
expect(link).toHaveClass('ant-anchor-link-title-active');
expect(link.classList).toContain('ant-anchor-link-title-active');
});
it('scrolls the page when clicking a link', async () => {
@@ -1024,29 +1026,25 @@ describe('Anchor Render', () => {
</div>
);
};
const { container, findByText } = await render(<Foo />);
(await findByText('part-1')).click();
const wrapper = await render(<Foo />);
(await wrapper.findByText('part-1')).click();
await waitFakeTimer();
const inkElement = container.querySelector<HTMLSpanElement>('.ant-anchor-ink');
const toggleButton = container.querySelector<HTMLElement>('button');
const ink = wrapper.container.querySelector<HTMLSpanElement>('.ant-anchor-ink')!;
const toggleButton = wrapper.container.querySelector('button')!;
expect(toggleButton).toBeInTheDocument();
fireEvent.click(toggleButton!);
fireEvent.click(toggleButton);
act(() => jest.runAllTimers());
expect(!!ink.style.left).toBe(true);
expect(!!ink.style.width).toBe(true);
expect(ink.style.top).toBe('');
expect(ink.style.height).toBe('');
expect(inkElement).toHaveStyle({
left: '0px',
width: '0px',
});
fireEvent.click(toggleButton!);
fireEvent.click(toggleButton);
act(() => jest.runAllTimers());
expect(inkElement).toHaveStyle({
top: '0px',
height: '0px',
});
expect(!!ink.style.top).toBe(true);
expect(!!ink.style.height).toBe(true);
expect(ink.style.left).toBe('');
expect(ink.style.width).toBe('');
});
});
});

View File

@@ -4,7 +4,7 @@ import type { BaseSelectRef } from 'rc-select';
import toArray from 'rc-util/lib/Children/toArray';
import omit from 'rc-util/lib/omit';
import { useZIndex } from '../_util/hooks';
import { useZIndex } from '../_util/hooks/useZIndex';
import type { InputStatus } from '../_util/statusUtils';
import { devUseWarning } from '../_util/warning';
import type { ConfigConsumerProps } from '../config-provider';
@@ -24,7 +24,6 @@ export interface DataSourceItemObject {
value: string;
text: string;
}
export type DataSourceItemType = DataSourceItemObject | React.ReactNode;
export interface AutoCompleteProps<

View File

@@ -46,7 +46,8 @@ Common props ref[Common props](/docs/react/common-props)
| allowClear | Show clear button | boolean \| { clearIcon?: ReactNode } | false | 5.8.0: Support Object type |
| autoFocus | If get focus when component mounted | boolean | false | |
| backfill | If backfill selected item the input when using keyboard | boolean | false | |
| children | Customize input element | HTMLInputElement \| HTMLTextAreaElement \| React.ReactElement&lt;InputProps> | &lt;Input /> | |
| children (for customize input element) | Customize input element | HTMLInputElement \| HTMLTextAreaElement \| React.ReactElement&lt;InputProps> | &lt;Input /> | |
| children (for dataSource) | Data source to auto complete | React.ReactElement&lt;OptionProps> \| Array&lt;React.ReactElement&lt;OptionProps>> | - | |
| classNames | Semantic DOM class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.25.0 |
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |
| defaultOpen | Initial open state of dropdown | boolean | - | |

View File

@@ -47,7 +47,8 @@ demo:
| allowClear | 支持清除 | boolean \| { clearIcon?: ReactNode } | false | 5.8.0: 支持对象形式 |
| autoFocus | 自动获取焦点 | boolean | false | |
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
| children | 自定义输入框 | HTMLInputElement \| HTMLTextAreaElement \| React.ReactElement&lt;InputProps> | &lt;Input /> | |
| children (自动完成的数据源) | 自动完成的数据源,不能和自定义输入框同时配置 | React.ReactElement&lt;OptionProps> \| Array&lt;React.ReactElement&lt;OptionProps>> | - | |
| children (自定义输入框) | 自定义输入框,不能和自动完成的数据源同时配置 | HTMLInputElement \| HTMLTextAreaElement \| React.ReactElement&lt;InputProps> | &lt;Input /> | |
| classNames | 语义化结构 class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.25.0 |
| defaultActiveFirstOption | 是否默认高亮第一个选项 | boolean | true | |
| defaultOpen | 是否默认展开下拉菜单 | boolean | - | |

View File

@@ -129,7 +129,7 @@ const Avatar = React.forwardRef<HTMLSpanElement, AvatarProps>((props, ref) => {
fontSize: currentSize && (icon || children) ? currentSize / 2 : 18,
}
: {};
}, [screens, size, icon, children]);
}, [screens, size]);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning('Avatar');
@@ -205,7 +205,11 @@ const Avatar = React.forwardRef<HTMLSpanElement, AvatarProps>((props, ref) => {
childrenToRender = (
<ResizeObserver onResize={setScaleParam}>
<span className={`${prefixCls}-string`} ref={avatarChildrenRef} style={childrenStyle}>
<span
className={`${prefixCls}-string`}
ref={avatarChildrenRef}
style={{ ...childrenStyle }}
>
{children}
</span>
</ResizeObserver>

View File

@@ -146,11 +146,11 @@ describe('Badge', () => {
// https://github.com/ant-design/ant-design/issues/15349
it('should color style works on Badge', () => {
const { container } = render(
<Badge style={{ color: 'rgb(255, 0, 0)' }} status="success" text="Success" />,
<Badge style={{ color: 'red' }} status="success" text="Success" />,
);
expect((container.querySelector('.ant-badge-status-text')! as HTMLElement).style.color).toEqual(
'red',
);
expect(container.querySelector<HTMLElement>('.ant-badge-status-text')).toHaveStyle({
color: 'rgb(255, 0, 0)',
});
});
// https://github.com/ant-design/ant-design/issues/15799
@@ -247,8 +247,14 @@ describe('Badge', () => {
const { container } = render(
<Badge
count={10}
classNames={{ root: 'test-root', indicator: 'test-indicator' }}
styles={{ root: { padding: 10 }, indicator: { padding: 20 } }}
classNames={{
root: 'test-root',
indicator: 'test-indicator',
}}
styles={{
root: { backgroundColor: 'yellow' },
indicator: { backgroundColor: 'blue' },
}}
>
test
</Badge>,
@@ -261,7 +267,9 @@ describe('Badge', () => {
expect(element?.querySelector<HTMLElement>('sup')).toHaveClass('test-indicator');
// styles
expect(element).toHaveStyle({ padding: '10px' });
expect(element?.querySelector<HTMLElement>('sup')).toHaveStyle({ padding: '20px' });
expect(element).toHaveStyle({ backgroundColor: 'rgb(255, 255, 0)' });
expect(element?.querySelector<HTMLElement>('sup')).toHaveStyle({
backgroundColor: 'rgb(0, 0, 255)',
});
});
});

View File

@@ -37,28 +37,28 @@ describe('Ribbon', () => {
expect(container.querySelectorAll('.ant-ribbon-color-green').length).toEqual(1);
});
it('works with custom color', () => {
const { container, rerender } = render(
<Badge.Ribbon color="rgb(136, 136, 136)" placement="start">
const { container: wrapperLeft } = render(
<Badge.Ribbon color="#888" placement="start">
<div />
</Badge.Ribbon>,
);
expect(container.querySelector<HTMLElement>('.ant-ribbon')).toHaveStyle({
backgroundColor: 'rgb(136, 136, 136)',
});
expect(container.querySelector<HTMLElement>('.ant-ribbon-corner')).toHaveStyle({
color: 'rgb(136, 136, 136)',
});
rerender(
<Badge.Ribbon color="rgb(136, 136, 136)" placement="end">
expect((wrapperLeft.querySelector('.ant-ribbon')! as HTMLElement).style.background).toEqual(
'rgb(136, 136, 136)',
);
expect((wrapperLeft.querySelector('.ant-ribbon-corner')! as HTMLElement).style.color).toEqual(
'rgb(136, 136, 136)',
);
const { container: wrapperRight } = render(
<Badge.Ribbon color="#888" placement="end">
<div />
</Badge.Ribbon>,
);
expect(container.querySelector<HTMLElement>('.ant-ribbon')).toHaveStyle({
backgroundColor: 'rgb(136, 136, 136)',
});
expect(container.querySelector<HTMLElement>('.ant-ribbon-corner')).toHaveStyle({
color: 'rgb(136, 136, 136)',
});
expect((wrapperRight.querySelector('.ant-ribbon')! as HTMLElement).style.background).toEqual(
'rgb(136, 136, 136)',
);
expect(
(wrapperRight.querySelector('.ant-ribbon-corner')! as HTMLElement).style.color,
).toEqual('rgb(136, 136, 136)');
});
});

View File

@@ -94,7 +94,7 @@ export const InternalBreadcrumbItem: React.FC<BreadcrumbItemProps> = (props) =>
if (link !== undefined && link !== null) {
return (
<>
<li className={`${prefixCls}-item`}>{link}</li>
<li>{link}</li>
{separator && <BreadcrumbSeparator>{separator}</BreadcrumbSeparator>}
</>
);

View File

@@ -5,9 +5,7 @@ exports[`Breadcrumb filter React.Fragment 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -20,9 +18,7 @@ exports[`Breadcrumb filter React.Fragment 1`] = `
>
:
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -61,9 +57,7 @@ exports[`Breadcrumb should allow Breadcrumb.Item is null or undefined 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -79,9 +73,7 @@ exports[`Breadcrumb should not display Breadcrumb Item when its children is fals
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -94,9 +86,7 @@ exports[`Breadcrumb should not display Breadcrumb Item when its children is fals
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -112,9 +102,7 @@ exports[`Breadcrumb should render a menu 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href="#/index"
@@ -128,9 +116,7 @@ exports[`Breadcrumb should render a menu 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-dropdown-trigger ant-breadcrumb-overlay-link"
>
@@ -167,9 +153,7 @@ exports[`Breadcrumb should render a menu 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href="#/index/first/second"
@@ -183,9 +167,7 @@ exports[`Breadcrumb should render a menu 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href="#/index/first/second/third"
@@ -200,9 +182,7 @@ exports[`Breadcrumb should render correct 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href="#/"
@@ -218,9 +198,7 @@ exports[`Breadcrumb should render correct 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -236,9 +214,7 @@ exports[`Breadcrumb should support Breadcrumb.Item default separator 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -252,9 +228,7 @@ exports[`Breadcrumb should support Breadcrumb.Item default separator 1`] = `
/
</li>
<span>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -268,9 +242,7 @@ exports[`Breadcrumb should support Breadcrumb.Item default separator 1`] = `
/
</li>
</span>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -286,9 +258,7 @@ exports[`Breadcrumb should support React.Fragment and falsy children 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -301,9 +271,7 @@ exports[`Breadcrumb should support React.Fragment and falsy children 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -316,9 +284,7 @@ exports[`Breadcrumb should support React.Fragment and falsy children 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -342,9 +308,7 @@ exports[`Breadcrumb should support custom attribute 1`] = `
data-custom="custom"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
data-custom="custom-item"
@@ -358,9 +322,7 @@ exports[`Breadcrumb should support custom attribute 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -376,9 +338,7 @@ exports[`Breadcrumb should support string \`0\` and number \`0\` 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -391,9 +351,7 @@ exports[`Breadcrumb should support string \`0\` and number \`0\` 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>

View File

@@ -5,9 +5,7 @@ exports[`renders components/breadcrumb/demo/basic.tsx extend context correctly 1
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -20,9 +18,7 @@ exports[`renders components/breadcrumb/demo/basic.tsx extend context correctly 1
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -39,9 +35,7 @@ exports[`renders components/breadcrumb/demo/basic.tsx extend context correctly 1
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -58,9 +52,7 @@ exports[`renders components/breadcrumb/demo/basic.tsx extend context correctly 1
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -78,9 +70,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx extend context c
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -93,9 +83,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx extend context c
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -112,9 +100,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx extend context c
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-dropdown-trigger ant-breadcrumb-overlay-link"
>
@@ -281,9 +267,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx extend context c
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -297,9 +281,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx extend context c
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -331,9 +313,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx extend context c
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -373,9 +353,7 @@ exports[`renders components/breadcrumb/demo/debug-routes.tsx extend context corr
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href="#/home"
@@ -389,9 +367,7 @@ exports[`renders components/breadcrumb/demo/debug-routes.tsx extend context corr
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-dropdown-trigger ant-breadcrumb-overlay-link"
>
@@ -523,9 +499,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -538,9 +512,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -557,9 +529,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-dropdown-trigger ant-breadcrumb-overlay-link"
>
@@ -726,9 +696,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -746,9 +714,7 @@ exports[`renders components/breadcrumb/demo/separator.tsx extend context correct
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -761,9 +727,7 @@ exports[`renders components/breadcrumb/demo/separator.tsx extend context correct
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -777,9 +741,7 @@ exports[`renders components/breadcrumb/demo/separator.tsx extend context correct
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -793,9 +755,7 @@ exports[`renders components/breadcrumb/demo/separator.tsx extend context correct
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -813,9 +773,7 @@ exports[`renders components/breadcrumb/demo/separator-component.tsx extend conte
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -828,9 +786,7 @@ exports[`renders components/breadcrumb/demo/separator-component.tsx extend conte
>
:
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -844,9 +800,7 @@ exports[`renders components/breadcrumb/demo/separator-component.tsx extend conte
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -860,9 +814,7 @@ exports[`renders components/breadcrumb/demo/separator-component.tsx extend conte
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -880,9 +832,7 @@ exports[`renders components/breadcrumb/demo/withIcon.tsx extend context correctl
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -914,9 +864,7 @@ exports[`renders components/breadcrumb/demo/withIcon.tsx extend context correctl
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -951,9 +899,7 @@ exports[`renders components/breadcrumb/demo/withIcon.tsx extend context correctl
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -971,9 +917,7 @@ exports[`renders components/breadcrumb/demo/withParams.tsx extend context correc
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -986,9 +930,7 @@ exports[`renders components/breadcrumb/demo/withParams.tsx extend context correc
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""

View File

@@ -5,9 +5,7 @@ exports[`renders components/breadcrumb/demo/basic.tsx correctly 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -20,9 +18,7 @@ exports[`renders components/breadcrumb/demo/basic.tsx correctly 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -39,9 +35,7 @@ exports[`renders components/breadcrumb/demo/basic.tsx correctly 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -58,9 +52,7 @@ exports[`renders components/breadcrumb/demo/basic.tsx correctly 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -76,9 +68,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx correctly 1`] =
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -91,9 +81,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx correctly 1`] =
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -110,9 +98,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx correctly 1`] =
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-dropdown-trigger ant-breadcrumb-overlay-link"
>
@@ -152,9 +138,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx correctly 1`] =
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -168,9 +152,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx correctly 1`] =
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -202,9 +184,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx correctly 1`] =
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -242,9 +222,7 @@ exports[`renders components/breadcrumb/demo/debug-routes.tsx correctly 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href="#/home"
@@ -258,9 +236,7 @@ exports[`renders components/breadcrumb/demo/debug-routes.tsx correctly 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-dropdown-trigger ant-breadcrumb-overlay-link"
>
@@ -300,9 +276,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx correctly 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -315,9 +289,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx correctly 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -334,9 +306,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx correctly 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-dropdown-trigger ant-breadcrumb-overlay-link"
>
@@ -376,9 +346,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx correctly 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -394,9 +362,7 @@ exports[`renders components/breadcrumb/demo/separator.tsx correctly 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -409,9 +375,7 @@ exports[`renders components/breadcrumb/demo/separator.tsx correctly 1`] = `
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -425,9 +389,7 @@ exports[`renders components/breadcrumb/demo/separator.tsx correctly 1`] = `
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -441,9 +403,7 @@ exports[`renders components/breadcrumb/demo/separator.tsx correctly 1`] = `
>
&gt;
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -459,9 +419,7 @@ exports[`renders components/breadcrumb/demo/separator-component.tsx correctly 1`
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -474,9 +432,7 @@ exports[`renders components/breadcrumb/demo/separator-component.tsx correctly 1`
>
:
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -490,9 +446,7 @@ exports[`renders components/breadcrumb/demo/separator-component.tsx correctly 1`
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -506,9 +460,7 @@ exports[`renders components/breadcrumb/demo/separator-component.tsx correctly 1`
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -524,9 +476,7 @@ exports[`renders components/breadcrumb/demo/withIcon.tsx correctly 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -558,9 +508,7 @@ exports[`renders components/breadcrumb/demo/withIcon.tsx correctly 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""
@@ -595,9 +543,7 @@ exports[`renders components/breadcrumb/demo/withIcon.tsx correctly 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -613,9 +559,7 @@ exports[`renders components/breadcrumb/demo/withParams.tsx correctly 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -628,9 +572,7 @@ exports[`renders components/breadcrumb/demo/withParams.tsx correctly 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href=""

View File

@@ -6,9 +6,7 @@ exports[`Breadcrumb.ItemRender render as expect 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="my-link"
data-path="/"
@@ -22,9 +20,7 @@ exports[`Breadcrumb.ItemRender render as expect 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="my-link"
data-path="/bamboo"

View File

@@ -5,9 +5,7 @@ exports[`react router react router legacy 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href="#/"
@@ -21,9 +19,7 @@ exports[`react router react router legacy 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href="#//apps"
@@ -37,9 +33,7 @@ exports[`react router react router legacy 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href="#//apps/1"
@@ -53,9 +47,7 @@ exports[`react router react router legacy 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<a
class="ant-breadcrumb-link"
href="#//apps/1/detail"

View File

@@ -66,7 +66,7 @@ const genBreadcrumbStyle: GenerateStyle<BreadcrumbToken, CSSObject> = (token) =>
listStyle: 'none',
},
[`${componentCls}-item a`]: {
a: {
color: token.linkColor,
transition: `color ${token.motionDurationMid}`,
padding: `0 ${unit(token.paddingXXS)}`,
@@ -83,7 +83,7 @@ const genBreadcrumbStyle: GenerateStyle<BreadcrumbToken, CSSObject> = (token) =>
...genFocusStyle(token),
},
[`${componentCls}-item:last-child`]: {
'li:last-child': {
color: token.lastItemColor,
},

View File

@@ -1,8 +1,8 @@
import React, { Children, useContext, useEffect, useMemo, useRef, useState } from 'react';
import classNames from 'classnames';
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
import omit from 'rc-util/lib/omit';
import { useComposeRef } from 'rc-util/lib/ref';
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
import { devUseWarning } from '../_util/warning';
import Wave from '../_util/wave';
@@ -154,7 +154,7 @@ const InternalCompoundedButton = React.forwardRef<
}
return ['default', 'outlined'];
}, [color, variant, type, danger, button?.color, button?.variant, mergedType]);
}, [type, color, variant, danger, button?.variant, button?.color]);
const isDanger = mergedColor === 'danger';
const mergedColorText = isDanger ? 'dangerous' : mergedColor;
@@ -335,35 +335,23 @@ const InternalCompoundedButton = React.forwardRef<
...(contextStyles.icon || {}),
};
/**
* Extract icon node
* If there is a custom icon and not in loading state: show custom icon
*/
const iconWrapperElement = (child: React.ReactNode) => (
<IconWrapper prefixCls={prefixCls} className={iconClasses} style={iconStyle}>
{child}
</IconWrapper>
);
const defaultLoadingIconElement = () => (
<DefaultLoadingIcon
existIcon={!!icon}
prefixCls={prefixCls}
loading={innerLoading}
mount={isMountRef.current}
/>
);
/**
* Using if-else statements can improve code readability without affecting future expansion.
*/
let iconNode: React.ReactNode;
if (icon && !innerLoading) {
iconNode = iconWrapperElement(icon);
} else if (loading && typeof loading === 'object' && loading.icon) {
iconNode = iconWrapperElement(loading.icon);
} else {
iconNode = defaultLoadingIconElement();
}
const iconNode =
icon && !innerLoading ? (
<IconWrapper prefixCls={prefixCls} className={iconClasses} style={iconStyle}>
{icon}
</IconWrapper>
) : loading && typeof loading === 'object' && loading.icon ? (
<IconWrapper prefixCls={prefixCls} className={iconClasses} style={iconStyle}>
{loading.icon}
</IconWrapper>
) : (
<DefaultLoadingIcon
existIcon={!!icon}
prefixCls={prefixCls}
loading={innerLoading}
mount={isMountRef.current}
/>
);
const kids =
children || children === 0 ? spaceChildren(children, needInserted && mergedInsertSpace) : null;

View File

@@ -1,5 +1,8 @@
import React from 'react';
import Dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import React from 'react';
import MockDate from 'mockdate';
import type { PickerPanelProps } from 'rc-picker';
import dayjsGenerateConfig from 'rc-picker/lib/generate/dayjs';
@@ -14,12 +17,9 @@ import ConfigProvider from '../../config-provider';
import Group from '../../radio/group';
import Button from '../../radio/radioButton';
import Select from '../../select';
import type { DefaultOptionType } from '../../select';
import Header from '../Header';
import type { CalendarHeaderProps } from '../Header';
import 'dayjs/locale/zh-cn';
const ref: {
calendarProps?: PickerPanelProps;
calendarHeaderProps?: CalendarHeaderProps<unknown>;
@@ -375,10 +375,15 @@ describe('Calendar', () => {
// Year
const headerRender = jest.fn(({ value }) => {
const year = value.year();
const options: DefaultOptionType[] = [];
const options = [];
for (let i = year - 100; i < year + 100; i += 1) {
options.push({ label: i, value: i });
options.push(
<Select.Option className="year-item" key={i} value={i}>
{i}
</Select.Option>,
);
}
return (
<Select
size="small"
@@ -386,8 +391,9 @@ describe('Calendar', () => {
className="my-year-select"
onChange={onYearChange}
value={String(year)}
options={options}
/>
>
{options}
</Select>
);
});
const uiWithYear = <Calendar fullscreen={false} headerRender={headerRender} />;
@@ -406,17 +412,23 @@ describe('Calendar', () => {
const headerRenderWithMonth = jest.fn(({ value }) => {
const start = 0;
const end = 12;
const months: string[] = [];
const monthOptions: DefaultOptionType[] = [];
const monthOptions = [];
const current = value.clone();
const localeData = value.localeData();
const months = [];
for (let i = 0; i < 12; i += 1) {
current.month(i);
months.push(localeData.monthsShort(current));
}
for (let index = start; index < end; index += 1) {
monthOptions.push({ label: months[index], value: index });
monthOptions.push(
<Select.Option className="month-item" key={index} value={index}>
{months[index]}
</Select.Option>,
);
}
const month = value.month();
return (
<Select
@@ -425,8 +437,9 @@ describe('Calendar', () => {
className="my-month-select"
onChange={onMonthChange}
value={String(month)}
options={monthOptions}
/>
>
{monthOptions}
</Select>
);
});
const uiWithMonth = <Calendar fullscreen={false} headerRender={headerRenderWithMonth} />;

View File

@@ -65,12 +65,8 @@ const App: React.FC = () => {
};
const cellRender: CalendarProps<Dayjs>['cellRender'] = (current, info) => {
if (info.type === 'date') {
return dateCellRender(current);
}
if (info.type === 'month') {
return monthCellRender(current);
}
if (info.type === 'date') return dateCellRender(current);
if (info.type === 'month') return monthCellRender(current);
return info.originNode;
};

View File

@@ -327,7 +327,7 @@ exports[`renders components/carousel/demo/autoplay.tsx extend context correctly
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
4
</h3>
@@ -347,7 +347,7 @@ exports[`renders components/carousel/demo/autoplay.tsx extend context correctly
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
1
</h3>
@@ -367,7 +367,7 @@ exports[`renders components/carousel/demo/autoplay.tsx extend context correctly
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
2
</h3>
@@ -387,7 +387,7 @@ exports[`renders components/carousel/demo/autoplay.tsx extend context correctly
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
3
</h3>
@@ -407,7 +407,7 @@ exports[`renders components/carousel/demo/autoplay.tsx extend context correctly
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
4
</h3>
@@ -427,7 +427,7 @@ exports[`renders components/carousel/demo/autoplay.tsx extend context correctly
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
1
</h3>
@@ -447,7 +447,7 @@ exports[`renders components/carousel/demo/autoplay.tsx extend context correctly
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
2
</h3>
@@ -467,7 +467,7 @@ exports[`renders components/carousel/demo/autoplay.tsx extend context correctly
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
3
</h3>
@@ -487,7 +487,7 @@ exports[`renders components/carousel/demo/autoplay.tsx extend context correctly
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
4
</h3>
@@ -1036,7 +1036,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx extend context correc
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
4
</h3>
@@ -1056,7 +1056,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx extend context correc
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
1
</h3>
@@ -1076,7 +1076,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx extend context correc
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
2
</h3>
@@ -1096,7 +1096,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx extend context correc
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
3
</h3>
@@ -1116,7 +1116,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx extend context correc
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
4
</h3>
@@ -1136,7 +1136,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx extend context correc
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
1
</h3>
@@ -1156,7 +1156,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx extend context correc
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
2
</h3>
@@ -1176,7 +1176,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx extend context correc
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
3
</h3>
@@ -1196,7 +1196,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx extend context correc
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
4
</h3>
@@ -1272,7 +1272,7 @@ exports[`renders components/carousel/demo/fade.tsx extend context correctly 1`]
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
1
</h3>
@@ -1292,7 +1292,7 @@ exports[`renders components/carousel/demo/fade.tsx extend context correctly 1`]
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
2
</h3>
@@ -1312,7 +1312,7 @@ exports[`renders components/carousel/demo/fade.tsx extend context correctly 1`]
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
3
</h3>
@@ -1332,7 +1332,7 @@ exports[`renders components/carousel/demo/fade.tsx extend context correctly 1`]
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
4
</h3>
@@ -1503,7 +1503,7 @@ Array [
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
4
</h3>
@@ -1523,7 +1523,7 @@ Array [
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
1
</h3>
@@ -1543,7 +1543,7 @@ Array [
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
2
</h3>
@@ -1563,7 +1563,7 @@ Array [
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
3
</h3>
@@ -1583,7 +1583,7 @@ Array [
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
4
</h3>
@@ -1603,7 +1603,7 @@ Array [
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
1
</h3>
@@ -1623,7 +1623,7 @@ Array [
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
2
</h3>
@@ -1643,7 +1643,7 @@ Array [
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
3
</h3>
@@ -1663,7 +1663,7 @@ Array [
tabindex="-1"
>
<h3
style="margin: 0px; height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
style="height: 160px; color: rgb(255, 255, 255); line-height: 160px; text-align: center; background: rgb(54, 77, 121);"
>
4
</h3>

View File

@@ -324,7 +324,7 @@ exports[`renders components/carousel/demo/autoplay.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
4
</h3>
@@ -344,7 +344,7 @@ exports[`renders components/carousel/demo/autoplay.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
1
</h3>
@@ -364,7 +364,7 @@ exports[`renders components/carousel/demo/autoplay.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
2
</h3>
@@ -384,7 +384,7 @@ exports[`renders components/carousel/demo/autoplay.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
3
</h3>
@@ -404,7 +404,7 @@ exports[`renders components/carousel/demo/autoplay.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
4
</h3>
@@ -424,7 +424,7 @@ exports[`renders components/carousel/demo/autoplay.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
1
</h3>
@@ -444,7 +444,7 @@ exports[`renders components/carousel/demo/autoplay.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
2
</h3>
@@ -464,7 +464,7 @@ exports[`renders components/carousel/demo/autoplay.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
3
</h3>
@@ -484,7 +484,7 @@ exports[`renders components/carousel/demo/autoplay.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
4
</h3>
@@ -1027,7 +1027,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
4
</h3>
@@ -1047,7 +1047,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
1
</h3>
@@ -1067,7 +1067,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
2
</h3>
@@ -1087,7 +1087,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
3
</h3>
@@ -1107,7 +1107,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
4
</h3>
@@ -1127,7 +1127,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
1
</h3>
@@ -1147,7 +1147,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
2
</h3>
@@ -1167,7 +1167,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
3
</h3>
@@ -1187,7 +1187,7 @@ exports[`renders components/carousel/demo/dot-duration.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
4
</h3>
@@ -1261,7 +1261,7 @@ exports[`renders components/carousel/demo/fade.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
1
</h3>
@@ -1281,7 +1281,7 @@ exports[`renders components/carousel/demo/fade.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
2
</h3>
@@ -1301,7 +1301,7 @@ exports[`renders components/carousel/demo/fade.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
3
</h3>
@@ -1321,7 +1321,7 @@ exports[`renders components/carousel/demo/fade.tsx correctly 1`] = `
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
4
</h3>
@@ -1490,7 +1490,7 @@ Array [
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
4
</h3>
@@ -1510,7 +1510,7 @@ Array [
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
1
</h3>
@@ -1530,7 +1530,7 @@ Array [
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
2
</h3>
@@ -1550,7 +1550,7 @@ Array [
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
3
</h3>
@@ -1570,7 +1570,7 @@ Array [
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
4
</h3>
@@ -1590,7 +1590,7 @@ Array [
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
1
</h3>
@@ -1610,7 +1610,7 @@ Array [
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
2
</h3>
@@ -1630,7 +1630,7 @@ Array [
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
3
</h3>
@@ -1650,7 +1650,7 @@ Array [
tabindex="-1"
>
<h3
style="margin:0;height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
style="height:160px;color:#fff;line-height:160px;text-align:center;background:#364d79"
>
4
</h3>

View File

@@ -2,7 +2,6 @@ import React from 'react';
import { Carousel } from 'antd';
const contentStyle: React.CSSProperties = {
margin: 0,
height: '160px',
color: '#fff',
lineHeight: '160px',

View File

@@ -2,7 +2,6 @@ import React from 'react';
import { Carousel } from 'antd';
const contentStyle: React.CSSProperties = {
margin: 0,
height: '160px',
color: '#fff',
lineHeight: '160px',

View File

@@ -2,7 +2,6 @@ import React from 'react';
import { Carousel } from 'antd';
const contentStyle: React.CSSProperties = {
margin: 0,
height: '160px',
color: '#fff',
lineHeight: '160px',

View File

@@ -5,7 +5,6 @@ import { Carousel, Radio } from 'antd';
type DotPosition = CarouselProps['dotPosition'];
const contentStyle: React.CSSProperties = {
margin: 0,
height: '160px',
color: '#fff',
lineHeight: '160px',

View File

@@ -1,4 +1,4 @@
import { Keyframes, unit } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
@@ -230,16 +230,6 @@ const genDotsStyle: GenerateStyle<CarouselToken> = (token) => {
colorBgContainer,
motionDurationSlow,
} = token;
const animation = new Keyframes(`${token.prefixCls}-dot-animation`, {
from: {
width: 0,
},
to: {
width: token.dotActiveWidth,
},
});
return {
[componentCls]: {
'.slick-dots': {
@@ -284,7 +274,7 @@ const genDotsStyle: GenerateStyle<CarouselToken> = (token) => {
position: 'absolute',
top: 0,
insetInlineStart: 0,
width: 0,
width: '100%',
height: dotHeight,
content: '""',
background: 'transparent',
@@ -293,6 +283,7 @@ const genDotsStyle: GenerateStyle<CarouselToken> = (token) => {
outline: 'none',
cursor: 'pointer',
overflow: 'hidden',
transform: 'translate3d(-100%, 0, 0)',
},
button: {
@@ -331,10 +322,8 @@ const genDotsStyle: GenerateStyle<CarouselToken> = (token) => {
},
'&::after': {
background: colorBgContainer,
animationName: animation,
animationDuration: `var(${DotDuration})`,
animationTimingFunction: 'ease-out',
animationFillMode: 'forwards',
transform: 'translate3d(0, 0, 0)',
transition: `transform var(${DotDuration}) ease-out`,
},
},
},
@@ -346,15 +335,6 @@ const genDotsStyle: GenerateStyle<CarouselToken> = (token) => {
const genCarouselVerticalStyle: GenerateStyle<CarouselToken> = (token) => {
const { componentCls, dotOffset, arrowOffset, marginXXS } = token;
const animation = new Keyframes(`${token.prefixCls}-dot-vertical-animation`, {
from: {
height: 0,
},
to: {
height: token.dotActiveWidth,
},
});
const reverseSizeOfDot = {
width: token.dotHeight,
height: token.dotWidth,
@@ -416,19 +396,12 @@ const genCarouselVerticalStyle: GenerateStyle<CarouselToken> = (token) => {
'&.slick-active': {
...reverseSizeOfDot,
height: token.dotActiveWidth,
button: {
...reverseSizeOfDot,
height: token.dotActiveWidth,
},
button: reverseSizeOfDot,
'&::after': {
...reverseSizeOfDot,
animationName: animation,
animationDuration: `var(${DotDuration})`,
animationTimingFunction: 'ease-out',
animationFillMode: 'forwards',
transition: `height var(${DotDuration}) ease-out`,
},
},
},

View File

@@ -558,14 +558,14 @@ describe('Cascader', () => {
resetWarned();
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const { container } = render(<Cascader dropdownStyle={{ padding: 10 }} open />);
const customStyle = { background: 'red' };
const { container } = render(<Cascader dropdownStyle={customStyle} open />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Cascader] `dropdownStyle` is deprecated. Please use `styles.popup.root` instead.',
);
expect(container.querySelector<HTMLElement>('.ant-select-dropdown')).toHaveStyle({
padding: '10px',
});
expect(container.querySelector('.ant-select-dropdown')?.getAttribute('style')).toContain(
'background: red',
);
errSpy.mockRestore();
});
@@ -595,11 +595,11 @@ describe('Cascader', () => {
resetWarned();
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const columnStyle = { background: 'red' };
const { getByRole } = render(
<Cascader
options={[{ label: 'test', value: 1 }]}
dropdownMenuColumnStyle={{ padding: 10 }}
dropdownMenuColumnStyle={columnStyle}
open
/>,
);
@@ -607,7 +607,7 @@ describe('Cascader', () => {
'Warning: [antd: Cascader] `dropdownMenuColumnStyle` is deprecated. Please use `popupMenuColumnStyle` instead.',
);
const menuColumn = getByRole('menuitemcheckbox');
expect(menuColumn).toHaveStyle({ padding: '10px' });
expect(menuColumn.style.background).toBe('red');
errSpy.mockRestore();
});

View File

@@ -11,7 +11,7 @@ import RcCascader from 'rc-cascader';
import type { Placement } from 'rc-select/lib/BaseSelect';
import omit from 'rc-util/lib/omit';
import { useZIndex } from '../_util/hooks';
import { useZIndex } from '../_util/hooks/useZIndex';
import type { SelectCommonPlacement } from '../_util/motion';
import { getTransitionName } from '../_util/motion';
import genPurePanel from '../_util/PurePanel';

View File

@@ -82,12 +82,14 @@ describe('Collapse', () => {
</Collapse.Panel>
</Collapse>,
);
expect(container.querySelector('.ant-collapse-item')).not.toHaveClass(
'ant-collapse-item-active',
);
expect(
container.querySelector('.ant-collapse-item')?.classList.contains('ant-collapse-item-active'),
).toBe(false);
fireEvent.click(container.querySelector('.ant-collapse-header')!);
await waitFakeTimer();
expect(container.querySelector('.ant-collapse-item')).toHaveClass('ant-collapse-item-active');
expect(
container.querySelector('.ant-collapse-item')?.classList.contains('ant-collapse-item-active'),
).toBe(true);
jest.useRealTimers();
});

View File

@@ -3,6 +3,8 @@ import { SettingOutlined } from '@ant-design/icons';
import type { CollapseProps } from 'antd';
import { Collapse, Select } from 'antd';
const { Option } = Select;
const text = `
A dog is a type of domesticated animal.
Known for its loyalty and faithfulness,
@@ -62,15 +64,10 @@ const App: React.FC = () => {
/>
<br />
<span>Expand Icon Position: </span>
<Select
value={expandIconPosition}
style={{ margin: '0 8px' }}
onChange={onPositionChange}
options={[
{ label: 'start', value: 'start' },
{ label: 'end', value: 'end' },
]}
/>
<Select value={expandIconPosition} style={{ margin: '0 8px' }} onChange={onPositionChange}>
<Option value="start">start</Option>
<Option value="end">end</Option>
</Select>
</>
);
};

View File

@@ -4018,7 +4018,6 @@ exports[`renders components/color-picker/demo/line-gradient.tsx extend context c
>
<div
aria-label="segmented control"
aria-orientation="horizontal"
class="ant-segmented ant-segmented-sm"
role="radiogroup"
tabindex="0"
@@ -4036,6 +4035,7 @@ exports[`renders components/color-picker/demo/line-gradient.tsx extend context c
type="radio"
/>
<div
aria-selected="false"
class="ant-segmented-item-label"
title="Single"
>
@@ -4051,6 +4051,7 @@ exports[`renders components/color-picker/demo/line-gradient.tsx extend context c
type="radio"
/>
<div
aria-selected="true"
class="ant-segmented-item-label"
title="Gradient"
>

View File

@@ -205,7 +205,7 @@ describe('ColorPicker', () => {
fireEvent.click(container.querySelector('.ant-color-picker-trigger')!);
await waitFakeTimer();
const presetsColors = container
?.querySelector('.ant-collapse-content')
.querySelector('.ant-collapse-content')
?.querySelectorAll('.ant-color-picker-presets-color')!;
expect(container.querySelector('.ant-color-picker-presets')).toBeTruthy();
@@ -217,7 +217,9 @@ describe('ColorPicker', () => {
).toBeTruthy();
fireEvent.click(presetsColors[0]);
expect(presetsColors[0]).not.toHaveClass('ant-color-picker-presets-color-bright');
expect(
presetsColors[0].classList.contains('ant-color-picker-presets-color-bright'),
).toBeFalsy();
expect(
container.querySelector('.ant-color-picker-hex-input input')?.getAttribute('value'),
).toEqual('000000');
@@ -226,7 +228,9 @@ describe('ColorPicker', () => {
);
fireEvent.click(presetsColors[9]);
expect(presetsColors[9]).toHaveClass('ant-color-picker-presets-color-bright');
expect(
presetsColors[9].classList.contains('ant-color-picker-presets-color-bright'),
).toBeTruthy();
expect(
container.querySelector('.ant-color-picker-hex-input input')?.getAttribute('value'),
).toEqual('000000');

View File

@@ -79,7 +79,7 @@ const ColorTrigger = forwardRef<HTMLDivElement, ColorTriggerProps>((props, ref)
default:
return alpha < 100 ? `${hexString.slice(0, 7)},${alpha}%` : hexString;
}
}, [color, format, showText, activeIndex, locale.transparent, colorTextCellPrefixCls]);
}, [color, format, showText, activeIndex]);
// ============================= Render =============================
const containerNode = useMemo<React.ReactNode>(

View File

@@ -4,7 +4,6 @@ import RcColorPicker from '@rc-component/color-picker';
import type { Color } from '@rc-component/color-picker';
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
import { useForceUpdate } from '../../../_util/hooks';
import Segmented from '../../../segmented';
import { AggregationColor } from '../../color';
import { PanelPickerContext } from '../../context';
@@ -71,7 +70,7 @@ const PanelPicker: FC = () => {
if (!isSingle) {
setLockedColor(colors[activeIndex]?.color);
}
}, [isSingle, colors, gradientDragging, activeIndex]);
}, [gradientDragging, activeIndex]);
const activeColor = React.useMemo(() => {
if (isSingle) {
@@ -84,12 +83,11 @@ const PanelPicker: FC = () => {
}
return colors[activeIndex]?.color;
}, [colors, value, activeIndex, isSingle, lockedColor, gradientDragging]);
}, [value, activeIndex, isSingle, lockedColor, gradientDragging]);
// ========================= Picker Color =========================
const [pickerColor, setPickerColor] = React.useState<AggregationColor | null>(activeColor);
const [forceSync, setForceSync] = useForceUpdate();
const [forceSync, setForceSync] = React.useState(0);
const mergedPickerColor = pickerColor?.equals(activeColor) ? activeColor : pickerColor;
@@ -150,7 +148,7 @@ const PanelPicker: FC = () => {
// Back of origin color in case in controlled
// This will set after `onChangeComplete` to avoid `setState` trigger rerender
// which will make `fillColor` get wrong `color.cleared` state
setForceSync();
setForceSync((ori) => ori + 1);
};
const onInputChange = (colorValue: AggregationColor) => {

View File

@@ -57,7 +57,7 @@ export default function useModeColor(
pushOption('gradient', locale.gradientColor);
return [optionList, modes];
}, [mode, locale.singleColor, locale.gradientColor]);
}, [mode]);
// ======================== Post ========================
// We need align `mode` with `color` state

View File

@@ -1175,9 +1175,7 @@ exports[`ConfigProvider components Breadcrumb configProvider 1`] = `
class="config-breadcrumb"
>
<ol>
<li
class="config-breadcrumb-item"
>
<li>
<span
class="config-breadcrumb-link"
>
@@ -1190,9 +1188,7 @@ exports[`ConfigProvider components Breadcrumb configProvider 1`] = `
>
/
</li>
<li
class="config-breadcrumb-item"
>
<li>
<span
class="config-breadcrumb-link"
>
@@ -1208,9 +1204,7 @@ exports[`ConfigProvider components Breadcrumb configProvider componentDisabled 1
class="config-breadcrumb"
>
<ol>
<li
class="config-breadcrumb-item"
>
<li>
<span
class="config-breadcrumb-link"
>
@@ -1223,9 +1217,7 @@ exports[`ConfigProvider components Breadcrumb configProvider componentDisabled 1
>
/
</li>
<li
class="config-breadcrumb-item"
>
<li>
<span
class="config-breadcrumb-link"
>
@@ -1241,9 +1233,7 @@ exports[`ConfigProvider components Breadcrumb configProvider componentSize large
class="config-breadcrumb"
>
<ol>
<li
class="config-breadcrumb-item"
>
<li>
<span
class="config-breadcrumb-link"
>
@@ -1256,9 +1246,7 @@ exports[`ConfigProvider components Breadcrumb configProvider componentSize large
>
/
</li>
<li
class="config-breadcrumb-item"
>
<li>
<span
class="config-breadcrumb-link"
>
@@ -1274,9 +1262,7 @@ exports[`ConfigProvider components Breadcrumb configProvider componentSize middl
class="config-breadcrumb"
>
<ol>
<li
class="config-breadcrumb-item"
>
<li>
<span
class="config-breadcrumb-link"
>
@@ -1289,9 +1275,7 @@ exports[`ConfigProvider components Breadcrumb configProvider componentSize middl
>
/
</li>
<li
class="config-breadcrumb-item"
>
<li>
<span
class="config-breadcrumb-link"
>
@@ -1307,9 +1291,7 @@ exports[`ConfigProvider components Breadcrumb configProvider componentSize small
class="config-breadcrumb"
>
<ol>
<li
class="config-breadcrumb-item"
>
<li>
<span
class="config-breadcrumb-link"
>
@@ -1322,9 +1304,7 @@ exports[`ConfigProvider components Breadcrumb configProvider componentSize small
>
/
</li>
<li
class="config-breadcrumb-item"
>
<li>
<span
class="config-breadcrumb-link"
>
@@ -1340,9 +1320,7 @@ exports[`ConfigProvider components Breadcrumb normal 1`] = `
class="ant-breadcrumb"
>
<ol>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -1355,9 +1333,7 @@ exports[`ConfigProvider components Breadcrumb normal 1`] = `
>
/
</li>
<li
class="ant-breadcrumb-item"
>
<li>
<span
class="ant-breadcrumb-link"
>
@@ -1373,9 +1349,7 @@ exports[`ConfigProvider components Breadcrumb prefixCls 1`] = `
class="prefix-Breadcrumb"
>
<ol>
<li
class="prefix-Breadcrumb-item"
>
<li>
<span
class="prefix-Breadcrumb-link"
>
@@ -1388,9 +1362,7 @@ exports[`ConfigProvider components Breadcrumb prefixCls 1`] = `
>
/
</li>
<li
class="prefix-Breadcrumb-item"
>
<li>
<span
class="prefix-Breadcrumb-link"
>
@@ -24829,7 +24801,7 @@ exports[`ConfigProvider components Select configProvider 1`] = `
class="config-select-selection-search"
>
<input
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_1"
aria-autocomplete="list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
@@ -24847,11 +24819,8 @@ exports[`ConfigProvider components Select configProvider 1`] = `
/>
</span>
<span
class="config-select-selection-item"
title="Light"
>
Light
</span>
class="config-select-selection-placeholder"
/>
</span>
</div>
<div
@@ -24865,12 +24834,17 @@ exports[`ConfigProvider components Select configProvider 1`] = `
style="height: 0px; width: 0px; overflow: hidden;"
>
<div
aria-label="Light"
aria-selected="true"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_0"
role="presentation"
/>
<div
aria-label="Light"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_1"
role="option"
>
light
Bamboo
</div>
</div>
<div
@@ -24887,8 +24861,14 @@ exports[`ConfigProvider components Select configProvider 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-selected="true"
class="config-select-item config-select-item-option config-select-item-option-active config-select-item-option-selected"
class="config-select-item config-select-item-group"
title="grp"
>
grp
</div>
<div
aria-selected="false"
class="config-select-item config-select-item-option config-select-item-option-grouped config-select-item-option-active"
title="Light"
>
<div
@@ -24970,11 +24950,8 @@ exports[`ConfigProvider components Select configProvider componentDisabled 1`] =
/>
</span>
<span
class="config-select-selection-item"
title="Light"
>
Light
</span>
class="config-select-selection-placeholder"
/>
</span>
</div>
<span
@@ -25020,7 +24997,7 @@ exports[`ConfigProvider components Select configProvider componentSize large 1`]
class="config-select-selection-search"
>
<input
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_1"
aria-autocomplete="list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
@@ -25038,11 +25015,8 @@ exports[`ConfigProvider components Select configProvider componentSize large 1`]
/>
</span>
<span
class="config-select-selection-item"
title="Light"
>
Light
</span>
class="config-select-selection-placeholder"
/>
</span>
</div>
<div
@@ -25056,12 +25030,17 @@ exports[`ConfigProvider components Select configProvider componentSize large 1`]
style="height: 0px; width: 0px; overflow: hidden;"
>
<div
aria-label="Light"
aria-selected="true"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_0"
role="presentation"
/>
<div
aria-label="Light"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_1"
role="option"
>
light
Bamboo
</div>
</div>
<div
@@ -25078,8 +25057,14 @@ exports[`ConfigProvider components Select configProvider componentSize large 1`]
style="display: flex; flex-direction: column;"
>
<div
aria-selected="true"
class="config-select-item config-select-item-option config-select-item-option-active config-select-item-option-selected"
class="config-select-item config-select-item-group"
title="grp"
>
grp
</div>
<div
aria-selected="false"
class="config-select-item config-select-item-option config-select-item-option-grouped config-select-item-option-active"
title="Light"
>
<div
@@ -25143,7 +25128,7 @@ exports[`ConfigProvider components Select configProvider componentSize middle 1`
class="config-select-selection-search"
>
<input
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_1"
aria-autocomplete="list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
@@ -25161,11 +25146,8 @@ exports[`ConfigProvider components Select configProvider componentSize middle 1`
/>
</span>
<span
class="config-select-selection-item"
title="Light"
>
Light
</span>
class="config-select-selection-placeholder"
/>
</span>
</div>
<div
@@ -25179,12 +25161,17 @@ exports[`ConfigProvider components Select configProvider componentSize middle 1`
style="height: 0px; width: 0px; overflow: hidden;"
>
<div
aria-label="Light"
aria-selected="true"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_0"
role="presentation"
/>
<div
aria-label="Light"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_1"
role="option"
>
light
Bamboo
</div>
</div>
<div
@@ -25201,8 +25188,14 @@ exports[`ConfigProvider components Select configProvider componentSize middle 1`
style="display: flex; flex-direction: column;"
>
<div
aria-selected="true"
class="config-select-item config-select-item-option config-select-item-option-active config-select-item-option-selected"
class="config-select-item config-select-item-group"
title="grp"
>
grp
</div>
<div
aria-selected="false"
class="config-select-item config-select-item-option config-select-item-option-grouped config-select-item-option-active"
title="Light"
>
<div
@@ -25266,7 +25259,7 @@ exports[`ConfigProvider components Select configProvider componentSize small 1`]
class="config-select-selection-search"
>
<input
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_1"
aria-autocomplete="list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
@@ -25284,11 +25277,8 @@ exports[`ConfigProvider components Select configProvider componentSize small 1`]
/>
</span>
<span
class="config-select-selection-item"
title="Light"
>
Light
</span>
class="config-select-selection-placeholder"
/>
</span>
</div>
<div
@@ -25302,12 +25292,17 @@ exports[`ConfigProvider components Select configProvider componentSize small 1`]
style="height: 0px; width: 0px; overflow: hidden;"
>
<div
aria-label="Light"
aria-selected="true"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_0"
role="presentation"
/>
<div
aria-label="Light"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_1"
role="option"
>
light
Bamboo
</div>
</div>
<div
@@ -25324,8 +25319,14 @@ exports[`ConfigProvider components Select configProvider componentSize small 1`]
style="display: flex; flex-direction: column;"
>
<div
aria-selected="true"
class="config-select-item config-select-item-option config-select-item-option-active config-select-item-option-selected"
class="config-select-item config-select-item-group"
title="grp"
>
grp
</div>
<div
aria-selected="false"
class="config-select-item config-select-item-option config-select-item-option-grouped config-select-item-option-active"
title="Light"
>
<div
@@ -25389,7 +25390,7 @@ exports[`ConfigProvider components Select normal 1`] = `
class="ant-select-selection-search"
>
<input
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_1"
aria-autocomplete="list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
@@ -25407,11 +25408,8 @@ exports[`ConfigProvider components Select normal 1`] = `
/>
</span>
<span
class="ant-select-selection-item"
title="Light"
>
Light
</span>
class="ant-select-selection-placeholder"
/>
</span>
</div>
<div
@@ -25425,12 +25423,17 @@ exports[`ConfigProvider components Select normal 1`] = `
style="height: 0px; width: 0px; overflow: hidden;"
>
<div
aria-label="Light"
aria-selected="true"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_0"
role="presentation"
/>
<div
aria-label="Light"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_1"
role="option"
>
light
Bamboo
</div>
</div>
<div
@@ -25447,8 +25450,14 @@ exports[`ConfigProvider components Select normal 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-selected="true"
class="ant-select-item ant-select-item-option ant-select-item-option-active ant-select-item-option-selected"
class="ant-select-item ant-select-item-group"
title="grp"
>
grp
</div>
<div
aria-selected="false"
class="ant-select-item ant-select-item-option ant-select-item-option-grouped ant-select-item-option-active"
title="Light"
>
<div
@@ -25512,7 +25521,7 @@ exports[`ConfigProvider components Select prefixCls 1`] = `
class="prefix-Select-selection-search"
>
<input
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_1"
aria-autocomplete="list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
@@ -25530,11 +25539,8 @@ exports[`ConfigProvider components Select prefixCls 1`] = `
/>
</span>
<span
class="prefix-Select-selection-item"
title="Light"
>
Light
</span>
class="prefix-Select-selection-placeholder"
/>
</span>
</div>
<div
@@ -25548,12 +25554,17 @@ exports[`ConfigProvider components Select prefixCls 1`] = `
style="height: 0px; width: 0px; overflow: hidden;"
>
<div
aria-label="Light"
aria-selected="true"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_0"
role="presentation"
/>
<div
aria-label="Light"
aria-selected="false"
id="rc_select_TEST_OR_SSR_list_1"
role="option"
>
light
Bamboo
</div>
</div>
<div
@@ -25570,8 +25581,14 @@ exports[`ConfigProvider components Select prefixCls 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-selected="true"
class="prefix-Select-item prefix-Select-item-option prefix-Select-item-option-active prefix-Select-item-option-selected"
class="prefix-Select-item prefix-Select-item-group"
title="grp"
>
grp
</div>
<div
aria-selected="false"
class="prefix-Select-item prefix-Select-item-option prefix-Select-item-option-grouped prefix-Select-item-option-active"
title="Light"
>
<div
@@ -39922,7 +39939,7 @@ exports[`ConfigProvider components Transfer configProvider 1`] = `
exports[`ConfigProvider components Transfer configProvider componentDisabled 1`] = `
<div
class="config-transfer config-transfer-disabled"
class="config-transfer"
>
<div
class="config-transfer-list"
@@ -39949,7 +39966,6 @@ exports[`ConfigProvider components Transfer configProvider componentDisabled 1`]
<span
aria-label="down"
class="anticon anticon-down config-dropdown-trigger config-transfer-list-header-dropdown"
disabled=""
role="img"
>
<svg
@@ -40120,7 +40136,6 @@ exports[`ConfigProvider components Transfer configProvider componentDisabled 1`]
<span
aria-label="down"
class="anticon anticon-down config-dropdown-trigger config-transfer-list-header-dropdown"
disabled=""
role="img"
>
<svg
@@ -41795,12 +41810,11 @@ exports[`ConfigProvider components Tree configProvider 1`] = `
exports[`ConfigProvider components Tree configProvider componentDisabled 1`] = `
<div>
<div
class="config-tree config-tree-icon-hide config-tree-disabled"
class="config-tree config-tree-icon-hide"
>
<div>
<input
aria-label="for screen reader"
disabled=""
style="width: 0px; height: 0px; display: flex; overflow: hidden; opacity: 0; border: 0px; padding: 0px; margin: 0px;"
tabindex="0"
value=""
@@ -41834,7 +41848,7 @@ exports[`ConfigProvider components Tree configProvider componentDisabled 1`] = `
>
<div
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-disabled config-tree-treenode-switcher-close config-tree-treenode-leaf-last config-tree-treenode-leaf"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last config-tree-treenode-leaf"
draggable="false"
role="treeitem"
>
@@ -41862,12 +41876,11 @@ exports[`ConfigProvider components Tree configProvider componentDisabled 1`] = `
</div>
</div>
<div
class="config-tree config-tree-block-node config-tree-disabled config-tree-directory"
class="config-tree config-tree-block-node config-tree-directory"
>
<div>
<input
aria-label="for screen reader"
disabled=""
style="width: 0px; height: 0px; display: flex; overflow: hidden; opacity: 0; border: 0px; padding: 0px; margin: 0px;"
tabindex="0"
value=""
@@ -41901,7 +41914,7 @@ exports[`ConfigProvider components Tree configProvider componentDisabled 1`] = `
>
<div
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-disabled config-tree-treenode-switcher-close config-tree-treenode-leaf-last config-tree-treenode-leaf"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last config-tree-treenode-leaf"
draggable="false"
role="treeitem"
>

View File

@@ -59,12 +59,11 @@ import TreeSelect from '../../tree-select';
import Upload from '../../upload';
dayjs.extend(customParseFormat);
jest.mock('rc-util/lib/Portal');
describe('ConfigProvider', () => {
describe('components', () => {
const testPair = (name: string, renderComponent: (props?: any) => React.ReactElement<any>) => {
function testPair(name: string, renderComponent: (props?: any) => React.ReactElement): void {
const isArray = ['Menu', 'TimePicker', 'Tooltip'].includes(name);
describe(`${name}`, () => {
// normal
@@ -123,7 +122,7 @@ describe('ConfigProvider', () => {
expect(isArray ? container.children : container.firstChild).toMatchSnapshot();
});
});
};
}
// Alert
testPair('Alert', (props) => (
@@ -431,12 +430,11 @@ describe('ConfigProvider', () => {
// Select
testPair('Select', (props) => (
<Select
open
defaultValue={'light'}
options={[{ label: 'Light', value: 'light' }]}
{...props}
/>
<Select {...props} open>
<Select.OptGroup key="grp">
<Select.Option key="Bamboo">Light</Select.Option>
</Select.OptGroup>
</Select>
));
// Skeleton

View File

@@ -82,8 +82,7 @@ describe('ConfigProvider.Locale', () => {
const datepicke = wrapper.container.querySelector<HTMLInputElement>('.ant-picker-input input');
expect(datepicke?.value).toBe('');
expect(datepicke?.placeholder).toBe('请选择日期');
expect(wrapper.container.querySelector<HTMLElement>('.ant-pagination-item-1')).toHaveClass(
expect(wrapper.container.querySelector('.ant-pagination-item-1')?.className).toContain(
'ant-pagination-item-active',
);
@@ -94,7 +93,6 @@ describe('ConfigProvider.Locale', () => {
expect(
wrapper.container.querySelector<HTMLInputElement>('.ant-picker-input input')?.value,
).not.toBe('');
wrapper.rerender(
<ConfigProvider locale={{} as Locale}>
<DatePicker />
@@ -110,7 +108,7 @@ describe('ConfigProvider.Locale', () => {
expect(datepicker?.value).not.toBe('');
expect(datepicker?.value).toContain('-10');
expect(wrapper.container.querySelector('.ant-pagination-item-3')).toHaveClass(
expect(wrapper.container.querySelector('.ant-pagination-item-3')?.className).toContain(
'ant-pagination-item-active',
);
});

View File

@@ -16,14 +16,4 @@ describe('ConfigProvider.Pagination', () => {
);
expect(container.querySelector('.ant-pagination-options-size-changer')).toBeFalsy();
});
it('totalBoundaryShowSizeChanger', () => {
const { container } = render(
<ConfigProvider pagination={{ totalBoundaryShowSizeChanger: 100 }}>
<Pagination total={80} />
</ConfigProvider>,
);
// total={80} < 100, so size changer should not be visible
expect(container.querySelector('.ant-pagination-options-size-changer')).toBeFalsy();
});
});

Some files were not shown because too many files have changed in this diff Show More