Merge branch 'master' into feature-merge-master

This commit is contained in:
kiner-tang(文辉) 2023-09-16 11:11:47 +08:00
commit 4717b5c649
176 changed files with 1504 additions and 1281 deletions

View File

@ -41,6 +41,7 @@ const SiteThemeProvider: FC<ThemeProviderProps> = ({ children, theme, ...rest })
theme={theme}
customToken={{
headerHeight: 64,
bannerHeight: 38,
menuItemBorder: 2,
mobileMaxWidth: 767.99,
siteMarkdownCodeBg: token.colorFillTertiary,

View File

@ -80,7 +80,7 @@ const { Title } = Typography;
const Overview: React.FC = () => {
const { styles } = useStyle();
const { theme } = useContext(SiteContext);
const { theme, bannerVisible } = useContext(SiteContext);
const data = useSidebarData();
const [searchBarAffixed, setSearchBarAffixed] = useState<boolean>(false);
@ -143,7 +143,10 @@ const Overview: React.FC = () => {
return (
<section className="markdown" ref={sectionRef}>
<Divider />
<Affix offsetTop={24 + token.headerHeight} onChange={setSearchBarAffixed}>
<Affix
offsetTop={24 + token.headerHeight + (bannerVisible ? token.bannerHeight : 0)}
onChange={setSearchBarAffixed}
>
<div
className={styles.componentsOverviewAffix}
style={searchBarAffixed ? affixedStyle : {}}

View File

@ -1,4 +1,4 @@
import React, { useCallback, useMemo, useState } from 'react';
import React, { useCallback, useContext, useMemo, useState } from 'react';
import type { CSSProperties } from 'react';
import Icon, * as AntdIcons from '@ant-design/icons';
import type { IntlShape } from 'react-intl';
@ -11,6 +11,7 @@ import Category from './Category';
import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons';
import type { CategoriesKeys } from './fields';
import { categories } from './fields';
import SiteContext from '../../slots/SiteContext';
export enum ThemeType {
Filled = 'Filled',
@ -59,6 +60,7 @@ const IconSearch: React.FC = () => {
theme: ThemeType.Outlined,
});
const token = useTheme();
const { bannerVisible } = useContext(SiteContext);
const newIconNames: string[] = [];
@ -124,7 +126,10 @@ const IconSearch: React.FC = () => {
return (
<div className="markdown">
<Affix offsetTop={24 + token.headerHeight} onChange={setSearchBarAffixed}>
<Affix
offsetTop={24 + token.headerHeight + (bannerVisible ? token.bannerHeight : 0)}
onChange={setSearchBarAffixed}
>
<div className={styles.iconSearchAffix} style={searchBarAffixed ? affixedStyle : {}}>
<Segmented
size="large"

View File

@ -10,7 +10,7 @@ export default () => {
styles={css`
.nav-phone-icon {
position: absolute;
top: 25px;
bottom: 17px;
right: 30px;
z-index: 1;
display: none;

View File

@ -1,7 +1,7 @@
import classNames from 'classnames';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import { Helmet, useOutlet, useSiteData } from 'dumi';
import { Helmet, useOutlet } from 'dumi';
import React, { useContext, useEffect, useLayoutEffect, useMemo, useRef } from 'react';
import zhCN from 'antd/es/locale/zh_CN';
import ConfigProvider from 'antd/es/config-provider';
@ -30,11 +30,10 @@ const locales = {
const DocLayout: React.FC = () => {
const outlet = useOutlet();
const location = useLocation();
const { pathname, search, hash } = location;
const { pathname, search } = location;
const [locale, lang] = useLocale(locales);
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const { direction } = useContext(SiteContext);
const { loading } = useSiteData();
useLayoutEffect(() => {
if (lang === 'cn') {
@ -53,20 +52,10 @@ const DocLayout: React.FC = () => {
}
}, []);
// handle hash change or visit page hash from Link component, and jump after async chunk loaded
useEffect(() => {
const id = hash.replace('#', '');
if (id) document.getElementById(decodeURIComponent(id))?.scrollIntoView();
}, [loading, hash]);
React.useEffect(() => {
if (typeof (window as any).ga !== 'undefined') {
(window as any).ga('send', 'pageview', pathname + search);
}
if (typeof (window as any)._hmt !== 'undefined') {
(window as any)._hmt.push(['_trackPageview', pathname + search]);
}
}, [location]);
const content = useMemo(() => {

View File

@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useMemo } from 'react';
import React, { useCallback, useEffect, useMemo, startTransition } from 'react';
import {
createCache,
extractStyle,
@ -56,11 +56,13 @@ const GlobalLayout: React.FC = () => {
const { pathname } = useLocation();
const [searchParams, setSearchParams] = useSearchParams();
const [, , setPrefersColor] = usePrefersColor();
const [{ theme = [], direction, isMobile }, setSiteState] = useLayoutState<SiteState>({
isMobile: false,
direction: 'ltr',
theme: [],
});
const [{ theme = [], direction, isMobile, bannerVisible = true }, setSiteState] =
useLayoutState<SiteState>({
isMobile: false,
direction: 'ltr',
theme: [],
bannerVisible: true,
});
const updateSiteConfig = useCallback(
(props: SiteState) => {
@ -84,7 +86,9 @@ const GlobalLayout: React.FC = () => {
...nextSearchParams,
theme: _theme,
});
setPrefersColor(_theme.includes('dark') ? 'dark' : 'light');
startTransition(() => {
setPrefersColor(_theme.includes('dark') ? 'dark' : 'light');
});
}
});
@ -106,8 +110,6 @@ const GlobalLayout: React.FC = () => {
setSiteState({ theme: _theme, direction: _direction === 'rtl' ? 'rtl' : 'ltr' });
// Handle isMobile
updateMobileMode();
// https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
setPrefersColor(_theme.includes('dark') ? 'dark' : 'light');
window.addEventListener('resize', updateMobileMode);
return () => {
@ -121,8 +123,9 @@ const GlobalLayout: React.FC = () => {
updateSiteConfig,
theme: theme!,
isMobile: isMobile!,
bannerVisible,
}),
[isMobile, direction, updateSiteConfig, theme],
[isMobile, direction, updateSiteConfig, theme, bannerVisible],
);
const [styleCache] = React.useState(() => createCache());

View File

@ -4,7 +4,7 @@ import classNames from 'classnames';
import { useLocation, useSiteData } from 'dumi';
import DumiSearchBar from 'dumi/theme-default/slots/SearchBar';
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { Col, Popover, Row, Select } from 'antd';
import { Alert, Col, Popover, Row, Select } from 'antd';
import useLocale from '../../../hooks/useLocale';
import DirectionIcon from '../../common/DirectionIcon';
import * as utils from '../../utils';
@ -20,6 +20,15 @@ import type { SharedProps } from './interface';
const RESPONSIVE_XS = 1120;
const RESPONSIVE_SM = 1200;
const locales = {
cn: {
message:
'语雀公益计划:大学生认证教育邮箱,即可免费获得语雀会员。语雀,支付宝匠心打造的在线文档平台。',
shortMessage: '支付宝语雀 · 大学生公益计划火热进行中!',
more: '了解更多',
},
};
const useStyle = createStyles(({ token, css }) => {
const searchIconColor = '#ced4d9';
@ -106,6 +115,24 @@ const useStyle = createStyles(({ token, css }) => {
padding: 0,
},
},
banner: css`
width: 100%;
background: #daf5eb;
text-align: center;
word-break: keep-all;
`,
link: css`
margin-left: 10px;
@media only screen and (max-width: ${token.mobileMaxWidth}px) {
margin-left: 0;
}
`,
icon: css`
margin-right: 10px;
width: 22px;
height: 22px;
`,
};
});
@ -117,7 +144,7 @@ interface HeaderState {
// ================================= Header =================================
const Header: React.FC = () => {
const [, lang] = useLocale();
const [locale, lang] = useLocale(locales);
const { pkg } = useSiteData();
@ -149,6 +176,9 @@ const Header: React.FC = () => {
const onDirectionChange = () => {
updateSiteConfig({ direction: direction !== 'rtl' ? 'rtl' : 'ltr' });
};
const onBannerClose = () => {
updateSiteConfig({ bannerVisible: false });
};
useEffect(() => {
handleHideMenu();
@ -322,6 +352,40 @@ const Header: React.FC = () => {
<MenuOutlined className="nav-phone-icon" onClick={handleShowMenu} />
</Popover>
)}
{isZhCN && (
<Alert
className={styles.banner}
message={
<>
<img
className={styles.icon}
src="https://gw.alipayobjects.com/zos/rmsportal/XuVpGqBFxXplzvLjJBZB.svg"
alt="yuque"
/>
{isMobile ? locale.shortMessage : locale.message}
<a
className={styles.link}
href="https://www.yuque.com/yuque/blog/welfare-edu?source=antd"
target="_blank"
rel="noreferrer"
onClick={() => {
window.gtag?.('event', '点击', {
event_category: 'top_banner',
event_label: 'https://www.yuque.com/yuque/blog/welfare-edu?source=antd',
});
}}
>
{locale.more}
</a>
</>
}
type="info"
banner
closable
showIcon={false}
onClose={onBannerClose}
/>
)}
<Row style={{ flexFlow: 'nowrap', height: 64 }}>
<Col {...colProps[0]}>
<Logo {...sharedProps} location={location} />

View File

@ -4,6 +4,7 @@ import type { ThemeName } from '../common/ThemeSwitch';
export interface SiteContextProps {
isMobile: boolean;
bannerVisible: boolean;
direction: DirectionType;
theme: ThemeName[];
updateSiteConfig: (props: Partial<SiteContextProps>) => void;
@ -11,6 +12,7 @@ export interface SiteContextProps {
const SiteContext = React.createContext<SiteContextProps>({
isMobile: false,
bannerVisible: true,
direction: 'ltr',
theme: ['light'],
updateSiteConfig: () => {},

View File

@ -1,24 +0,0 @@
name: 🤖 ChatGPT Code Review
permissions:
contents: read
pull-requests: write
on:
pull_request:
types: [opened, reopened, synchronize]
jobs:
test:
runs-on: ubuntu-latest
if: github.event.pull_request.head.ref != 'feature' && github.event.pull_request.head.ref != 'master' && github.event.pull_request.head.ref != 'next' && github.event.pull_request.head.ref != 'master-merge-feature' && github.event.pull_request.head.ref != 'feature-merge-master' && github.event.pull_request.head.ref != 'next-merge-master' && github.event.pull_request.head.ref != 'next-merge-feature'
steps:
- uses: anc95/ChatGPT-CodeReview@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# Optional
LANGUAGE: Chinese
MODEL:
top_p: 1
temperature: 1

View File

@ -22,7 +22,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- uses: actions/cache@v3
with:

View File

@ -74,7 +74,7 @@ jobs:
run: npm run site
env:
SITE_ENV: development
NODE_OPTIONS: --max_old_space_size=4096
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
- name: upload site artifact
uses: actions/upload-artifact@v3

View File

@ -53,7 +53,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: restore cache from package-lock.json
uses: actions/cache@v3
@ -70,13 +70,13 @@ jobs:
- name: build site
run: npm run predeploy
env:
NODE_OPTIONS: "--max_old_space_size=4096"
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
- name: build dist and bundle analyzer report
run: npm run dist
env:
ANALYZER: 1
NODE_OPTIONS: "--max_old_space_size=4096"
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
- name: Get version
id: publish-version

View File

@ -27,7 +27,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: cache package-lock.json
uses: actions/cache@v3
@ -63,5 +63,5 @@ jobs:
build_script: dist
skip_step: install
env:
NODE_OPTIONS: --max_old_space_size=4096
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
PRODUCTION_ONLY: 1

View File

@ -21,7 +21,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: cache package-lock.json
uses: actions/cache@v3
@ -57,7 +57,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: restore cache from package-lock.json
uses: actions/cache@v3
@ -83,7 +83,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: restore cache from package-lock.json
uses: actions/cache@v3
@ -108,7 +108,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: restore cache from package-lock.json
uses: actions/cache@v3
@ -129,9 +129,10 @@ jobs:
key: dist-${{ github.sha }}
- name: dist
run: CI=1 npm run dist
run: npm run dist
env:
NODE_OPTIONS: --max_old_space_size=4096
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
CI: 1
needs: setup
################################ Test ################################
@ -151,7 +152,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: restore cache from package-lock.json
uses: actions/cache@v3
@ -235,7 +236,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- uses: actions/download-artifact@v3
with:
@ -261,7 +262,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: restore cache from package-lock.json
uses: actions/cache@v3
@ -316,7 +317,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- name: restore cache from package-lock.json
# lib only run in master branch not in pull request

6
.npmrc
View File

@ -1 +1,5 @@
package-lock=false
package-lock=false
PUPPETEER_DOWNLOAD_BASE_URL="https://cdn.npmmirror.com/binaries/chrome-for-testing"
npm_config_sharp_libvips_binary_host="https://cdn.npmmirror.com/binaries/sharp-libvips"

View File

@ -16,6 +16,25 @@ tag: vVERSION
---
## 5.9.1
`2023-09-15`
- 🐞 Fix Select that `controlHeightSM` not work in small size. [#44859](https://github.com/ant-design/ant-design/pull/44859) [@MadCcc](https://github.com/MadCcc)
- 🐞 Fix Rate that star transaform not at center. [#44855](https://github.com/ant-design/ant-design/pull/44855) [@MadCcc](https://github.com/MadCcc)
- 🐞 Fix DatePicker that in `dateTime` mode switching input didn't trigger `onCalendarChange`. [#44845](https://github.com/ant-design/ant-design/pull/44845) [@Yuiai01](https://github.com/Yuiai01)
- 🐞 Fix Table `virtual` selection checkbox or radio not align in center. [#44786](https://github.com/ant-design/ant-design/pull/44786)
- 🐞 Fix Select carbin align top bug when enable `maxTagCount`. [#44757](https://github.com/ant-design/ant-design/pull/44757)
- 🐞 Fix Select alignment issue when label is Typography. [#44756](https://github.com/ant-design/ant-design/pull/44756)
- 💄 Fix Table with `virtual` display issue about columns less than table size and some border &amp; hover style missing. [#44818](https://github.com/ant-design/ant-design/pull/44818)
- 💄 Fix wrong style of Select in Input `addon`. [#44825](https://github.com/ant-design/ant-design/pull/44825) [@MadCcc](https://github.com/MadCcc)
- 💄 Fix Tree that Checkbox should be aligned with first line. [#44827](https://github.com/ant-design/ant-design/pull/44827) [@MadCcc](https://github.com/MadCcc)
- 💄 Fix Card that Card.Grid has wrong style with left bottom corner. [#44801](https://github.com/ant-design/ant-design/pull/44801) [@Jason-huang66](https://github.com/Jason-huang66)
- 💄 Fix Select/Cascader/TreeSelect style issue when customize their height. [#44753](https://github.com/ant-design/ant-design/pull/44753)
- TypeScript
- 🤖 Optimize `ref` type of Radio.Button. [#44747](https://github.com/ant-design/ant-design/pull/44747) [@LexiosAlex](https://github.com/LexiosAlex)
- 🤖 Optimize `ref` type of Checkbox. [#44746](https://github.com/ant-design/ant-design/pull/44746) [@LexiosAlex](https://github.com/LexiosAlex)
## 5.9.0
`2023-09-08`

View File

@ -16,6 +16,25 @@ tag: vVERSION
---
## 5.9.1
`2023-09-15`
- 🐞 修复小尺寸 Select 组件 `controlHeightSM` token 配置无效的问题。[#44859](https://github.com/ant-design/ant-design/pull/44859) [@MadCcc](https://github.com/MadCcc)
- 🐞 修复 Rate 组件星星变换中心不在正中心的问题。[#44855](https://github.com/ant-design/ant-design/pull/44855) [@MadCcc](https://github.com/MadCcc)
- 🐞 修复 DatePicker 组件 `dateTime` 模式切换输入框不会触发 `onCalendarChange` 的问题。[#44845](https://github.com/ant-design/ant-design/pull/44845) [@Yuiai01](https://github.com/Yuiai01)
- 🐞 修复 Table `virtual` 配置下,选择框没有居中对齐的问题。[#44786](https://github.com/ant-design/ant-design/pull/44786)
- 🐞 修复 Select 开启 `maxTagCount` 时搜索光标偏上的问题。[#44757](https://github.com/ant-design/ant-design/pull/44757)
- 🐞 修复 Select 的 label 为 Typography 组件时的选中文本对齐问题。[#44756](https://github.com/ant-design/ant-design/pull/44756)
- 💄 修复 Table `virtual` 开启虚拟滚动时,当 `columns` 小于表格宽度会显示异常的问题以及部分边框、悬浮样式丢失的问题。[#44818](https://github.com/ant-design/ant-design/pull/44818)
- 💄 修复 Select 组件在 Input `addon` 中使用时的样式错误。[#44825](https://github.com/ant-design/ant-design/pull/44825) [@MadCcc](https://github.com/MadCcc)
- 💄 修复 Tree 组件样式,使 Checkbox 与文字第一行对齐。[#44827](https://github.com/ant-design/ant-design/pull/44827) [@MadCcc](https://github.com/MadCcc)
- 💄 修复 Card 组件 Card.Grid 边缘样式问题。[#44801](https://github.com/ant-design/ant-design/pull/44801) [@Jason-huang66](https://github.com/Jason-huang66)
- 💄 修复 Select/Cascader/TreeSelect 自定义高度时的样式问题。[#44753](https://github.com/ant-design/ant-design/pull/44753)
- TypeScript
- 🤖 优化 Radio.Button 的 `ref` 类型。[#44747](https://github.com/ant-design/ant-design/pull/44747) [@LexiosAlex](https://github.com/LexiosAlex)
- 🤖 优化 Checkbox 的 `ref` 类型。[#44746](https://github.com/ant-design/ant-design/pull/44746) [@LexiosAlex](https://github.com/LexiosAlex)
## 5.9.0
`2023-09-08`
@ -49,7 +68,7 @@ tag: vVERSION
- 💄 修复 Select 配置的 `getPopupContainer` 容器有 `transform: scale` 样式时,弹出框宽度与输入框不一致的情况。[#44378](https://github.com/ant-design/ant-design/pull/44378)
- 🐞 修复 Form.Item 配置 `noStyle` 时,被绑定的元素无法消费 `useStatus` 的问题。[#44576](https://github.com/ant-design/ant-design/pull/44576)
- 🐞 修复 Tag 被 Popover/Popconfirm 包裹时Hover 会导致 `font-size` 错误的问题。[#44663](https://github.com/ant-design/ant-design/pull/44663)
- 🐞 修复 Input.Search 组合中,搜索按钮额外阴影的问题。[#44660](https://github.com/ant-design/ant-design/pull/44660) [@daledelv](https://github.com/daledelv)
- 🐞 修复 Input.Search 组合中,搜索按钮存在额外阴影的问题。[#44660](https://github.com/ant-design/ant-design/pull/44660) [@daledelv](https://github.com/daledelv)
- 🐞 修复 Modal 的 hooks 调用通过按键 `esc` 关闭时无法正确触发 await 的问题。[#44646](https://github.com/ant-design/ant-design/pull/44646)
- 🐞 修复 Space 的预设 `size` 不会跟随 Design Token 的问题,现在紧凑模式也会正确处理对应的间距数值。[#44598](https://github.com/ant-design/ant-design/pull/44598) [@li-jia-nan](https://github.com/li-jia-nan)
- 🐞 修复 Upload 组件点击某文件的下载按钮后,鼠标移出该文件时仍展示下载按钮的问题。[#44594](https://github.com/ant-design/ant-design/pull/44594) [@zbw-zbw](https://github.com/zbw-zbw)

View File

@ -1,3 +1,7 @@
import { render } from '@testing-library/react';
import React from 'react';
import { devUseWarning as useWarning } from '../warning';
describe('Test warning', () => {
let spy: jest.SpyInstance;
@ -40,13 +44,40 @@ describe('Test warning', () => {
expect(spy).not.toHaveBeenCalled();
});
it('should show warning when using devUseWarning', async () => {
const App = () => {
// Don't use dynamic import to fixed issue: TypeError: Cannot read properties of null (reading 'useContext')
const warning = useWarning('Test');
warning(false, 'usage', 'test message');
warning.deprecated(false, 'old prop', 'new prop');
return null;
};
render(<App />);
expect(spy).toHaveBeenCalledWith('Warning: [antd: Test] test message');
expect(spy).toHaveBeenCalledWith(
'Warning: [antd: Test] `old prop` is deprecated. Please use `new prop` instead.',
);
expect(spy).toHaveBeenCalledTimes(2);
});
});
describe('process.env.NODE_ENV === "production"', () => {
it('Whether `true` or `false`, do not exec `console.error`', async () => {
const prevEnv = process.env.NODE_ENV;
let prevEnv: string | undefined;
const mockNodeEnv = () => {
prevEnv = process.env.NODE_ENV;
process.env.NODE_ENV = 'production';
};
const restoreNodeEnv = () => {
process.env.NODE_ENV = prevEnv;
};
beforeEach(() => {
mockNodeEnv();
});
afterEach(() => {
restoreNodeEnv();
});
it('Whether `true` or `false`, do not exec `console.error`', async () => {
const { default: warning, noop } = await import('../warning');
expect(warning).toEqual(noop);
@ -56,8 +87,19 @@ describe('Test warning', () => {
warning(true, 'error message');
expect(spy).not.toHaveBeenCalled();
});
process.env.NODE_ENV = prevEnv;
it('should not show warning when using devUseWarning', async () => {
const { devUseWarning } = await import('../warning');
const App = () => {
const warning = devUseWarning('Test');
warning(false, 'usage', 'test message');
warning.deprecated(false, 'old prop', 'new prop');
return null;
};
render(<App />);
expect(spy).toHaveBeenCalledTimes(0);
});
});
});

View File

@ -25,9 +25,8 @@ if (process.env.NODE_ENV !== 'production') {
};
}
type TypeWarning = (
type BaseTypeWarning = (
valid: boolean,
component: string,
/**
* - deprecated: Some API will be removed in future but still support now.
* - usage: Some API usage is not correct.
@ -37,6 +36,10 @@ type TypeWarning = (
message?: string,
) => void;
type TypeWarning = BaseTypeWarning & {
deprecated: (valid: boolean, oldProp: string, newProp: string, message?: string) => void;
};
export interface WarningContextProps {
strict?: boolean;
}
@ -48,12 +51,12 @@ export const WarningContext = React.createContext<WarningContextProps>({});
* since this is only used in development.
* We should always wrap this in `if (process.env.NODE_ENV !== 'production')` condition
*/
export const devUseWarning: () => TypeWarning =
export const devUseWarning: (component: string) => TypeWarning =
process.env.NODE_ENV !== 'production'
? () => {
? (component) => {
const { strict } = React.useContext(WarningContext);
const typeWarning: TypeWarning = (valid, component, type, message) => {
const typeWarning: TypeWarning = (valid, type, message) => {
if (!valid) {
if (strict === false && type === 'deprecated') {
const existWarning = deprecatedWarnList;
@ -81,8 +84,24 @@ export const devUseWarning: () => TypeWarning =
}
};
typeWarning.deprecated = (valid, oldProp, newProp, message) => {
typeWarning(
valid,
'deprecated',
`\`${oldProp}\` is deprecated. Please use \`${newProp}\` instead.${
message ? ` ${message}` : ''
}`,
);
};
return typeWarning;
}
: () => noop;
: () => {
const noopWarning: TypeWarning = () => {};
noopWarning.deprecated = noop;
return noopWarning;
};
export default warning;

View File

@ -120,15 +120,10 @@ const Alert: React.FC<AlertProps> = (props) => {
const [closed, setClosed] = React.useState(false);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
warning(
!closeText,
'Alert',
'deprecated',
'`closeText` is deprecated. Please use `closeIcon` instead.',
);
const warning = devUseWarning('Alert');
warning.deprecated(!closeText, 'closeText', 'closeIcon');
}
const ref = React.useRef<HTMLDivElement>(null);
const { getPrefixCls, direction, alert } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('alert', customizePrefixCls);

View File

@ -132,18 +132,12 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Anchor');
warning(
!children,
'Anchor',
'deprecated',
'`Anchor children` is deprecated. Please use `items` instead.',
);
warning.deprecated(!children, 'Anchor children', 'items');
warning(
!(anchorDirection === 'horizontal' && items?.some((n) => 'children' in n)),
'Anchor',
'usage',
'`Anchor items#children` is not supported when `Anchor` direction is horizontal.',
);

View File

@ -52,11 +52,10 @@ const AnchorLink: React.FC<AnchorLinkProps> = (props) => {
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Anchor.Link');
warning(
!children || direction !== 'horizontal',
'Anchor.Link',
'usage',
'`Anchor.Link children` is not supported when `Anchor` direction is horizontal',
);

View File

@ -288,39 +288,6 @@ Array [
Part 3
</a>
</div>
<div
class="ant-anchor-link"
>
<a
class="ant-anchor-link-title"
href="#part-4"
title="Part 4"
>
Part 4
</a>
</div>
<div
class="ant-anchor-link"
>
<a
class="ant-anchor-link-title"
href="#part-5"
title="Part 5"
>
Part 5
</a>
</div>
<div
class="ant-anchor-link"
>
<a
class="ant-anchor-link-title"
href="#part-6"
title="Part 6"
>
Part 6
</a>
</div>
</div>
</div>
</div>
@ -339,18 +306,6 @@ Array [
id="part-3"
style="width: 100vw; height: 100vh; text-align: center; background: rgb(255, 251, 233);"
/>
<div
id="part-4"
style="width: 100vw; height: 100vh; text-align: center; background: rgb(244, 234, 213);"
/>
<div
id="part-5"
style="width: 100vw; height: 100vh; text-align: center; background: rgb(218, 226, 182);"
/>
<div
id="part-6"
style="width: 100vw; height: 100vh; text-align: center; background: rgb(204, 214, 166);"
/>
</div>,
]
`;

View File

@ -278,39 +278,6 @@ Array [
Part 3
</a>
</div>
<div
class="ant-anchor-link"
>
<a
class="ant-anchor-link-title"
href="#part-4"
title="Part 4"
>
Part 4
</a>
</div>
<div
class="ant-anchor-link"
>
<a
class="ant-anchor-link-title"
href="#part-5"
title="Part 5"
>
Part 5
</a>
</div>
<div
class="ant-anchor-link"
>
<a
class="ant-anchor-link-title"
href="#part-6"
title="Part 6"
>
Part 6
</a>
</div>
</div>
</div>
</div>
@ -329,18 +296,6 @@ Array [
id="part-3"
style="width:100vw;height:100vh;text-align:center;background:#FFFBE9"
/>
<div
id="part-4"
style="width:100vw;height:100vh;text-align:center;background:#F4EAD5"
/>
<div
id="part-5"
style="width:100vw;height:100vh;text-align:center;background:#DAE2B6"
/>
<div
id="part-6"
style="width:100vw;height:100vh;text-align:center;background:#CCD6A6"
/>
</div>,
]
`;

View File

@ -1,5 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Anchor image', () => {
imageDemoTest('anchor');
imageDemoTest('anchor', { onlyViewport: true });
});

View File

@ -22,21 +22,6 @@ const App: React.FC = () => (
href: '#part-3',
title: 'Part 3',
},
{
key: 'part-4',
href: '#part-4',
title: 'Part 4',
},
{
key: 'part-5',
href: '#part-5',
title: 'Part 5',
},
{
key: 'part-6',
href: '#part-6',
title: 'Part 6',
},
]}
/>
</div>
@ -63,18 +48,6 @@ const App: React.FC = () => (
id="part-3"
style={{ width: '100vw', height: '100vh', textAlign: 'center', background: '#FFFBE9' }}
/>
<div
id="part-4"
style={{ width: '100vw', height: '100vh', textAlign: 'center', background: '#F4EAD5' }}
/>
<div
id="part-5"
style={{ width: '100vw', height: '100vh', textAlign: 'center', background: '#DAE2B6' }}
/>
<div
id="part-6"
style={{ width: '100vw', height: '100vh', textAlign: 'center', background: '#CCD6A6' }}
/>
</div>
</>
);

View File

@ -1887,7 +1887,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
exports[`renders components/auto-complete/demo/form-debug.tsx extend context correctly 2`] = `
[
"Warning: [antd: Input.Group] 'Input.Group' is deprecated. Please use 'Space.Compact' instead.",
"Warning: [antd: Input.Group] \`Input.Group\` is deprecated. Please use \`Space.Compact\` instead.",
]
`;

View File

@ -110,7 +110,7 @@ describe('AutoComplete', () => {
/>,
);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: AutoComplete] `dropdownClassName` is deprecated, please use `popupClassName` instead.',
'Warning: [antd: AutoComplete] `dropdownClassName` is deprecated. Please use `popupClassName` instead.',
);
expect(container.querySelector('.legacy')).toBeTruthy();

View File

@ -111,28 +111,17 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
}
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('AutoComplete');
warning(
!('dataSource' in props),
'AutoComplete',
'deprecated',
'`dataSource` is deprecated, please use `options` instead.',
);
warning.deprecated(!('dataSource' in props), 'dataSource', 'options');
warning(
!customizeInput || !('size' in props),
'AutoComplete',
'usage',
'You need to control style self instead of setting `size` when using customize input.',
);
warning(
!dropdownClassName,
'AutoComplete',
'deprecated',
'`dropdownClassName` is deprecated, please use `popupClassName` instead.',
);
warning.deprecated(!dropdownClassName, 'dropdownClassName', 'popupClassName');
}
const { getPrefixCls } = React.useContext<ConfigConsumerProps>(ConfigContext);

View File

@ -134,11 +134,10 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
}, [screens, size]);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Avatar');
warning(
!(typeof icon === 'string' && icon.length > 2),
'Avatar',
'breaking',
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,
);

