mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-24 02:59:58 +08:00
chore: auto merge branches (#51642)
Some checks failed
Publish Any Commit / build (push) Has been cancelled
🔀 Sync mirror to Gitee / mirror (push) Has been cancelled
✅ test / lint (push) Has been cancelled
✅ test / test-react-legacy (16, 1/2) (push) Has been cancelled
✅ test / test-react-legacy (16, 2/2) (push) Has been cancelled
✅ test / test-react-legacy (17, 1/2) (push) Has been cancelled
✅ test / test-react-legacy (17, 2/2) (push) Has been cancelled
✅ test / test-node (push) Has been cancelled
✅ test / test-react-latest (dom, 1/2) (push) Has been cancelled
✅ test / test-react-latest (dom, 2/2) (push) Has been cancelled
✅ test / build (push) Has been cancelled
✅ test / test lib/es module (es, 1/2) (push) Has been cancelled
✅ test / test lib/es module (es, 2/2) (push) Has been cancelled
✅ test / test lib/es module (lib, 1/2) (push) Has been cancelled
✅ test / test lib/es module (lib, 2/2) (push) Has been cancelled
👁️ Visual Regression Persist Start / test image (push) Has been cancelled
✅ test / test-react-latest-dist (dist, 1/2) (push) Has been cancelled
✅ test / test-react-latest-dist (dist, 2/2) (push) Has been cancelled
✅ test / test-react-latest-dist (dist-min, 1/2) (push) Has been cancelled
✅ test / test-react-latest-dist (dist-min, 2/2) (push) Has been cancelled
✅ test / test-coverage (push) Has been cancelled
Some checks failed
Publish Any Commit / build (push) Has been cancelled
🔀 Sync mirror to Gitee / mirror (push) Has been cancelled
✅ test / lint (push) Has been cancelled
✅ test / test-react-legacy (16, 1/2) (push) Has been cancelled
✅ test / test-react-legacy (16, 2/2) (push) Has been cancelled
✅ test / test-react-legacy (17, 1/2) (push) Has been cancelled
✅ test / test-react-legacy (17, 2/2) (push) Has been cancelled
✅ test / test-node (push) Has been cancelled
✅ test / test-react-latest (dom, 1/2) (push) Has been cancelled
✅ test / test-react-latest (dom, 2/2) (push) Has been cancelled
✅ test / build (push) Has been cancelled
✅ test / test lib/es module (es, 1/2) (push) Has been cancelled
✅ test / test lib/es module (es, 2/2) (push) Has been cancelled
✅ test / test lib/es module (lib, 1/2) (push) Has been cancelled
✅ test / test lib/es module (lib, 2/2) (push) Has been cancelled
👁️ Visual Regression Persist Start / test image (push) Has been cancelled
✅ test / test-react-latest-dist (dist, 1/2) (push) Has been cancelled
✅ test / test-react-latest-dist (dist, 2/2) (push) Has been cancelled
✅ test / test-react-latest-dist (dist-min, 1/2) (push) Has been cancelled
✅ test / test-react-latest-dist (dist-min, 2/2) (push) Has been cancelled
✅ test / test-coverage (push) Has been cancelled
chore: merge master into feature
This commit is contained in:
commit
1b8e956a62
@ -58,7 +58,13 @@ jobs:
|
||||
if (comment.body.includes('VISUAL_DIFF_FAILED')) {
|
||||
hasDiffFailed = true;
|
||||
}
|
||||
if (comment.body.includes('- [x] Visual diff is acceptable')) {
|
||||
|
||||
// https://regex101.com/r/kLjudz/1
|
||||
const RE = /(?<=\>\s\[!IMPORTANT\].*?- \[ \])/s;
|
||||
if (
|
||||
comment.body.includes('- [x] Visual diff is acceptable') &&
|
||||
comment.body.match(RE) == null /** 检查 IMPORTANT 是否存在未勾选的 */
|
||||
) {
|
||||
hasMemberApprove = true;
|
||||
}
|
||||
}
|
||||
|
@ -474,4 +474,10 @@ describe('Button', () => {
|
||||
'--ant-button-solid-text-color': '#000',
|
||||
});
|
||||
});
|
||||
|
||||
it('autoFocus should work', () => {
|
||||
const { container } = render(<Button autoFocus>button</Button>);
|
||||
|
||||
expect(container.querySelector('button')).toBe(document.activeElement);
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Children, createRef, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import React, { Children, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'rc-util/lib/omit';
|
||||
import { composeRef } from 'rc-util/lib/ref';
|
||||
import { useComposeRef } from 'rc-util/lib/ref';
|
||||
|
||||
import { devUseWarning } from '../_util/warning';
|
||||
import Wave from '../_util/wave';
|
||||
@ -119,6 +119,7 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
classNames: customClassNames,
|
||||
style: customStyle = {},
|
||||
autoInsertSpace,
|
||||
autoFocus,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
@ -162,13 +163,15 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
|
||||
const [hasTwoCNChar, setHasTwoCNChar] = useState<boolean>(false);
|
||||
|
||||
const internalRef = createRef<HTMLButtonElement | HTMLAnchorElement>();
|
||||
const buttonRef = useRef<HTMLButtonElement | HTMLAnchorElement>();
|
||||
|
||||
const buttonRef = composeRef(ref, internalRef);
|
||||
const mergedRef = useComposeRef(ref, buttonRef);
|
||||
|
||||
const needInserted =
|
||||
Children.count(children) === 1 && !icon && !isUnBorderedButtonVariant(mergedVariant);
|
||||
|
||||
// ========================= Effect =========================
|
||||
// Loading
|
||||
useEffect(() => {
|
||||
let delayTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
if (loadingOrDelay.delay > 0) {
|
||||
@ -190,12 +193,13 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
return cleanupTimer;
|
||||
}, [loadingOrDelay]);
|
||||
|
||||
// Two chinese characters check
|
||||
useEffect(() => {
|
||||
// FIXME: for HOC usage like <FormatMessage />
|
||||
if (!buttonRef || !(buttonRef as any).current || !mergedInsertSpace) {
|
||||
if (!buttonRef.current || !mergedInsertSpace) {
|
||||
return;
|
||||
}
|
||||
const buttonText = (buttonRef as any).current.textContent;
|
||||
const buttonText = buttonRef.current.textContent || '';
|
||||
if (needInserted && isTwoCNChar(buttonText)) {
|
||||
if (!hasTwoCNChar) {
|
||||
setHasTwoCNChar(true);
|
||||
@ -203,8 +207,16 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
} else if (hasTwoCNChar) {
|
||||
setHasTwoCNChar(false);
|
||||
}
|
||||
}, [buttonRef]);
|
||||
});
|
||||
|
||||
// Auto focus
|
||||
useEffect(() => {
|
||||
if (autoFocus && buttonRef.current) {
|
||||
buttonRef.current.focus();
|
||||
}
|
||||
}, []);
|
||||
|
||||
// ========================= Events =========================
|
||||
const handleClick = React.useCallback(
|
||||
(e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement, MouseEvent>) => {
|
||||
// FIXME: https://github.com/ant-design/ant-design/issues/30207
|
||||
@ -217,6 +229,7 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
[props.onClick, innerLoading, mergedDisabled],
|
||||
);
|
||||
|
||||
// ========================== Warn ==========================
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const warning = devUseWarning('Button');
|
||||
|
||||
@ -233,6 +246,7 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
);
|
||||
}
|
||||
|
||||
// ========================== Size ==========================
|
||||
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);
|
||||
|
||||
const sizeClassNameMap = { large: 'lg', small: 'sm', middle: undefined };
|
||||
@ -245,6 +259,7 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
|
||||
const linkButtonRestProps = omit(rest as ButtonProps & { navigate: any }, ['navigate']);
|
||||
|
||||
// ========================= Render =========================
|
||||
const classes = classNames(
|
||||
prefixCls,
|
||||
hashId,
|
||||
@ -301,7 +316,7 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
href={mergedDisabled ? undefined : linkButtonRestProps.href}
|
||||
style={fullStyle}
|
||||
onClick={handleClick}
|
||||
ref={buttonRef as React.Ref<HTMLAnchorElement>}
|
||||
ref={mergedRef as React.Ref<HTMLAnchorElement>}
|
||||
tabIndex={mergedDisabled ? -1 : 0}
|
||||
>
|
||||
{iconNode}
|
||||
@ -318,7 +333,7 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
style={fullStyle}
|
||||
onClick={handleClick}
|
||||
disabled={mergedDisabled}
|
||||
ref={buttonRef as React.Ref<HTMLButtonElement>}
|
||||
ref={mergedRef as React.Ref<HTMLButtonElement>}
|
||||
>
|
||||
{iconNode}
|
||||
{kids}
|
||||
|
@ -78,6 +78,17 @@ const ErrorList: React.FC<ErrorListProps> = ({
|
||||
];
|
||||
}, [help, helpStatus, debounceErrors, debounceWarnings]);
|
||||
|
||||
const filledKeyFullKeyList = React.useMemo<ErrorEntity[]>(() => {
|
||||
const keysCount: Record<string, number> = {};
|
||||
fullKeyList.forEach(({ key }) => {
|
||||
keysCount[key] = (keysCount[key] || 0) + 1;
|
||||
});
|
||||
return fullKeyList.map((entity, index) => ({
|
||||
...entity,
|
||||
key: keysCount[entity.key] > 1 ? `${entity.key}-fallback-${index}` : entity.key,
|
||||
}));
|
||||
}, [fullKeyList]);
|
||||
|
||||
const helpProps: { id?: string } = {};
|
||||
|
||||
if (fieldId) {
|
||||
@ -88,7 +99,7 @@ const ErrorList: React.FC<ErrorListProps> = ({
|
||||
<CSSMotion
|
||||
motionDeadline={collapseMotion.motionDeadline}
|
||||
motionName={`${prefixCls}-show-help`}
|
||||
visible={!!fullKeyList.length}
|
||||
visible={!!filledKeyFullKeyList.length}
|
||||
onVisibleChanged={onVisibleChanged}
|
||||
>
|
||||
{(holderProps) => {
|
||||
@ -109,7 +120,7 @@ const ErrorList: React.FC<ErrorListProps> = ({
|
||||
role="alert"
|
||||
>
|
||||
<CSSMotionList
|
||||
keys={fullKeyList}
|
||||
keys={filledKeyFullKeyList}
|
||||
{...initCollapseMotion(prefixCls)}
|
||||
motionName={`${prefixCls}-show-help-item`}
|
||||
component={false}
|
||||
|
@ -2459,4 +2459,60 @@ describe('Form', () => {
|
||||
fireEvent.click(container.querySelector('input')!);
|
||||
expect(container.querySelector('input')?.checked).toBeTruthy();
|
||||
});
|
||||
|
||||
it('not warning for react key', async () => {
|
||||
const MockInput = (props: { onChange?: (value: number[]) => void }) => (
|
||||
<Input
|
||||
onChange={({ target: { value } }) => {
|
||||
props.onChange?.(value.split(',').map(Number));
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const { container } = render(
|
||||
<Form>
|
||||
<Form.Item>
|
||||
<Form.Item
|
||||
name="test"
|
||||
rules={[
|
||||
{
|
||||
type: 'array',
|
||||
defaultField: {
|
||||
type: 'number',
|
||||
min: 10,
|
||||
message: 'LESS_THAN_10',
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<MockInput />
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
function expectErrors(errors: string[]) {
|
||||
expect(container.querySelectorAll('.ant-form-item-explain-error')).toHaveLength(
|
||||
errors.length,
|
||||
);
|
||||
errors.forEach((error, index) => {
|
||||
expect(container.querySelectorAll('.ant-form-item-explain-error')[index]).toHaveTextContent(
|
||||
error,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// user type something and clear
|
||||
await changeValue(0, '1');
|
||||
expectErrors(['LESS_THAN_10']);
|
||||
|
||||
await changeValue(0, '1,1');
|
||||
expectErrors(['LESS_THAN_10', 'LESS_THAN_10']);
|
||||
|
||||
await changeValue(0, '1');
|
||||
expectErrors(['LESS_THAN_10']);
|
||||
|
||||
await changeValue(0, '100');
|
||||
expectErrors([]);
|
||||
});
|
||||
});
|
||||
|
@ -52,13 +52,13 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
|
||||
### Timeline
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| mode | By sending `alternate` the timeline will distribute the nodes to the left and right | `left` \| `alternate` \| `right` | - |
|
||||
| pending | Set the last ghost node's existence or its content | ReactNode | false |
|
||||
| pendingDot | Set the dot of the last ghost node when pending is true | ReactNode | <LoadingOutlined /> |
|
||||
| reverse | Whether reverse nodes or not | boolean | false |
|
||||
| items | Each node of timeline | [Items](#Items)[] | 5.2.0 |
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| mode | By sending `alternate` the timeline will distribute the nodes to the left and right | `left` \| `alternate` \| `right` | - | |
|
||||
| pending | Set the last ghost node's existence or its content | ReactNode | false | |
|
||||
| pendingDot | Set the dot of the last ghost node when pending is true | ReactNode | <LoadingOutlined /> | |
|
||||
| reverse | Whether reverse nodes or not | boolean | false | |
|
||||
| items | Each node of timeline | [Items](#Items)[] | - | 5.2.0 |
|
||||
|
||||
### Items
|
||||
|
||||
|
@ -53,13 +53,13 @@ return (
|
||||
|
||||
### Timeline
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| mode | 通过设置 `mode` 可以改变时间轴和内容的相对位置 | `left` \| `alternate` \| `right` | - |
|
||||
| pending | 指定最后一个幽灵节点是否存在或内容 | ReactNode | false |
|
||||
| pendingDot | 当最后一个幽灵节点存在時,指定其时间图点 | ReactNode | <LoadingOutlined /> |
|
||||
| reverse | 节点排序 | boolean | false |
|
||||
| items | 选项配置 | [Items](#Items)[] | 5.2.0 |
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| mode | 通过设置 `mode` 可以改变时间轴和内容的相对位置 | `left` \| `alternate` \| `right` | - | |
|
||||
| pending | 指定最后一个幽灵节点是否存在或内容 | ReactNode | false | |
|
||||
| pendingDot | 当最后一个幽灵节点存在時,指定其时间图点 | ReactNode | <LoadingOutlined /> | |
|
||||
| reverse | 节点排序 | boolean | false | |
|
||||
| items | 选项配置 | [Items](#Items)[] | - | 5.2.0 |
|
||||
|
||||
### Items
|
||||
|
||||
|
@ -12,6 +12,7 @@ import pixelmatch from 'pixelmatch';
|
||||
import { PNG } from 'pngjs';
|
||||
import sharp from 'sharp';
|
||||
import simpleGit from 'simple-git';
|
||||
import filter from 'lodash/filter';
|
||||
|
||||
import markdown2Html from './convert';
|
||||
|
||||
@ -283,9 +284,17 @@ ${fullReport}
|
||||
|
||||
let diffCount = 0;
|
||||
|
||||
// Summary
|
||||
const badCount = badCases.length;
|
||||
const commentReportLimit = isLocalEnv ? badCount : 8;
|
||||
|
||||
const changedCount = filter(badCases, { type: 'changed' }).length;
|
||||
const removedCount = filter(badCases, { type: 'removed' }).length;
|
||||
const addedCount = filter(badCases, { type: 'added' }).length;
|
||||
|
||||
for (const badCase of badCases) {
|
||||
diffCount += 1;
|
||||
if (diffCount <= 10) {
|
||||
if (diffCount <= commentReportLimit) {
|
||||
// 将图片下方增加文件名
|
||||
reportMdStr += generateLineReport(badCase, publicPath, currentRef, true);
|
||||
}
|
||||
@ -293,18 +302,37 @@ ${fullReport}
|
||||
fullVersionMd += generateLineReport(badCase, publicPath, currentRef, false);
|
||||
}
|
||||
|
||||
reportMdStr += `\n\nCheck <a href="${htmlReportLink}" target="_blank">Full Report</a> for details`;
|
||||
const hasMore = badCount > commentReportLimit;
|
||||
|
||||
if (hasMore) {
|
||||
reportMdStr += [
|
||||
'\r',
|
||||
'> [!WARNING]',
|
||||
`> There are more diffs not shown in the table. Please check the <a href="${htmlReportLink}" target="_blank">Full Report</a> for details.`,
|
||||
'\r',
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
// tips for comment `Pass Visual Diff` will pass the CI
|
||||
if (!passed) {
|
||||
reportMdStr += `
|
||||
const summaryLine = [
|
||||
changedCount > 0 && `🔄 **${changedCount}** changed`,
|
||||
removedCount > 0 && `🛑 **${removedCount}** removed`,
|
||||
addedCount > 0 && `🆕 **${addedCount}** added`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(', ');
|
||||
|
||||
-----
|
||||
|
||||
If you think the visual diff is acceptable, please check:
|
||||
|
||||
- [ ] Visual diff is acceptable
|
||||
`;
|
||||
reportMdStr += [
|
||||
'\n---\n',
|
||||
'> [!IMPORTANT]',
|
||||
`> There are **${badCount}** diffs found in this PR: ${summaryLine}.`,
|
||||
'> **Please check all items:**',
|
||||
hasMore && '> - [ ] Checked all diffs in the full report',
|
||||
'> - [ ] Visual diff is acceptable',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
// convert fullVersionMd to html
|
||||
|
Loading…
Reference in New Issue
Block a user