chore: auto merge branches (#54374)

chore: merge master into feature
This commit is contained in:
github-actions[bot] 2025-07-13 04:46:28 +00:00 committed by GitHub
commit 06ef05d7da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 72 additions and 55 deletions

View file

@ -2,7 +2,7 @@
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
"name": "ant-design",
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm",
"image": "mcr.microsoft.com/devcontainers/typescript-node:2-22-bookworm",
"postCreateCommand": "pnpm install",
"customizations": {
"vscode": {

View file

@ -100,21 +100,19 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = () => {
return;
}
// 校验当前主题是否包含要切换的主题(避免 timeout in DOM update
if (theme.includes(key as ThemeName)) {
return;
}
// 亮色/暗色模式切换时应用动画效果
if (key === 'dark' || key === 'light') {
lastThemeKey.current = key;
toggleAnimationTheme(domEvent, theme.includes('dark'));
}
const themeKey = key as ThemeName;
// 亮色/暗色模式是互斥的
if (['light', 'dark'].includes(key)) {
// 校验当前主题是否包含要切换的主题(避免 timeout in DOM update
if (theme.includes(themeKey)) {
return;
}
// 亮色/暗色模式切换时应用动画效果
lastThemeKey.current = key;
toggleAnimationTheme(domEvent, theme.includes('dark'));
const filteredTheme = theme.filter((t) => !['light', 'dark'].includes(t));
updateSiteConfig({
theme: [...filteredTheme, themeKey],

View file

@ -156,7 +156,8 @@ export default function useClosable(
}
mergedCloseIcon = React.isValidElement<HTMLAriaDataAttributes>(mergedCloseIcon) ? (
React.cloneElement(mergedCloseIcon, {
'aria-label': contextLocale.close,
...mergedCloseIcon.props,
'aria-label': mergedCloseIcon.props?.['aria-label'] ?? contextLocale.close,
...ariaOrDataProps,
})
) : (

View file

@ -130,16 +130,12 @@ const Collapse = React.forwardRef<HTMLDivElement, CollapseProps>((props, ref) =>
);
return cloneElement(icon, () => ({
className: classNames(
(
icon as React.ReactElement<{
className?: string;
}>
)?.props?.className,
(icon as React.ReactElement<{ className?: string }>).props?.className,
`${prefixCls}-arrow`,
),
}));
},
[mergedExpandIcon, prefixCls],
[mergedExpandIcon, prefixCls, direction],
);
const collapseClassName = classNames(
@ -156,35 +152,35 @@ const Collapse = React.forwardRef<HTMLDivElement, CollapseProps>((props, ref) =>
hashId,
cssVarCls,
);
const openMotion: CSSMotionProps = {
...initCollapseMotion(rootPrefixCls),
motionAppear: false,
leavedClassName: `${prefixCls}-content-hidden`,
};
const openMotion = React.useMemo<CSSMotionProps>(
() => ({
...initCollapseMotion(rootPrefixCls),
motionAppear: false,
leavedClassName: `${prefixCls}-content-hidden`,
}),
[rootPrefixCls, prefixCls],
);
const items = React.useMemo<React.ReactNode[] | null>(() => {
if (children) {
return toArray(children).map((child, index) => {
const childProps = (
child as React.ReactElement<{
disabled?: boolean;
collapsible?: CollapsibleType;
}>
).props;
if (childProps?.disabled) {
const key = child.key ?? String(index);
const mergedChildProps: Omit<CollapseProps, 'items'> & { key: React.Key } = {
...omit(child.props as any, ['disabled']),
key,
collapsible: childProps.collapsible ?? 'disabled',
};
return cloneElement(child, mergedChildProps);
}
return child;
});
if (!children) {
return null;
}
return null;
return toArray(children).map((child, index) => {
const childProps = (
child as React.ReactElement<{ disabled?: boolean; collapsible?: CollapsibleType }>
).props;
if (childProps?.disabled) {
const key = child.key ?? String(index);
const mergedChildProps: Omit<CollapseProps, 'items'> & { key: React.Key } = {
...omit(child.props as any, ['disabled']),
key,
collapsible: childProps.collapsible ?? 'disabled',
};
return cloneElement(child, mergedChildProps);
}
return child;
});
}, [children]);
return wrapCSSVar(

View file

@ -254,6 +254,7 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = (token
borderEndEndRadius: borderRadiusLG,
},
'&:not(:last-child)': {
borderBottom: 'none',
borderInlineEnd: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
},
},

View file

@ -63,8 +63,8 @@ const App: React.FC = () => {
},
) => (
<Space size={12} className="toolbar-wrapper">
<LeftOutlined onClick={() => onActive?.(-1)} />
<RightOutlined onClick={() => onActive?.(1)} />
<LeftOutlined disabled={current === 0} onClick={() => onActive?.(-1)} />
<RightOutlined disabled={current === imageList.length - 1} onClick={() => onActive?.(1)} />
<DownloadOutlined onClick={onDownload} />
<SwapOutlined rotate={90} onClick={onFlipY} />
<SwapOutlined onClick={onFlipX} />

View file

@ -161,16 +161,21 @@ const SplitBar: React.FC<SplitBarProps> = (props) => {
setStartPos(null);
};
window.addEventListener('touchmove', handleTouchMove);
window.addEventListener('touchend', handleTouchEnd);
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', onMouseUp);
const eventHandlerMap: Partial<Record<keyof WindowEventMap, EventListener>> = {
mousemove: onMouseMove as EventListener,
mouseup: onMouseUp,
touchmove: handleTouchMove as EventListener,
touchend: handleTouchEnd,
};
for (const [event, handler] of Object.entries(eventHandlerMap)) {
window.addEventListener(event, handler);
}
return () => {
window.removeEventListener('touchmove', handleTouchMove);
window.removeEventListener('touchend', handleTouchEnd);
window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp);
for (const [event, handler] of Object.entries(eventHandlerMap)) {
window.removeEventListener(event, handler);
}
};
}
}, [startPos]);

View file

@ -219,4 +219,20 @@ describe('Tag', () => {
);
expect(container.querySelector('.ant-tag-close-icon')?.textContent).toEqual('X');
});
it('should not override aria-label in custom closeIcon', () => {
const { getByRole } = render(
<Tag
closable
closeIcon={
<button type="button" aria-label="Remove This Filter">
x
</button>
}
>
Filter
</Tag>,
);
expect(getByRole('button')).toHaveAttribute('aria-label', 'Remove This Filter');
});
});