View File

@ -17,7 +17,7 @@ Array [
exports[`renders components/back-top/demo/basic.tsx extend context correctly 2`] = `
[
"Warning: [antd: BackTop] \`BackTop\` is deprecated, please use \`FloatButton.BackTop\` instead.",
"Warning: [antd: BackTop] \`BackTop\` is deprecated. Please use \`FloatButton.BackTop\` instead.",
]
`;
@ -54,6 +54,6 @@ exports[`renders components/back-top/demo/custom.tsx extend context correctly 1`
exports[`renders components/back-top/demo/custom.tsx extend context correctly 2`] = `
[
"Warning: [antd: BackTop] \`BackTop\` is deprecated, please use \`FloatButton.BackTop\` instead.",
"Warning: [antd: BackTop] \`BackTop\` is deprecated. Please use \`FloatButton.BackTop\` instead.",
]
`;

View File

@ -1,5 +0,0 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('BackTop image', () => {
imageDemoTest('back-top');
});

View File

@ -47,7 +47,7 @@ describe('BackTop', () => {
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
render(<BackTop />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: BackTop] `BackTop` is deprecated, please use `FloatButton.BackTop` instead.',
'Warning: [antd: BackTop] `BackTop` is deprecated. Please use `FloatButton.BackTop` instead.',
);
errSpy.mockRestore();
});

View File

@ -50,14 +50,9 @@ const BackTop: React.FC<BackTopProps> = (props) => {
);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('BackTop');
warning(
false,
'BackTop',
'deprecated',
'`BackTop` is deprecated, please use `FloatButton.BackTop` instead.',
);
warning.deprecated(false, 'BackTop', 'FloatButton.BackTop');
}
React.useEffect(() => {

View File

@ -99,24 +99,17 @@ const Breadcrumb = <T extends AnyObject = AnyObject>(props: BreadcrumbProps<T>)
const mergedItems = useItems(items, legacyRoutes);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
warning(
!legacyRoutes,
'Breadcrumb',
'deprecated',
'`routes` is deprecated. Please use `items` instead.',
);
const warning = devUseWarning('Breadcrumb');
warning.deprecated(!legacyRoutes, 'routes', 'items');
// Deprecated warning for breadcrumb children
if (!mergedItems || mergedItems.length === 0) {
const childList = toArray(children);
warning(
warning.deprecated(
childList.length === 0,
'Breadcrumb',
'deprecated',
'`Breadcrumb.Item and Breadcrumb.Separator` is deprecated. Please use `items` instead.',
'Breadcrumb.Item and Breadcrumb.Separator',
'items',
);
childList.forEach((element: any) => {
@ -125,7 +118,6 @@ const Breadcrumb = <T extends AnyObject = AnyObject>(props: BreadcrumbProps<T>)
element.type &&
(element.type.__ANT_BREADCRUMB_ITEM === true ||
element.type.__ANT_BREADCRUMB_SEPARATOR === true),
'Breadcrumb',
'usage',
"Only accepts Breadcrumb.Item and Breadcrumb.Separator as it's children",
);

View File

@ -1,12 +1,12 @@
import DownOutlined from '@ant-design/icons/DownOutlined';
import * as React from 'react';
import { devUseWarning } from '../_util/warning';
import { ConfigContext } from '../config-provider';
import type { DropdownProps } from '../dropdown/dropdown';
import Dropdown from '../dropdown/dropdown';
import type { ItemType } from './Breadcrumb';
import BreadcrumbSeparator from './BreadcrumbSeparator';
import { renderItem } from './useItemRender';
import { devUseWarning } from '../_util/warning';
export interface SeparatorType {
separator?: React.ReactNode;
@ -42,14 +42,9 @@ export const InternalBreadcrumbItem: React.FC<BreadcrumbItemProps> = (props) =>
// Warning for deprecated usage
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Breadcrumb.Item');
warning(
!('overlay' in props),
'Breadcrumb.Item',
'deprecated',
'`overlay` is deprecated. Please use `menu` instead.',
);
warning.deprecated(!('overlay' in props), 'overlay', 'menu');
}
/** If overlay is have Wrap a Dropdown */

View File

@ -39,14 +39,9 @@ const ButtonGroup: React.FC<ButtonGroupProps> = (props) => {
}
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Button.Group');
warning(
!size || ['large', 'small', 'middle'].includes(size),
'Button.Group',
'usage',
'Invalid prop `size`.',
);
warning(!size || ['large', 'small', 'middle'].includes(size), 'usage', 'Invalid prop `size`.');
}
const classes = classNames(

View File

@ -184,18 +184,16 @@ const InternalButton: React.ForwardRefRenderFunction<
};
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Button');
warning(
!(typeof icon === 'string' && icon.length > 2),
'Button',
'breaking',
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,
);
warning(
!(ghost && isUnBorderedButtonType(type)),
'Button',
'usage',
"`link` or `text` button can't be a `ghost` button.",
);

View File

@ -125,32 +125,12 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
// ====================== Warning =======================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Calendar');
warning(
!dateFullCellRender,
'Calendar',
'deprecated',
'`dateFullCellRender` is deprecated. Please use `fullCellRender` instead.',
);
warning(
!dateCellRender,
'Calendar',
'deprecated',
'`dateCellRender` is deprecated. Please use `cellRender` instead.',
);
warning(
!monthFullCellRender,
'Calendar',
'deprecated',
'`monthFullCellRender` is deprecated. Please use `fullCellRender` instead.',
);
warning(
!monthCellRender,
'Calendar',
'deprecated',
'`monthCellRender` is deprecated. Please use `cellRender` instead.',
);
warning.deprecated(!dateFullCellRender, 'dateFullCellRender', 'fullCellRender');
warning.deprecated(!dateCellRender, 'dateCellRender', 'cellRender');
warning.deprecated(!monthFullCellRender, 'monthFullCellRender', 'fullCellRender');
warning.deprecated(!monthCellRender, 'monthCellRender', 'cellRender');
}
// ====================== State =======================

View File

@ -349,6 +349,7 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
},
[`${componentCls}-contain-grid`]: {
borderRadius: `${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0 `,
[`${componentCls}-body`]: {
display: 'flex',
flexWrap: 'wrap',

View File

@ -194,18 +194,12 @@ const Cascader = React.forwardRef<CascaderRef, CascaderProps<any>>((props, ref)
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Cascader');
warning(
!dropdownClassName,
'Cascader',
'deprecated',
'`dropdownClassName` is deprecated. Please use `popupClassName` instead.',
);
warning.deprecated(!dropdownClassName, 'dropdownClassName', 'popupClassName');
warning(
!('showArrow' in props),
'Cascader',
'deprecated',
'`showArrow` is deprecated which will be removed in next major version. It will be a default behavior, you can hide it by setting `suffixIcon` to null.',
);

View File

@ -78,11 +78,10 @@ const InternalCheckbox: React.ForwardRefRenderFunction<CheckboxRef, CheckboxProp
const prevValue = React.useRef(restProps.value);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Checkbox');
warning(
'checked' in restProps || !!checkboxGroup || !('value' in restProps),
'Checkbox',
'usage',
'`value` is not a valid prop, do you mean `checked`?',
);

View File

@ -79,12 +79,11 @@ const Collapse = React.forwardRef<HTMLDivElement, CollapseProps>((props, ref) =>
const [wrapSSR, hashId] = useStyle(prefixCls);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Collapse');
// Warning if use legacy type `expandIconPosition`
warning(
expandIconPosition !== 'left' && expandIconPosition !== 'right',
'Collapse',
'deprecated',
'`expandIconPosition` with `left` or `right` is deprecated. Please use `start` or `end` instead.',
);

View File

@ -25,14 +25,9 @@ export interface CollapsePanelProps {
const CollapsePanel = React.forwardRef<HTMLDivElement, CollapsePanelProps>((props, ref) => {
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Collapse.Panel');
warning(
!('disabled' in props),
'Collapse.Panel',
'deprecated',
'`disabled` is deprecated. Please use `collapsible="disabled"` instead.',
);
warning.deprecated(!('disabled' in props), 'disabled', 'collapsible="disabled"');
}
const { getPrefixCls } = React.useContext(ConfigContext);

View File

@ -151,11 +151,10 @@ const ColorPicker: CompoundedComponent = (props) => {
// ===================== Warning ======================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('ColorPicker');
warning(
!(disabledAlpha && isAlphaColor),
'ColorPicker',
'usage',
'`disabledAlpha` will make the alpha to be 100% when use alpha color.',
);

View File

@ -11,13 +11,12 @@ export interface PropWarningProps {
* This will be empty function in production.
*/
const PropWarning = React.memo(({ dropdownMatchSelectWidth }: PropWarningProps) => {
const warning = devUseWarning();
const warning = devUseWarning('ConfigProvider');
warning(
warning.deprecated(
dropdownMatchSelectWidth === undefined,
'ConfigProvider',
'deprecated',
'`dropdownMatchSelectWidth` is deprecated. Please use `popupMatchSelectWidth` instead.',
'dropdownMatchSelectWidth',
'popupMatchSelectWidth',
);
return null;

View File

@ -1,41 +1,33 @@
import React from 'react';
import { DatePicker, Space } from 'antd';
import { DatePicker, Space, theme } from 'antd';
import type { Dayjs } from 'dayjs';
import type { CellRenderInfo } from 'rc-picker/es/interface';
const { RangePicker } = DatePicker;
const App: React.FC = () => (
<Space direction="vertical" size={12}>
<DatePicker
cellRender={(current, info) => {
if (info.type !== 'date') return info.originNode;
const style: React.CSSProperties = {};
if (current.date() === 1) {
style.border = '1px solid #1677ff';
style.borderRadius = '50%';
}
return (
<div className="ant-picker-cell-inner" style={style}>
{current.date()}
</div>
);
}}
/>
<RangePicker
cellRender={(current, info) => {
if (info.type !== 'date') return info.originNode;
const style: React.CSSProperties = {};
if (current.date() === 1) {
style.border = '1px solid #1677ff';
style.borderRadius = '50%';
}
return (
<div className="ant-picker-cell-inner" style={style}>
{current.date()}
</div>
);
}}
/>
</Space>
);
const App: React.FC = () => {
const { token } = theme.useToken();
const style: React.CSSProperties = {
border: `1px solid ${token.colorPrimary}`,
borderRadius: '50%',
};
const cellRender = React.useCallback((current: number | Dayjs, info: CellRenderInfo<Dayjs>) => {
if (info.type !== 'date') {
return info.originNode;
}
if (typeof current === 'number') {
return <div className="ant-picker-cell-inner">{current}</div>;
}
return (
<div className="ant-picker-cell-inner" style={current.date() === 1 ? style : {}}>
{current.date()}
</div>
);
}, []);
return (
<Space size={12} direction="vertical">
<DatePicker cellRender={cellRender} />
<DatePicker.RangePicker cellRender={cellRender} />
</Space>
);
};
export default App;

View File

@ -78,14 +78,9 @@ export default function generateRangePicker<DateType>(generateConfig: GenerateCo
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('DatePicker.RangePicker');
warning(
!dropdownClassName,
'DatePicker.RangePicker',
'deprecated',
'`dropdownClassName` is deprecated. Please use `popupClassName` instead.',
);
warning.deprecated(!dropdownClassName, 'dropdownClassName', 'popupClassName');
}
// ===================== Size =====================

View File

@ -106,21 +106,15 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning(displayName! || 'DatePicker');
warning(
picker !== 'quarter',
displayName!,
'deprecated',
`DatePicker.${displayName} is legacy usage. Please use DatePicker[picker='${picker}'] directly.`,
);
warning(
!dropdownClassName,
displayName || 'DatePicker',
'deprecated',
'`dropdownClassName` is deprecated. Please use `popupClassName` instead.',
);
warning.deprecated(!dropdownClassName, 'dropdownClassName', 'popupClassName');
}
// ===================== Size =====================

View File

@ -1,5 +1,6 @@
import type { Dayjs } from 'dayjs';
import dayjsGenerateConfig from 'rc-picker/lib/generate/dayjs';
import genPurePanel from '../_util/PurePanel';
import type {
RangePickerProps as BaseRangePickerProps,

View File

@ -69,14 +69,9 @@ const useRow = (mergedColumn: number, items: InternalDescriptionsItemType[]) =>
const [rows, exceed] = useMemo(() => getCalcRows(items, mergedColumn), [items, mergedColumn]);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Descriptions');
warning(
!exceed,
'Descriptions',
'usage',
'Sum of column `span` in a line not match `column` of Descriptions.',
);
warning(!exceed, 'usage', 'Sum of column `span` in a line not match `column` of Descriptions.');
}
return rows;

View File

@ -76,11 +76,10 @@ const Divider: React.FC<DividerProps> = (props) => {
// Warning children not work in vertical mode
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Divider');
warning(
!children || type !== 'vertical',
'Divider',
'usage',
'`children` not working in `vertical` mode.',
);

View File

@ -135,10 +135,10 @@ describe('Drawer', () => {
expect(afterVisibleChange).toHaveBeenCalledTimes(1);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: Drawer] `visible` is deprecated, please use `open` instead.',
'Warning: [antd: Drawer] `visible` is deprecated. Please use `open` instead.',
);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: Drawer] `afterVisibleChange` is deprecated, please use `afterOpenChange` instead.',
'Warning: [antd: Drawer] `afterVisibleChange` is deprecated. Please use `afterOpenChange` instead.',
);
errorSpy.mockRestore();

View File

@ -88,24 +88,18 @@ const Drawer: React.FC<DrawerProps> & {
// ========================== Warning ===========================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Drawer');
[
['visible', 'open'],
['afterVisibleChange', 'afterOpenChange'],
].forEach(([deprecatedName, newName]) => {
warning(
!(deprecatedName in props),
'Drawer',
'deprecated',
`\`${deprecatedName}\` is deprecated, please use \`${newName}\` instead.`,
);
warning.deprecated(!(deprecatedName in props), deprecatedName, newName);
});
if (getContainer !== undefined && props.style?.position === 'absolute') {
warning(
false,
'Drawer',
'breaking',
'`style` is replaced by `rootStyle` in v5. Please check that `position: absolute` is necessary.',
);

View File

@ -8454,8 +8454,7 @@ exports[`renders components/dropdown/demo/render-panel.tsx extend context correc
exports[`renders components/dropdown/demo/render-panel.tsx extend context correctly 2`] = `
[
"Warning: [antd: Dropdown] \`visible\` is deprecated which will be removed in next major version, please use \`open\` instead.",
"Warning: [antd: Dropdown] \`visible\` is deprecated, please use \`open\` instead.",
"Warning: [antd: Dropdown] \`visible\` is deprecated. Please use \`open\` instead.",
]
`;

View File

@ -231,10 +231,10 @@ describe('Dropdown', () => {
expect(document.querySelector('.bamboo')).toBeTruthy();
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: Dropdown] `visible` is deprecated, please use `open` instead.',
'Warning: [antd: Dropdown] `visible` is deprecated. Please use `open` instead.',
);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: Dropdown] `onVisibleChange` is deprecated, please use `onOpenChange` instead.',
'Warning: [antd: Dropdown] `onVisibleChange` is deprecated. Please use `onOpenChange` instead.',
);
fireEvent.click(container.querySelector('.little')!);

View File

@ -109,27 +109,17 @@ const Dropdown: CompoundedComponent = (props) => {
} = React.useContext(ConfigContext);
// Warning for deprecated usage
const warning = devUseWarning();
const warning = devUseWarning('Dropdown');
if (process.env.NODE_ENV !== 'production') {
[
['visible', 'open'],
['onVisibleChange', 'onOpenChange'],
].forEach(([deprecatedName, newName]) => {
warning(
!(deprecatedName in props),
'Dropdown',
'deprecated',
`\`${deprecatedName}\` is deprecated which will be removed in next major version, please use \`${newName}\` instead.`,
);
warning.deprecated(!(deprecatedName in props), deprecatedName, newName);
});
warning(
!('overlay' in props),
'Dropdown',
'deprecated',
'`overlay` is deprecated. Please use `menu` instead.',
);
warning.deprecated(!('overlay' in props), 'overlay', 'menu');
}
const memoTransitionName = React.useMemo<string>(() => {
@ -161,7 +151,6 @@ const Dropdown: CompoundedComponent = (props) => {
const newPlacement = placement.slice(0, placement.indexOf('Center')) as DropdownPlacement;
warning(
!placement.includes('Center'),
'Dropdown',
'deprecated',
`You are using '${placement}' placement in Dropdown, which is deprecated. Try to use '${newPlacement}' instead.`,
);
@ -171,12 +160,7 @@ const Dropdown: CompoundedComponent = (props) => {
['visible', 'open'],
['onVisibleChange', 'onOpenChange'],
].forEach(([deprecatedName, newName]) => {
warning(
!(deprecatedName in props),
'Dropdown',
'deprecated',
`\`${deprecatedName}\` is deprecated, please use \`${newName}\` instead.`,
);
warning.deprecated(!(deprecatedName in props), deprecatedName, newName);
});
}
@ -266,7 +250,6 @@ const Dropdown: CompoundedComponent = (props) => {
// Warning if use other mode
warning(
!mode || mode === 'vertical',
'Dropdown',
'usage',
`mode="${mode}" is not supported for Dropdown's Menu.`,
);

View File

@ -85,11 +85,10 @@ const FloatButton: React.ForwardRefRenderFunction<
}
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('FloatButton');
warning(
!(shape === 'circle' && description),
'FloatButton',
'usage',
'supported only when `shape` is `square`. Due to narrow space for text, short sentence is recommended.',
);

View File

@ -94,11 +94,10 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('FloatButton.Group');
warning(
!('open' in props) || !!trigger,
'FloatButton.Group',
'usage',
'`open` need to be used together with `trigger`',
);

View File

@ -2,7 +2,7 @@
exports[`renders components/float-button/demo/back-top.tsx extend context correctly 1`] = `
<div
style="height: 500vh; padding: 10px;"
style="height: 300vh; padding: 10px;"
>
<div>
Scroll to bottom

View File

@ -2,7 +2,7 @@
exports[`renders components/float-button/demo/back-top.tsx correctly 1`] = `
<div
style="height:500vh;padding:10px"
style="height:300vh;padding:10px"
>
<div>
Scroll to bottom

View File

@ -1,5 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('float-button image', () => {
imageDemoTest('float-button');
imageDemoTest('float-button', { splitTheme: true, onlyViewport: ['back-top.tsx'] });
});

View File

@ -2,7 +2,7 @@ import React from 'react';
import { FloatButton } from 'antd';
const App: React.FC = () => (
<div style={{ height: '500vh', padding: 10 }}>
<div style={{ height: '300vh', padding: 10 }}>
<div>Scroll to bottom</div>
<div>Scroll to bottom</div>
<div>Scroll to bottom</div>

View File

@ -129,10 +129,10 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
const [wrapSSR, hashId] = useStyle(prefixCls);
// ========================= Warn =========================
const warning = devUseWarning();
const warning = devUseWarning('Form.Item');
if (process.env.NODE_ENV !== 'production') {
warning(name !== null, 'Form.Item', 'usage', '`null` is passed as `name` property');
warning(name !== null, 'usage', '`null` is passed as `name` property');
}
// ========================= MISC =========================
@ -307,14 +307,12 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
warning(
!(shouldUpdate && dependencies),
'Form.Item',
'usage',
"`shouldUpdate` and `dependencies` shouldn't be used together. See https://u.ant.design/form-deps.",
);
if (Array.isArray(mergedChildren) && hasName) {
warning(
false,
'Form.Item',
'usage',
'A `Form.Item` with a `name` prop must have a single child element. For information on how to render more complex form items, see https://u.ant.design/complex-form-item.',
);
@ -322,27 +320,23 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
} else if (isRenderProps && (!(shouldUpdate || dependencies) || hasName)) {
warning(
!!(shouldUpdate || dependencies),
'Form.Item',
'usage',
'A `Form.Item` with a render function must have either `shouldUpdate` or `dependencies`.',
);
warning(
!hasName,
'Form.Item',
'usage',
'A `Form.Item` with a render function cannot be a field, and thus cannot have a `name` prop.',
);
} else if (dependencies && !isRenderProps && !hasName) {
warning(
false,
'Form.Item',
'usage',
'Must set `name` or use a render function when `dependencies` is set.',
);
} else if (isValidElement(mergedChildren)) {
warning(
mergedChildren.props.defaultValue === undefined,
'Form.Item',
'usage',
'`defaultValue` will not work on controlled Field. You should use `initialValues` of Form instead.',
);
@ -409,7 +403,6 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
} else {
warning(
!mergedName.length,
'Form.Item',
'usage',
'`name` is only used for validate React element. If you are using Form.Item as layout display, please remove `name` instead.',
);

View File

@ -37,12 +37,11 @@ const FormList: React.FC<FormListProps> = ({
...props
}) => {
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Form.List');
warning(
typeof props.name === 'number' ||
(Array.isArray(props.name) ? !!props.name.length : !!props.name),
'Form.List',
'usage',
'Miss `name` prop.',
);

View File

@ -1662,7 +1662,7 @@ describe('Form', () => {
it('form child components should be given priority to own disabled props when it in a disabled form', () => {
const props = {
name: 'file',
action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
action: 'https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188',
headers: {
authorization: 'authorization-text',
},

View File

@ -14,11 +14,10 @@ const useFormItemStatus: UseFormItemStatus = () => {
const { status, errors = [], warnings = [] } = useContext(FormItemInputContext);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Form.Item');
warning(
status !== undefined,
'Form.Item',
'usage',
'Form.Item.useStatus should be used under Form.Item component. For more information: https://u.ant.design/form-item-usestatus',
);

View File

@ -6,13 +6,13 @@ import type { FormProps } from '../Form';
const names: Record<string, number> = {};
export default function useFormWarning({ name }: FormProps) {
const warning = devUseWarning();
const warning = devUseWarning('Form');
useEffect(() => {
if (name) {
names[name] = (names[name] || 0) + 1;
warning(names[name] <= 1, 'Form', 'usage', 'There exist multiple Form with same `name`.');
warning(names[name] <= 1, 'usage', 'There exist multiple Form with same `name`.');
return () => {
names[name] -= 1;

View File

@ -2,9 +2,9 @@ import { devUseWarning } from '../_util/warning';
const Icon: React.FC = () => {
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Icon');
warning(false, 'Icon', 'usage', 'Empty Icon');
warning(false, 'usage', 'Empty Icon');
}
return null;
};

View File

@ -50,14 +50,9 @@ const Group: React.FC<GroupProps> = (props) => {
);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Input.Group');
warning(
false,
'Input.Group',
'deprecated',
`'Input.Group' is deprecated. Please use 'Space.Compact' instead.`,
);
warning.deprecated(false, 'Input.Group', 'Space.Compact');
}
return wrapSSR(

View File

@ -116,13 +116,12 @@ const Input = forwardRef<InputRef, InputProps>((props, ref) => {
/* eslint-disable react-hooks/rules-of-hooks */
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Input');
useEffect(() => {
if (inputHasPrefixSuffix && !prevHasPrefixSuffix.current) {
warning(
document.activeElement === inputRef.current?.input,
'Input',
'usage',
`When Input is focused, dynamic add or remove prefix / suffix will make it lose focus caused by dom structure change. Read more: https://ant.design/components/input/#FAQ`,
);

View File

@ -9255,7 +9255,7 @@ exports[`renders components/input/demo/group.tsx extend context correctly 1`] =
exports[`renders components/input/demo/group.tsx extend context correctly 2`] = `
[
"Warning: [antd: Input.Group] 'Input.Group' is deprecated. Please use 'Space.Compact' instead.",
"Warning: [antd: Input.Group] \`Input.Group\` is deprecated. Please use \`Space.Compact\` instead.",
]
`;

View File

@ -124,7 +124,7 @@ describe('Input', () => {
render(<Input.Group />);
expect(errorSpy).toHaveBeenCalledWith(
"Warning: [antd: Input.Group] 'Input.Group' is deprecated. Please use 'Space.Compact' instead.",
'Warning: [antd: Input.Group] `Input.Group` is deprecated. Please use `Space.Compact` instead.',
);
});
});

View File

@ -340,13 +340,14 @@ export const genInputGroupStyle = (token: InputToken): CSSObject => {
[`${antCls}-select`]: {
margin: `-${token.paddingBlock + 1}px -${token.paddingInline}px`,
[`&${antCls}-select-single:not(${antCls}-select-customize-input)`]: {
[`${antCls}-select-selector`]: {
backgroundColor: 'inherit',
border: `${token.lineWidth}px ${token.lineType} transparent`,
boxShadow: 'none',
[`&${antCls}-select-single:not(${antCls}-select-customize-input):not(${antCls}-pagination-size-changer)`]:
{
[`${antCls}-select-selector`]: {
backgroundColor: 'inherit',
border: `${token.lineWidth}px ${token.lineType} transparent`,
boxShadow: 'none',
},
},
},
'&-open, &-focused': {
[`${antCls}-select-selector`]: {

View File

@ -1,5 +1,8 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Layout image', () => {
imageDemoTest('layout', { skip: ['fixed-sider.tsx'] });
imageDemoTest('layout', {
skip: ['fixed-sider.tsx'],
splitTheme: ['side.tsx'],
});
});

View File

@ -69,11 +69,10 @@ const LocaleProvider: React.FC<LocaleProviderProps> = (props) => {
const { locale = {} as Locale, children, _ANT_MARK__ } = props;
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('LocaleProvider');
warning(
_ANT_MARK__ === ANT_MARK,
'LocaleProvider',
'deprecated',
'`LocaleProvider` is deprecated. Please use `locale` with `ConfigProvider` instead: http://u.ant.design/locale',
);

View File

@ -88,14 +88,9 @@ const InternalMentions: React.ForwardRefRenderFunction<MentionsRef, MentionProps
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Mentions');
warning(
!children,
'Mentions',
'deprecated',
'`Mentions.Option` is deprecated. Please use `options` instead.',
);
warning.deprecated(!children, 'Mentions.Option', 'options');
}
const {

View File

@ -72,28 +72,21 @@ const InternalMenu = forwardRef<RcMenuRef, InternalMenuProps>((props, ref) => {
// ======================== Warning ==========================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Menu');
warning(
!('inlineCollapsed' in props && mode !== 'inline'),
'Menu',
'usage',
'`inlineCollapsed` should only be used when `mode` is inline.',
);
warning(
!(props.siderCollapsed !== undefined && 'inlineCollapsed' in props),
'Menu',
'usage',
'`inlineCollapsed` not control Menu under Sider. Should set `collapsed` on Sider instead.',
);
warning(
'items' in props && !children,
'Menu',
'deprecated',
'`children` will be removed in next major version. Please use `items` instead.',
);
warning.deprecated('items' in props && !children, 'children', 'items');
}
overrideObj.validator?.({ mode });

View File

@ -122,7 +122,7 @@ export function useInternalMessage(
): readonly [MessageInstance, React.ReactElement] {
const holderRef = React.useRef<HolderRef>(null);
const warning = devUseWarning();
const warning = devUseWarning('Message');
// ================================ API ================================
const wrapAPI = React.useMemo<MessageInstance>(() => {
@ -138,7 +138,6 @@ export function useInternalMessage(
if (!holderRef.current) {
warning(
false,
'Message',
'usage',
'You are calling notice in render which will break in React 18 concurrent mode. Please trigger in effect instead.',
);

View File

@ -62,11 +62,10 @@ export function ConfirmContent(
} = props;
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Modal');
warning(
!(typeof icon === 'string' && icon.length > 2),
'Modal',
'breaking',
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,
);
@ -190,14 +189,9 @@ const ConfirmDialog: React.FC<ConfirmDialogProps> = (props) => {
} = props;
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Modal');
warning(
visible === undefined,
'Modal',
'deprecated',
`\`visible\` is deprecated, please use \`open\` instead.`,
);
warning.deprecated(visible === undefined, 'visible', 'open');
}
const confirmPrefixCls = `${prefixCls}-confirm`;

View File

@ -55,14 +55,9 @@ const Modal: React.FC<ModalProps> = (props) => {
};
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Modal');
warning(
!('visible' in props),
'Modal',
'deprecated',
`\`visible\` will be removed in next major version, please use \`open\` instead.`,
);
warning.deprecated(!('visible' in props), 'visible', 'open');
}
const {

View File

@ -117,7 +117,7 @@ describe('Modal', () => {
render(<Modal visible />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Modal] `visible` will be removed in next major version, please use `open` instead.',
'Warning: [antd: Modal] `visible` is deprecated. Please use `open` instead.',
);
expect(document.querySelector('.ant-modal')).toBeTruthy();

View File

@ -118,7 +118,7 @@ export function useInternalNotification(
): readonly [NotificationInstance, React.ReactElement] {
const holderRef = React.useRef<HolderRef>(null);
const warning = devUseWarning();
const warning = devUseWarning('Notification');
// ================================ API ================================
const wrapAPI = React.useMemo<NotificationInstance>(() => {
@ -129,7 +129,6 @@ export function useInternalNotification(
if (!holderRef.current) {
warning(
false,
'Notification',
'usage',
'You are calling notice in render which will break in React 18 concurrent mode. Please trigger in effect instead.',
);

View File

@ -726,7 +726,7 @@ exports[`renders components/popover/demo/arrow-point-at-center.tsx extend contex
exports[`renders components/popover/demo/arrow-point-at-center.tsx extend context correctly 2`] = `
[
"Warning: [antd: Tooltip] \`arrowPointAtCenter\` is deprecated, please use \`arrow={{ pointAtCenter: true }}\` instead.",
"Warning: [antd: Tooltip] \`arrowPointAtCenter\` is deprecated. Please use \`arrow={{ pointAtCenter: true }}\` instead.",
]
`;

View File

@ -99,14 +99,9 @@ const Line: React.FC<LineProps> = (props) => {
const [width, height] = getSize(mergedSize, 'line', { strokeWidth });
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Progress');
warning(
!('strokeWidth' in props),
'Progress',
'deprecated',
'`strokeWidth` is deprecated. Please use `size` instead.',
);
warning.deprecated(!('strokeWidth' in props), 'strokeWidth', 'size');
}
const percentStyle: React.CSSProperties = {

View File

@ -123,37 +123,21 @@ const Progress = React.forwardRef<HTMLDivElement, ProgressProps>((props, ref) =>
}, [showInfo, percent, percentNumber, progressStatus, type, prefixCls, format]);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Progress');
warning(
!('successPercent' in props),
'Progress',
'deprecated',
'`successPercent` is deprecated. Please use `success.percent` instead.',
);
warning(
!('width' in props),
'Progress',
'deprecated',
'`width` is deprecated. Please use `size` instead.',
);
warning.deprecated(!('successPercent' in props), 'successPercent', 'success.percent');
warning.deprecated(!('width' in props), 'width', 'size');
if ((type === 'circle' || type === 'dashboard') && Array.isArray(size)) {
warning(
false,
'Progress',
'usage',
'Type "circle" and "dashboard" do not accept array as `size`, please use number or preset size instead.',
);
}
if (props.success && 'progress' in props.success) {
warning(
false,
'Progress',
'deprecated',
'`success.progress` is deprecated. Please use `success.percent` instead.',
);
warning.deprecated(false, 'success.progress', 'success.percent');
}
}

View File

@ -57,13 +57,12 @@ const QRCode: React.FC<QRCodeProps> = (props) => {
const [locale] = useLocale('QRCode');
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('QRCode');
warning(!!value, 'QRCode', 'usage', 'need to receive `value` props');
warning(!!value, 'usage', 'need to receive `value` props');
warning(
!(icon && errorLevel === 'L'),
'QRCode',
'usage',
'ErrorLevel `L` is not recommended to be used with `icon`, for scanning result would be affected by low level.',
);

View File

@ -23,14 +23,9 @@ const InternalRadio: React.ForwardRefRenderFunction<RadioRef, RadioProps> = (pro
const { isFormItemInput } = React.useContext(FormItemInputContext);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Radio');
warning(
!('optionType' in props),
'Radio',
'usage',
'`optionType` is only support in Radio.Group.',
);
warning(!('optionType' in props), 'usage', '`optionType` is only support in Radio.Group.');
}
const onChange = (e: RadioChangeEvent) => {

View File

@ -63,10 +63,6 @@ const genRateStarStyle: GenerateStyle<RateToken, CSSObject> = (token) => {
color: token.starBg,
transition: `all ${token.motionDurationMid}`,
userSelect: 'none',
[token.iconCls]: {
verticalAlign: 'middle',
},
},
'&-first': {
@ -108,7 +104,7 @@ const genRateStyle: GenerateStyle<RateToken> = (token) => {
padding: 0,
color: token.starColor,
fontSize: token.starSize,
lineHeight: 'unset',
lineHeight: 1,
listStyle: 'none',
outline: 'none',

View File

@ -61,11 +61,10 @@ const Icon: React.FC<IconProps> = ({ prefixCls, icon, status }) => {
const className = classNames(`${prefixCls}-icon`);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Result');
warning(
!(typeof icon === 'string' && icon.length > 2),
'Result',
'breaking',
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,
);

View File

@ -1,5 +1,7 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Select image', () => {
imageDemoTest('select', { skip: ['basic.tsx'] });
imageDemoTest('select', {
splitTheme: ['debug-flip-shift.tsx'],
});
});

View File

@ -16,38 +16,69 @@ const handleChange = (value: string[]) => {
};
const App: React.FC = () => (
<ConfigProvider
theme={{
components: {
Select: {
multipleItemBorderColor: 'rgba(0,0,0,0.06)',
multipleItemBorderColorDisabled: 'rgba(0,0,0,0.06)',
optionSelectedColor: '#1677ff',
<Space direction="vertical">
<ConfigProvider
theme={{
components: {
Select: {
multipleItemBorderColor: 'rgba(0,0,0,0.06)',
multipleItemBorderColorDisabled: 'rgba(0,0,0,0.06)',
optionSelectedColor: '#1677ff',
},
},
},
}}
>
<Space style={{ width: '100%' }} direction="vertical">
<Select
mode="multiple"
allowClear
style={{ width: '100%' }}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
options={options}
/>
<Select
mode="multiple"
disabled
style={{ width: '100%' }}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
options={options}
/>
</Space>
</ConfigProvider>
}}
>
<Space style={{ width: '100%' }} direction="vertical">
<Select
mode="multiple"
allowClear
style={{ width: '100%' }}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
options={options}
/>
<Select
mode="multiple"
disabled
style={{ width: '100%' }}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
options={options}
/>
</Space>
</ConfigProvider>
<ConfigProvider
theme={{
token: {
controlHeightSM: 28,
},
}}
>
<Space style={{ width: '100%' }} direction="vertical">
<Select
mode="multiple"
allowClear
size="small"
style={{ width: '100%' }}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
options={options}
/>
<Select
mode="multiple"
allowClear
style={{ width: '100%' }}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
options={options}
/>
</Space>
</ConfigProvider>
</Space>
);
export default App;

View File

@ -223,25 +223,18 @@ const InternalSelect = <
// ====================== Warning ======================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Select');
warning(
!dropdownClassName,
'Select',
'deprecated',
'`dropdownClassName` is deprecated. Please use `popupClassName` instead.',
);
warning.deprecated(!dropdownClassName, 'dropdownClassName', 'popupClassName');
warning(
warning.deprecated(
dropdownMatchSelectWidth === undefined,
'Select',
'deprecated',
'`dropdownMatchSelectWidth` is deprecated. Please use `popupMatchSelectWidth` instead.',
'dropdownMatchSelectWidth',
'popupMatchSelectWidth',
);
warning(
!('showArrow' in props),
'Select',
'deprecated',
'`showArrow` is deprecated which will be removed in next major version. It will be a default behavior, you can hide it by setting `suffixIcon` to null.',
);

View File

@ -110,6 +110,7 @@ export interface SelectToken extends FullToken<'Select'> {
rootPrefixCls: string;
inputPaddingHorizontalBase: number;
multipleSelectItemHeight: number;
selectHeight: number;
}
// ============================= Selector =============================
@ -434,6 +435,7 @@ export default genComponentStyleHook(
rootPrefixCls,
inputPaddingHorizontalBase: token.paddingSM - 1,
multipleSelectItemHeight: token.multipleItemHeight,
selectHeight: token.controlHeight,
});
return [genSelectStyle(selectToken)];

View File

@ -6,11 +6,11 @@ import { mergeToken } from '../../theme/internal';
const FIXED_ITEM_MARGIN = 2;
const getSelectItemStyle = ({
controlHeightSM,
controlHeight,
multipleSelectItemHeight,
selectHeight,
lineWidth: borderWidth,
}: SelectToken): readonly [number, number] => {
const selectItemDist = (controlHeight - controlHeightSM) / 2 - borderWidth;
const selectItemDist = (selectHeight - multipleSelectItemHeight) / 2 - borderWidth;
const selectItemMargin = Math.ceil(selectItemDist / 2);
return [selectItemDist, selectItemMargin] as const;
};
@ -202,7 +202,7 @@ const genMultipleStyle = (token: SelectToken): CSSInterpolation => {
const { componentCls } = token;
const smallToken = mergeToken<SelectToken>(token, {
controlHeight: token.controlHeightSM,
selectHeight: token.controlHeightSM,
multipleSelectItemHeight: token.controlHeightXS,
borderRadius: token.borderRadiusSM,
borderRadiusSM: token.borderRadiusXS,
@ -210,7 +210,7 @@ const genMultipleStyle = (token: SelectToken): CSSInterpolation => {
const largeToken = mergeToken<SelectToken>(token, {
fontSize: token.fontSizeLG,
controlHeight: token.controlHeightLG,
selectHeight: token.controlHeightLG,
multipleSelectItemHeight: token.multipleItemHeightLG,
borderRadius: token.borderRadiusLG,
borderRadiusSM: token.borderRadius,

View File

@ -39,14 +39,9 @@ export default function useIcons({
componentName: string;
}) {
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning(componentName);
warning(
!clearIcon,
componentName,
'deprecated',
'`clearIcon` is deprecated, please use `allowClear={{ clearIcon: React.ReactNode }}` instead.',
);
warning.deprecated(!clearIcon, 'clearIcon', 'allowClear={{ clearIcon: React.ReactNode }}');
}
// Clear Icon

View File

@ -171,27 +171,27 @@ describe('Slider', () => {
const { container, rerender } = render(<TSSlider tooltipPrefixCls="xxx" />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Slider] `tooltipPrefixCls` is deprecated, please use `tooltip.prefixCls` instead.',
'Warning: [antd: Slider] `tooltipPrefixCls` is deprecated. Please use `tooltip.prefixCls` instead.',
);
rerender(<TSSlider getTooltipPopupContainer={() => document.body} />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Slider] `getTooltipPopupContainer` is deprecated, please use `tooltip.getPopupContainer` instead.',
'Warning: [antd: Slider] `getTooltipPopupContainer` is deprecated. Please use `tooltip.getPopupContainer` instead.',
);
rerender(<TSSlider tipFormatter={(v: any) => v} />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Slider] `tipFormatter` is deprecated, please use `tooltip.formatter` instead.',
'Warning: [antd: Slider] `tipFormatter` is deprecated. Please use `tooltip.formatter` instead.',
);
rerender(<TSSlider tooltipVisible />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Slider] `tooltipVisible` is deprecated, please use `tooltip.open` instead.',
'Warning: [antd: Slider] `tooltipVisible` is deprecated. Please use `tooltip.open` instead.',
);
rerender(<TSSlider tooltipPlacement="left" />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Slider] `tooltipPlacement` is deprecated, please use `tooltip.placement` instead.',
'Warning: [antd: Slider] `tooltipPlacement` is deprecated. Please use `tooltip.placement` instead.',
);
// All should work

View File

@ -166,7 +166,7 @@ const Slider = React.forwardRef<SliderRef, SliderSingleProps | SliderRangeProps>
// Warning for deprecated usage
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Slider');
[
['tooltipPrefixCls', 'prefixCls'],
@ -175,12 +175,7 @@ const Slider = React.forwardRef<SliderRef, SliderSingleProps | SliderRangeProps>
['tooltipPlacement', 'placement'],
['tooltipVisible', 'open'],
].forEach(([deprecatedName, newName]) => {
warning(
!(deprecatedName in props),
'Slider',
'deprecated',
`\`${deprecatedName}\` is deprecated, please use \`tooltip.${newName}\` instead.`,
);
warning.deprecated(!(deprecatedName in props), deprecatedName, `tooltip.${newName}`);
});
}

View File

@ -111,9 +111,9 @@ const Spin: React.FC<SpinClassProps> = (props) => {
const isNestedPattern = React.useMemo<boolean>(() => typeof children !== 'undefined', [children]);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning();
const warning = devUseWarning('Spin');
warning(!tip || isNestedPattern, 'Spin', 'usage', '`tip` only work in nest pattern.');
warning(!tip || isNestedPattern, 'usage', '`tip` only work in nest pattern.');
}
const { direction, spin } = React.useContext<ConfigConsumerProps>(ConfigContext);

View File

@ -103,7 +103,7 @@ describe('Steps', () => {
expect(container.querySelectorAll('.ant-steps-item')).toHaveLength(1);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: Steps] Step is deprecated. Please use `items` directly.',
'Warning: [antd: Menu] `Step` is deprecated. Please use `items` instead.',
);
errorSpy.mockRestore();
});

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