Merge pull request #50103 from ant-design/master

chore: merge master into feature
This commit is contained in:
lijianan 2024-07-26 23:21:05 +08:00 committed by GitHub
commit 65496b5845
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 82 additions and 69 deletions

View File

@ -1,12 +1,14 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ColorPicker, Flex, Input } from 'antd'; import { ColorPicker, Flex, Input } from 'antd';
import { createStyles } from 'antd-style'; import { createStyles } from 'antd-style';
import type { Color } from 'antd/es/color-picker'; import type { ColorPickerProps, GetProp } from 'antd';
import { generateColor } from 'antd/es/color-picker/util'; import { generateColor } from 'antd/es/color-picker/util';
import classNames from 'classnames'; import classNames from 'classnames';
import { PRESET_COLORS } from './colorUtil'; import { PRESET_COLORS } from './colorUtil';
type Color = GetProp<ColorPickerProps, 'value'>;
const useStyle = createStyles(({ token, css }) => ({ const useStyle = createStyles(({ token, css }) => ({
color: css` color: css`
width: ${token.controlHeightLG / 2}px; width: ${token.controlHeightLG / 2}px;
@ -34,13 +36,13 @@ const useStyle = createStyles(({ token, css }) => ({
`, `,
})); }));
export interface ColorPickerProps { export interface ThemeColorPickerProps {
id?: string; id?: string;
value?: string | Color; value?: string | Color;
onChange?: (value?: Color | string) => void; onChange?: (value?: Color | string) => void;
} }
const DebouncedColorPicker: React.FC<React.PropsWithChildren<ColorPickerProps>> = (props) => { const DebouncedColorPicker: React.FC<React.PropsWithChildren<ThemeColorPickerProps>> = (props) => {
const { value: color, children, onChange } = props; const { value: color, children, onChange } = props;
const [value, setValue] = useState(color); const [value, setValue] = useState(color);
@ -66,7 +68,7 @@ const DebouncedColorPicker: React.FC<React.PropsWithChildren<ColorPickerProps>>
); );
}; };
const ThemeColorPicker: React.FC<ColorPickerProps> = ({ value, onChange, id }) => { const ThemeColorPicker: React.FC<ThemeColorPickerProps> = ({ value, onChange, id }) => {
const { styles } = useStyle(); const { styles } = useStyle();
const matchColors = React.useMemo(() => { const matchColors = React.useMemo(() => {

View File

@ -1,6 +1,8 @@
import type { Color } from 'antd/es/color-picker'; import type { ColorPickerProps, GetProp } from 'antd';
import { generateColor } from 'antd/es/color-picker/util'; import { generateColor } from 'antd/es/color-picker/util';
type Color = GetProp<ColorPickerProps, 'value'>;
export const DEFAULT_COLOR = '#1677FF'; export const DEFAULT_COLOR = '#1677FF';
export const PINK_COLOR = '#ED4192'; export const PINK_COLOR = '#ED4192';

View File

@ -7,7 +7,7 @@ import {
QuestionCircleOutlined, QuestionCircleOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { TinyColor } from '@ctrl/tinycolor'; import { TinyColor } from '@ctrl/tinycolor';
import type { MenuProps, ThemeConfig } from 'antd'; import type { MenuProps, ThemeConfig, GetProp, ColorPickerProps } from 'antd';
import { import {
Breadcrumb, Breadcrumb,
Card, Card,
@ -21,7 +21,6 @@ import {
Typography, Typography,
} from 'antd'; } from 'antd';
import { createStyles } from 'antd-style'; import { createStyles } from 'antd-style';
import type { Color } from 'antd/es/color-picker';
import { generateColor } from 'antd/es/color-picker/util'; import { generateColor } from 'antd/es/color-picker/util';
import classNames from 'classnames'; import classNames from 'classnames';
import { useLocation } from 'dumi'; import { useLocation } from 'dumi';
@ -41,6 +40,8 @@ import RadiusPicker from './RadiusPicker';
import type { THEME } from './ThemePicker'; import type { THEME } from './ThemePicker';
import ThemePicker from './ThemePicker'; import ThemePicker from './ThemePicker';
type Color = GetProp<ColorPickerProps, 'value'>;
const { Header, Content, Sider } = Layout; const { Header, Content, Sider } = Layout;
const TokenChecker: React.FC = () => { const TokenChecker: React.FC = () => {
@ -264,7 +265,7 @@ const sideMenuItems: MenuProps['items'] = [
// ============================= Theme ============================= // ============================= Theme =============================
function getTitleColor(colorPrimary: string | Color, isLight?: boolean) { function getTitleColor(colorPrimary: Color, isLight?: boolean) {
if (!isLight) { if (!isLight) {
return '#FFF'; return '#FFF';
} }
@ -289,7 +290,7 @@ function getTitleColor(colorPrimary: string | Color, isLight?: boolean) {
interface ThemeData { interface ThemeData {
themeType: THEME; themeType: THEME;
colorPrimary: string | Color; colorPrimary: Color;
borderRadius: number; borderRadius: number;
compact: 'default' | 'compact'; compact: 'default' | 'compact';
} }

View File

@ -156,7 +156,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
{title} {title}
<Popover <Popover
title={null} title={null}
popupStyle={{ width: 400 }} overlayStyle={{ width: 400 }}
content={ content={
<Typography> <Typography>
{/* <SourceCode lang="jsx">{code}</SourceCode> */} {/* <SourceCode lang="jsx">{code}</SourceCode> */}

View File

@ -1,6 +1,7 @@
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { Col, ColorPicker, Row } from 'antd'; import { Col, ColorPicker, Row } from 'antd';
import { FormattedMessage } from 'dumi'; import { FormattedMessage } from 'dumi';
import type { Color } from 'antd/es/color-picker';
import useLocale from '../../../hooks/useLocale'; import useLocale from '../../../hooks/useLocale';
import ColorPatterns from './ColorPatterns'; import ColorPatterns from './ColorPatterns';
@ -24,7 +25,7 @@ const locales = {
const ColorPaletteTool: React.FC = () => { const ColorPaletteTool: React.FC = () => {
const [primaryColor, setPrimaryColor] = useState<string>('#1890ff'); const [primaryColor, setPrimaryColor] = useState<string>('#1890ff');
const [backgroundColor, setBackgroundColor] = useState<string>('#141414'); const [backgroundColor, setBackgroundColor] = useState<string>('#141414');
const [primaryColorInstance, setPrimaryColorInstance] = useState<Color>(null); const [primaryColorInstance, setPrimaryColorInstance] = useState<Color | null>(null);
const [locale] = useLocale(locales); const [locale] = useLocale(locales);

View File

@ -142,8 +142,10 @@ jobs:
## Visual Regression Build for PR #${{ steps.pr.outputs.id }} Failed ❌ ## Visual Regression Build for PR #${{ steps.pr.outputs.id }} Failed ❌
Potential causes: Potential causes:
- `upstream workflow` status: ${{ needs.upstream-workflow-summary.outputs.build-status }} [upstream job link](${{ needs.upstream-workflow-summary.outputs.upstream-job-link }}) - `upstream workflow` status: ${{ needs.upstream-workflow-summary.outputs.build-status }} [upstream job link](${{ needs.upstream-workflow-summary.outputs.upstream-job-link }})
- `download report artifact` status: ${{ steps.download_report.outcome }} - `current workflow` summary:
- `report upload` status: ${{ steps.report.outcome }} - `download report artifact` status: ${{ steps.download_report.outcome }}
- `report upload` status: ${{ steps.report.outcome }}
- job url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/jobs/${{ github.job }}
<!-- VISUAL_DIFF_REGRESSION_HOOK --> <!-- VISUAL_DIFF_REGRESSION_HOOK -->
body-include: '<!-- VISUAL_DIFF_REGRESSION_HOOK -->' body-include: '<!-- VISUAL_DIFF_REGRESSION_HOOK -->'
number: ${{ steps.pr.outputs.id }} number: ${{ steps.pr.outputs.id }}

View File

@ -189,8 +189,8 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token) => {
'&-indeterminate': { '&-indeterminate': {
// Wrapper > Checkbox > inner // Wrapper > Checkbox > inner
[`${checkboxCls}-inner`]: { [`${checkboxCls}-inner`]: {
backgroundColor: token.colorBgContainer, backgroundColor: `${token.colorBgContainer} !important`,
borderColor: token.colorBorder, borderColor: `${token.colorBorder} !important`,
'&:after': { '&:after': {
top: '50%', top: '50%',
@ -204,6 +204,12 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token) => {
content: '""', content: '""',
}, },
}, },
// https://github.com/ant-design/ant-design/issues/50074
[`&:hover ${checkboxCls}-inner`]: {
backgroundColor: `${token.colorBgContainer} !important`,
borderColor: `${token.colorPrimary} !important`,
},
}, },
}, },
}, },

View File

@ -25,7 +25,7 @@ const genSharedEmptyStyle: GenerateStyle<EmptyToken> = (token): CSSObject => {
lineHeight, lineHeight,
textAlign: 'center', textAlign: 'center',
// 原来 &-image 没有父子结构,现在为了外层承担我们的hashId改成父子结果 // 原来 &-image 没有父子结构,现在为了外层承担我们的 hashId改成父子结构
[`${componentCls}-image`]: { [`${componentCls}-image`]: {
height: token.emptyImgHeight, height: token.emptyImgHeight,
marginBottom: marginXS, marginBottom: marginXS,
@ -46,7 +46,7 @@ const genSharedEmptyStyle: GenerateStyle<EmptyToken> = (token): CSSObject => {
color: token.colorTextDescription, color: token.colorTextDescription,
}, },
// 原来 &-footer 没有父子结构,现在为了外层承担我们的hashId改成父子结果 // 原来 &-footer 没有父子结构,现在为了外层承担我们的 hashId改成父子结构
[`${componentCls}-footer`]: { [`${componentCls}-footer`]: {
marginTop: margin, marginTop: margin,
}, },

View File

@ -59,16 +59,17 @@ export const Overlay: React.FC<OverlayProps> = (props) => {
const { getPrefixCls } = React.useContext(ConfigContext); const { getPrefixCls } = React.useContext(ConfigContext);
const [contextLocale] = useLocale('Popconfirm', defaultLocale.Popconfirm); const [contextLocale] = useLocale('Popconfirm', defaultLocale.Popconfirm);
const theTitle = getRenderPropValue(title);
const theDescription = getRenderPropValue(description); const titleNode = getRenderPropValue(title);
const descriptionNode = getRenderPropValue(description);
return ( return (
<div className={`${prefixCls}-inner-content`} onClick={onPopupClick}> <div className={`${prefixCls}-inner-content`} onClick={onPopupClick}>
<div className={`${prefixCls}-message`}> <div className={`${prefixCls}-message`}>
{icon && <span className={`${prefixCls}-message-icon`}>{icon}</span>} {icon && <span className={`${prefixCls}-message-icon`}>{icon}</span>}
<div className={`${prefixCls}-message-text`}> <div className={`${prefixCls}-message-text`}>
{theTitle && <div className={classNames(`${prefixCls}-title`)}>{theTitle}</div>} {titleNode && <div className={`${prefixCls}-title`}>{titleNode}</div>}
{theDescription && <div className={`${prefixCls}-description`}>{theDescription}</div>} {descriptionNode && <div className={`${prefixCls}-description`}>{descriptionNode}</div>}
</div> </div>
</div> </div>
<div className={`${prefixCls}-buttons`}> <div className={`${prefixCls}-buttons`}>

View File

@ -7,18 +7,20 @@ import { getRenderPropValue } from '../_util/getRenderPropValue';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import useStyle from './style'; import useStyle from './style';
export const getOverlay = ( interface OverlayProps {
prefixCls?: string, prefixCls?: string;
title?: PopoverProps['title'], title?: React.ReactNode;
content?: PopoverProps['content'], content?: React.ReactNode;
) => { }
export const Overlay: React.FC<OverlayProps> = ({ title, content, prefixCls }) => {
if (!title && !content) { if (!title && !content) {
return null; return null;
} }
return ( return (
<> <>
{title && <div className={`${prefixCls}-title`}>{getRenderPropValue(title)}</div>} {title && <div className={`${prefixCls}-title`}>{title}</div>}
<div className={`${prefixCls}-inner-content`}>{getRenderPropValue(content)}</div> {content && <div className={`${prefixCls}-inner-content`}>{content}</div>}
</> </>
); );
}; };
@ -43,20 +45,22 @@ export const RawPurePanel: React.FC<RawPurePanelProps> = (props) => {
children, children,
} = props; } = props;
const titleNode = getRenderPropValue(title);
const contentNode = getRenderPropValue(content);
const cls = classNames(
hashId,
prefixCls,
`${prefixCls}-pure`,
`${prefixCls}-placement-${placement}`,
className,
);
return ( return (
<div <div className={cls} style={style}>
className={classNames(
hashId,
prefixCls,
`${prefixCls}-pure`,
`${prefixCls}-placement-${placement}`,
className,
)}
style={style}
>
<div className={`${prefixCls}-arrow`} /> <div className={`${prefixCls}-arrow`} />
<Popup {...props} className={hashId} prefixCls={prefixCls}> <Popup {...props} className={hashId} prefixCls={prefixCls}>
{children || getOverlay(prefixCls, title, content)} {children || <Overlay prefixCls={prefixCls} title={titleNode} content={contentNode} />}
</Popup> </Popup>
</div> </div>
); );

View File

@ -27,9 +27,6 @@ Array [
> >
RTL RTL
</div> </div>
<div
class="ant-popover-inner-content"
/>
</div> </div>
</div> </div>
</div>, </div>,

View File

@ -124,4 +124,17 @@ describe('Popover', () => {
fireEvent.keyDown(triggerNode, { key: 'Escape', keyCode: 27 }); fireEvent.keyDown(triggerNode, { key: 'Escape', keyCode: 27 });
expect(onOpenChange).toHaveBeenLastCalledWith(false, eventObject); expect(onOpenChange).toHaveBeenLastCalledWith(false, eventObject);
}); });
it('should not display overlay when the content is null/undefined', () => {
[null, undefined].forEach((item) => {
const { container } = render(
<Popover title={() => item} content={() => item} trigger="click">
<span>show me your code</span>
</Popover>,
);
fireEvent.click(container.querySelector<HTMLSpanElement>('span')!);
const popup = document.querySelector('.ant-popover');
expect(popup).toBe(null);
});
});
}); });

View File

@ -10,7 +10,7 @@ import { cloneElement } from '../_util/reactNode';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import type { AbstractTooltipProps, TooltipRef } from '../tooltip'; import type { AbstractTooltipProps, TooltipRef } from '../tooltip';
import Tooltip from '../tooltip'; import Tooltip from '../tooltip';
import PurePanel from './PurePanel'; import PurePanel, { Overlay } from './PurePanel';
// CSSINJS // CSSINJS
import useStyle from './style'; import useStyle from './style';
@ -23,19 +23,6 @@ export interface PopoverProps extends AbstractTooltipProps {
) => void; ) => void;
} }
interface OverlayProps {
prefixCls?: string;
title?: PopoverProps['title'];
content?: PopoverProps['content'];
}
const Overlay: React.FC<OverlayProps> = ({ title, content, prefixCls }) => (
<>
{title && <div className={`${prefixCls}-title`}>{getRenderPropValue(title)}</div>}
<div className={`${prefixCls}-inner-content`}>{getRenderPropValue(content)}</div>
</>
);
const InternalPopover = React.forwardRef<TooltipRef, PopoverProps>((props, ref) => { const InternalPopover = React.forwardRef<TooltipRef, PopoverProps>((props, ref) => {
const { const {
prefixCls: customizePrefixCls, prefixCls: customizePrefixCls,
@ -81,6 +68,9 @@ const InternalPopover = React.forwardRef<TooltipRef, PopoverProps>((props, ref)
settingOpen(value); settingOpen(value);
}; };
const titleNode = getRenderPropValue(title);
const contentNode = getRenderPropValue(content);
return wrapCSSVar( return wrapCSSVar(
<Tooltip <Tooltip
placement={placement} placement={placement}
@ -95,7 +85,9 @@ const InternalPopover = React.forwardRef<TooltipRef, PopoverProps>((props, ref)
open={open} open={open}
onOpenChange={onInternalOpenChange} onOpenChange={onInternalOpenChange}
overlay={ overlay={
title || content ? <Overlay prefixCls={prefixCls} title={title} content={content} /> : null titleNode || contentNode ? (
<Overlay prefixCls={prefixCls} title={titleNode} content={contentNode} />
) : null
} }
transitionName={getTransitionName(rootPrefixCls, 'zoom-big', otherProps.transitionName)} transitionName={getTransitionName(rootPrefixCls, 'zoom-big', otherProps.transitionName)}
data-popover-inject data-popover-inject

View File

@ -46,19 +46,16 @@ interface TourToken extends FullToken<'Tour'> {
const genBaseStyle: GenerateStyle<TourToken> = (token) => { const genBaseStyle: GenerateStyle<TourToken> = (token) => {
const { const {
componentCls, componentCls,
lineHeight,
padding, padding,
paddingXS, paddingXS,
borderRadius, borderRadius,
borderRadiusXS, borderRadiusXS,
colorPrimary, colorPrimary,
colorText,
colorFill, colorFill,
indicatorHeight, indicatorHeight,
indicatorWidth, indicatorWidth,
boxShadowTertiary, boxShadowTertiary,
tourZIndexPopup, tourZIndexPopup,
fontSize,
colorBgElevated, colorBgElevated,
fontWeightStrong, fontWeightStrong,
marginXS, marginXS,
@ -77,13 +74,10 @@ const genBaseStyle: GenerateStyle<TourToken> = (token) => {
[componentCls]: { [componentCls]: {
...resetComponent(token), ...resetComponent(token),
color: colorText,
position: 'absolute', position: 'absolute',
zIndex: tourZIndexPopup, zIndex: tourZIndexPopup,
display: 'block', maxWidth: 'fit-content',
visibility: 'visible', visibility: 'visible',
fontSize,
lineHeight,
width: 520, width: 520,
'--antd-arrow-background-color': colorBgElevated, '--antd-arrow-background-color': colorBgElevated,
@ -100,6 +94,7 @@ const genBaseStyle: GenerateStyle<TourToken> = (token) => {
[`${componentCls}-content`]: { [`${componentCls}-content`]: {
position: 'relative', position: 'relative',
}, },
[`${componentCls}-inner`]: { [`${componentCls}-inner`]: {
textAlign: 'start', textAlign: 'start',
textDecoration: 'none', textDecoration: 'none',
@ -151,15 +146,12 @@ const genBaseStyle: GenerateStyle<TourToken> = (token) => {
padding: `${unit(padding)} ${unit(padding)} ${unit(paddingXS)}`, padding: `${unit(padding)} ${unit(padding)} ${unit(paddingXS)}`,
[`${componentCls}-title`]: { [`${componentCls}-title`]: {
lineHeight,
fontSize,
fontWeight: fontWeightStrong, fontWeight: fontWeightStrong,
}, },
}, },
[`${componentCls}-description`]: { [`${componentCls}-description`]: {
padding: `0 ${unit(padding)}`, padding: `0 ${unit(padding)}`,
lineHeight,
wordWrap: 'break-word', wordWrap: 'break-word',
}, },

View File

@ -240,7 +240,7 @@
"eslint-plugin-markdown": "^5.1.0", "eslint-plugin-markdown": "^5.1.0",
"eslint-plugin-react": "^7.34.4", "eslint-plugin-react": "^7.34.4",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-unicorn": "^54.0.0", "eslint-plugin-unicorn": "^55.0.0",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"fetch-jsonp": "^1.3.0", "fetch-jsonp": "^1.3.0",
"fs-extra": "^11.2.0", "fs-extra": "^11.2.0",
@ -248,7 +248,7 @@
"glob": "^11.0.0", "glob": "^11.0.0",
"html2sketch": "^1.0.2", "html2sketch": "^1.0.2",
"http-server": "^14.1.1", "http-server": "^14.1.1",
"husky": "^9.0.11", "husky": "^9.1.2",
"identity-obj-proxy": "^3.0.0", "identity-obj-proxy": "^3.0.0",
"immer": "^10.1.1", "immer": "^10.1.1",
"is-ci": "^3.0.1", "is-ci": "^3.0.1",