Merge branch 'master' into feature-merge-master

This commit is contained in:
MadCcc 2022-05-12 15:56:18 +08:00
commit 2d70027f45
107 changed files with 1626 additions and 1384 deletions

View File

@ -30,7 +30,7 @@ jobs:
key: lock-${{ github.sha }} key: lock-${{ github.sha }}
- name: create package-lock.json - name: create package-lock.json
run: npm i --package-lock-only --ignore-scripts run: npm i --package-lock-only --ignore-scripts --legacy-peer-deps
- name: hack for single file - name: hack for single file
run: | run: |

View File

@ -22,7 +22,7 @@ jobs:
key: lock-${{ github.sha }} key: lock-${{ github.sha }}
- name: create package-lock.json - name: create package-lock.json
run: npm i --package-lock-only --ignore-scripts run: npm i --package-lock-only --ignore-scripts --legacy-peer-deps
- name: hack for single file - name: hack for single file
run: | run: |

View File

@ -26,7 +26,7 @@ jobs:
key: lock-${{ github.sha }} key: lock-${{ github.sha }}
- name: create package-lock.json - name: create package-lock.json
run: npm i --package-lock-only --ignore-scripts run: npm i --package-lock-only --ignore-scripts --legacy-peer-deps
- name: hack for single file - name: hack for single file
run: | run: |

View File

@ -28,7 +28,7 @@ jobs:
node-version: '16' node-version: '16'
- name: create package-lock.json - name: create package-lock.json
run: npm i --package-lock-only --ignore-scripts run: npm i --package-lock-only --ignore-scripts --legacy-peer-deps
- name: hack for single file - name: hack for single file
run: | run: |

View File

@ -20,13 +20,13 @@ module.exports = {
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'md'], moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'md'],
modulePathIgnorePatterns: ['/_site/'], modulePathIgnorePatterns: ['/_site/'],
moduleNameMapper: { moduleNameMapper: {
'^dnd-core$': 'dnd-core/dist/cjs', '/^dnd-core$/': 'dnd-core/dist/cjs',
'^react-dnd$': 'react-dnd/dist/cjs', '/^react-dnd$/': 'react-dnd/dist/cjs',
'^react-dnd-html5-backend$': 'react-dnd-html5-backend/dist/cjs', '/^react-dnd-html5-backend$/': 'react-dnd-html5-backend/dist/cjs',
'^react-dnd-touch-backend$': 'react-dnd-touch-backend/dist/cjs', '/^react-dnd-touch-backend$/': 'react-dnd-touch-backend/dist/cjs',
'^react-dnd-test-backend$': 'react-dnd-test-backend/dist/cjs', '/^react-dnd-test-backend$/': 'react-dnd-test-backend/dist/cjs',
'^react-dnd-test-utils$': 'react-dnd-test-utils/dist/cjs', '/^react-dnd-test-utils$/': 'react-dnd-test-utils/dist/cjs',
'\\.(css|less)$': 'identity-obj-proxy', '/\\.(css|less)$/': 'identity-obj-proxy',
}, },
testPathIgnorePatterns: ['/node_modules/', 'dekko', 'node', 'image.test.js', 'image.test.ts'], testPathIgnorePatterns: ['/node_modules/', 'dekko', 'node', 'image.test.js', 'image.test.ts'],
transform: { transform: {
@ -52,5 +52,7 @@ module.exports = {
tsConfig: './tsconfig.test.json', tsConfig: './tsconfig.test.json',
}, },
}, },
testURL: 'http://localhost', testEnvironmentOptions: {
url: 'http://localhost',
},
}; };

View File

@ -15,6 +15,26 @@ timeline: true
--- ---
## 4.20.4
`2022-05-11`
- 🐞 Fix broken List.Item type definition. [#35455](https://github.com/ant-design/ant-design/pull/35455) [@rsmeral](https://github.com/rsmeral)
- 🐞 Fix Checkbox margin in Tree RTL mode. [#35491](https://github.com/ant-design/ant-design/pull/35491) [@miracles1919](https://github.com/miracles1919)
- 🗑 Remove Cascader `displayRender` warning. [#35417](https://github.com/ant-design/ant-design/pull/35417) [@lalalazero](https://github.com/lalalazero)
## 4.20.3
`2022-05-08`
- 🐞 Fix unnecessary `rowGap: 0` style attribute in Row. [#35409](https://github.com/ant-design/ant-design/pull/35409)
- 🐞 Fix List.Item `ref` no work problem. [#35321](https://github.com/ant-design/ant-design/pull/35321)
- 💄 Optimize the style of arrow in Tooltip. [#35401](https://github.com/ant-design/ant-design/pull/35401)
- 🐞 Fix Table column filter reset is not working. [#35386](https://github.com/ant-design/ant-design/pull/35386) [@lalalazero](https://github.com/lalalazero)
- 🌍 Add missing localizations for 🇬🇧 en_GB and 🇺🇦 uk_UA. [#35430](https://github.com/ant-design/ant-design/pull/35430) [@velykanov](https://github.com/velykanov)
- Typescript
- 🤖 Fixed an issue where notification `maxCount` attribute was missing. [#35369](https://github.com/ant-design/ant-design/pull/35369) [@cwveysey](https://github.com/cwveysey)
## 4.20.2 ## 4.20.2
`2022-04-30` `2022-04-30`

View File

@ -15,6 +15,27 @@ timeline: true
--- ---
## 4.20.4
`2022-05-11`
- 🐞 修复 List.Item 类型错误。[#35455](https://github.com/ant-design/ant-design/pull/35455) [@rsmeral](https://github.com/rsmeral)
- 🐞 修复 Tree 组件 RTL 模式下 Checkbox 的间距。[#35491](https://github.com/ant-design/ant-design/pull/35491) [@miracles1919](https://github.com/miracles1919)
- 🗑 删除 Cascader `displayRender` 警告。[#35417](https://github.com/ant-design/ant-design/pull/35417) [@lalalazero](https://github.com/lalalazero)
## 4.20.3
`2022-05-08`
- 🔥 增加 [官方国内镜像](https://ant-design.antgroup.com/index-cn),享受飞一般的加载速度。
- 🐞 修复 Row 里不必要的 `rowGap: 0` 样式属性。[#35409](https://github.com/ant-design/ant-design/pull/35409)
- 🐞 修复 List.Item `ref` 不生效的问题。[#35321](https://github.com/ant-design/ant-design/pull/35321)
- 💄 优化 Tooltip 箭头的样式。[#35401](https://github.com/ant-design/ant-design/pull/35401)
- 🐞 修复 Table 筛选的重置功能不生效问题。[#35386](https://github.com/ant-design/ant-design/pull/35386) [@lalalazero](https://github.com/lalalazero)
- 🌍 为 🇬🇧 en_GB 和 🇺🇦 uk_UA 添加缺失的本地化文案。[#35430](https://github.com/ant-design/ant-design/pull/35430) [@velykanov](https://github.com/velykanov)
- TypeScript
- 🤖 修复 Notification 的 `maxCount` 属性缺失的问题。[#35369](https://github.com/ant-design/ant-design/pull/35369) [@cwveysey](https://github.com/cwveysey)
## 4.20.2 ## 4.20.2
`2022-04-30` `2022-04-30`

View File

@ -0,0 +1,65 @@
describe('Test warning', () => {
let spy: jest.SpyInstance;
beforeAll(() => {
spy = jest.spyOn(console, 'error');
});
afterAll(() => {
spy.mockRestore();
});
beforeEach(() => {
jest.resetModules();
});
afterEach(() => {
spy.mockReset();
});
it('Test noop', async () => {
const { noop } = await import('../warning');
const value = noop();
expect(value).toBe(undefined);
expect(spy).not.toHaveBeenCalled();
expect(() => {
noop();
}).not.toThrow();
});
describe('process.env.NODE_ENV !== "production"', () => {
it('If `false`, exec `console.error`', async () => {
const warning = (await import('../warning')).default;
warning(false, 'error');
expect(spy).toHaveBeenCalled();
});
it('If `true`, do not exec `console.error`', async () => {
const warning = (await import('../warning')).default;
warning(true, 'error message');
expect(spy).not.toHaveBeenCalled();
});
});
describe('process.env.NODE_ENV === "production"', () => {
it('Whether `true` or `false`, do not exec `console.error`', async () => {
const prevEnv = process.env.NODE_ENV;
process.env.NODE_ENV = 'production';
const { default: warning, noop } = await import('../warning');
expect(warning).toEqual(noop);
warning(false, 'error message');
expect(spy).not.toHaveBeenCalled();
warning(true, 'error message');
expect(spy).not.toHaveBeenCalled();
process.env.NODE_ENV = prevEnv;
});
});
});

View File

@ -1,12 +0,0 @@
import devWarning, { resetWarned } from 'rc-util/lib/warning';
export { resetWarned };
export default (valid: boolean, component: string, message: string): void => {
devWarning(valid, `[antd: ${component}] ${message}`);
// StrictMode will inject console which will not throw warning in React 17.
if (process.env.NODE_ENV === 'test') {
resetWarned();
}
};

View File

@ -0,0 +1,21 @@
import rcWarning, { resetWarned } from 'rc-util/lib/warning';
export { resetWarned };
export function noop() {}
type Warning = (valid: boolean, component: string, message: string) => void;
// eslint-disable-next-line import/no-mutable-exports
let warning: Warning = noop;
if (process.env.NODE_ENV !== 'production') {
warning = (valid, component, message) => {
rcWarning(valid, `[antd: ${component}] ${message}`);
// StrictMode will inject console which will not throw warning in React 17.
if (process.env.NODE_ENV === 'test') {
resetWarned();
}
};
}
export default warning;

View File

@ -42,16 +42,15 @@ describe('AutoComplete', () => {
}); });
it('AutoComplete throws error when contains invalid dataSource', () => { it('AutoComplete throws error when contains invalid dataSource', () => {
jest.spyOn(console, 'error').mockImplementation(() => undefined); const spy = jest.spyOn(console, 'error').mockImplementation(() => undefined);
expect(() => {
mount( mount(
<AutoComplete dataSource={[() => {}]}> <AutoComplete dataSource={[() => {}]}>
<textarea /> <textarea />
</AutoComplete>, </AutoComplete>,
); );
}).toThrow();
// eslint-disable-next-line no-console expect(spy).toHaveBeenCalled();
console.error.mockRestore();
}); });
it('legacy dataSource should accept react element option', () => { it('legacy dataSource should accept react element option', () => {

View File

@ -20,7 +20,7 @@ import type {
import Select from '../select'; import Select from '../select';
import type { ConfigConsumerProps } from '../config-provider'; import type { ConfigConsumerProps } from '../config-provider';
import { ConfigConsumer } from '../config-provider'; import { ConfigConsumer } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import { isValidElement } from '../_util/reactNode'; import { isValidElement } from '../_util/reactNode';
import type { InputStatus } from '../_util/statusUtils'; import type { InputStatus } from '../_util/statusUtils';
@ -95,26 +95,28 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
); );
} }
default: default:
throw new Error('AutoComplete[dataSource] only supports type `string[] | Object[]`.'); warning(
false,
'AutoComplete',
'`dataSource` is only supports type `string[] | Object[]`.',
);
return undefined;
} }
}) })
: []; : [];
} }
// ============================ Warning ============================ warning(
React.useEffect(() => { !('dataSource' in props),
devWarning( 'AutoComplete',
!('dataSource' in props), '`dataSource` is deprecated, please use `options` instead.',
'AutoComplete', );
'`dataSource` is deprecated, please use `options` instead.',
);
devWarning( warning(
!customizeInput || !('size' in props), !customizeInput || !('size' in props),
'AutoComplete', 'AutoComplete',
'You need to control style self instead of setting `size` when using customize input.', 'You need to control style self instead of setting `size` when using customize input.',
); );
}, []);
return ( return (
<ConfigConsumer> <ConfigConsumer>

View File

@ -3,7 +3,7 @@ import classNames from 'classnames';
import ResizeObserver from 'rc-resize-observer'; import ResizeObserver from 'rc-resize-observer';
import { composeRef } from 'rc-util/lib/ref'; import { composeRef } from 'rc-util/lib/ref';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import type { Breakpoint } from '../_util/responsiveObserve'; import type { Breakpoint } from '../_util/responsiveObserve';
import { responsiveArray } from '../_util/responsiveObserve'; import { responsiveArray } from '../_util/responsiveObserve';
import useBreakpoint from '../grid/hooks/useBreakpoint'; import useBreakpoint from '../grid/hooks/useBreakpoint';
@ -126,7 +126,7 @@ const InternalAvatar: React.ForwardRefRenderFunction<unknown, AvatarProps> = (pr
: {}; : {};
}, [screens, size]); }, [screens, size]);
devWarning( warning(
!(typeof icon === 'string' && icon.length > 2), !(typeof icon === 'string' && icon.length > 2),
'Avatar', 'Avatar',
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`, `\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,

View File

@ -14,65 +14,59 @@ title:
The count will be animated as it changes. The count will be animated as it changes.
```jsx ```jsx
import React, { useState } from 'react';
import { Badge, Button, Switch, Divider, Avatar } from 'antd'; import { Badge, Button, Switch, Divider, Avatar } from 'antd';
import { MinusOutlined, PlusOutlined, QuestionOutlined } from '@ant-design/icons'; import { MinusOutlined, PlusOutlined, QuestionOutlined } from '@ant-design/icons';
const ButtonGroup = Button.Group; const ButtonGroup = Button.Group;
class Demo extends React.Component { export default () => {
state = { const [count, setCount] = useState(5);
count: 5, const [show, setShow] = useState(true);
show: true,
const increase = () => {
setCount(count + 1);
}; };
increase = () => { const decline = () => {
const count = this.state.count + 1; let countValue = count - 1;
this.setState({ count }); if (countValue < 0) {
}; countValue = 0;
decline = () => {
let count = this.state.count - 1;
if (count < 0) {
count = 0;
} }
this.setState({ count }); setCount(countValue);
}; };
random = () => { const random = () => {
const count = Math.floor(Math.random() * 100); const countValue = Math.floor(Math.random() * 100);
this.setState({ count }); setCount(countValue);
}; };
onChange = show => { const onChange = isShow => {
this.setState({ show }); setShow(isShow);
}; };
render() { return (
return ( <>
<> <Badge count={count}>
<Badge count={this.state.count}> <Avatar shape="square" size="large" />
<Avatar shape="square" size="large" /> </Badge>
</Badge> <ButtonGroup>
<ButtonGroup> <Button onClick={decline}>
<Button onClick={this.decline}> <MinusOutlined />
<MinusOutlined /> </Button>
</Button> <Button onClick={increase}>
<Button onClick={this.increase}> <PlusOutlined />
<PlusOutlined /> </Button>
</Button> <Button onClick={random}>
<Button onClick={this.random}> <QuestionOutlined />
<QuestionOutlined /> </Button>
</Button> </ButtonGroup>
</ButtonGroup> <Divider />
<Divider /> <Badge dot={show}>
<Badge dot={this.state.show}> <Avatar shape="square" size="large" />
<Avatar shape="square" size="large" /> </Badge>
</Badge> <Switch onChange={onChange} checked={show} />
<Switch onChange={this.onChange} checked={this.state.show} /> </>
</> );
); };
}
}
export default Demo;
``` ```

View File

@ -5,7 +5,7 @@ import BreadcrumbItem from './BreadcrumbItem';
import BreadcrumbSeparator from './BreadcrumbSeparator'; import BreadcrumbSeparator from './BreadcrumbSeparator';
import Menu from '../menu'; import Menu from '../menu';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import { cloneElement } from '../_util/reactNode'; import { cloneElement } from '../_util/reactNode';
export interface Route { export interface Route {
@ -119,7 +119,7 @@ const Breadcrumb: BreadcrumbInterface = ({
return element; return element;
} }
devWarning( warning(
element.type && element.type &&
(element.type.__ANT_BREADCRUMB_ITEM === true || (element.type.__ANT_BREADCRUMB_ITEM === true ||
element.type.__ANT_BREADCRUMB_SEPARATOR === true), element.type.__ANT_BREADCRUMB_SEPARATOR === true),

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import type { SizeType } from '../config-provider/SizeContext'; import type { SizeType } from '../config-provider/SizeContext';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
export interface ButtonGroupProps { export interface ButtonGroupProps {
size?: SizeType; size?: SizeType;
@ -34,7 +34,7 @@ const ButtonGroup: React.FC<ButtonGroupProps> = props => {
case undefined: case undefined:
break; break;
default: default:
devWarning(!size, 'Button.Group', 'Invalid prop `size`.'); warning(!size, 'Button.Group', 'Invalid prop `size`.');
} }
const classes = classNames( const classes = classNames(

View File

@ -7,7 +7,7 @@ import Group, { GroupSizeContext } from './button-group';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import Wave from '../_util/wave'; import Wave from '../_util/wave';
import { tuple } from '../_util/type'; import { tuple } from '../_util/type';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import type { SizeType } from '../config-provider/SizeContext'; import type { SizeType } from '../config-provider/SizeContext';
import SizeContext from '../config-provider/SizeContext'; import SizeContext from '../config-provider/SizeContext';
import DisabledContext from '../config-provider/DisabledContext'; import DisabledContext from '../config-provider/DisabledContext';
@ -226,13 +226,13 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)?.(e); (onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)?.(e);
}; };
devWarning( warning(
!(typeof icon === 'string' && icon.length > 2), !(typeof icon === 'string' && icon.length > 2),
'Button', 'Button',
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`, `\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,
); );
devWarning( warning(
!(ghost && isUnBorderedButtonType(type)), !(ghost && isUnBorderedButtonType(type)),
'Button', 'Button',
"`link` or `text` button can't be a `ghost` button.", "`link` or `text` button can't be a `ghost` button.",

View File

@ -14,72 +14,61 @@ title:
A loading indicator can be added to a button by setting the `loading` property on the `Button`. A loading indicator can be added to a button by setting the `loading` property on the `Button`.
```jsx ```jsx
import React, { useEffect, useState, useRef } from 'react';
import { Button, Space } from 'antd'; import { Button, Space } from 'antd';
import { PoweroffOutlined } from '@ant-design/icons'; import { PoweroffOutlined } from '@ant-design/icons';
class App extends React.Component { export default () => {
state = { const [loadings, setLoadings] = useState([]);
loadings: [],
};
enterLoading = index => { const enterLoading = index => {
this.setState(({ loadings }) => { setLoadings(prevLoadings => {
const newLoadings = [...loadings]; const newLoadings = [...prevLoadings];
newLoadings[index] = true; newLoadings[index] = true;
return newLoadings;
return {
loadings: newLoadings,
};
}); });
setTimeout(() => {
this.setState(({ loadings }) => {
const newLoadings = [...loadings];
newLoadings[index] = false;
return { setTimeout(() => {
loadings: newLoadings, setLoadings(prevLoadings => {
}; const newLoadings = [...prevLoadings];
newLoadings[index] = false;
return newLoadings;
}); });
}, 6000); }, 6000);
}; };
render() { return (
const { loadings } = this.state; <>
return ( <Space style={{ width: '100%' }}>
<> <Button type="primary" loading>
<Space style={{ width: '100%' }}> Loading
<Button type="primary" loading> </Button>
Loading <Button type="primary" size="small" loading>
</Button> Loading
<Button type="primary" size="small" loading> </Button>
Loading <Button type="primary" icon={<PoweroffOutlined />} loading />
</Button> </Space>
<Button type="primary" icon={<PoweroffOutlined />} loading />
</Space>
<Space style={{ width: '100%' }}> <Space style={{ width: '100%' }}>
<Button type="primary" loading={loadings[0]} onClick={() => this.enterLoading(0)}> <Button type="primary" loading={loadings[0]} onClick={() => enterLoading(0)}>
Click me! Click me!
</Button> </Button>
<Button <Button
type="primary" type="primary"
icon={<PoweroffOutlined />} icon={<PoweroffOutlined />}
loading={loadings[1]} loading={loadings[1]}
onClick={() => this.enterLoading(1)} onClick={() => enterLoading(1)}
> >
Click me! Click me!
</Button> </Button>
<Button <Button
type="primary" type="primary"
icon={<PoweroffOutlined />} icon={<PoweroffOutlined />}
loading={loadings[2]} loading={loadings[2]}
onClick={() => this.enterLoading(2)} onClick={() => enterLoading(2)}
/> />
</Space> </Space>
</> </>
); );
} };
}
export default App;
``` ```

View File

@ -18,54 +18,47 @@ Ant Design supports a default button size as well as a large and small size.
If a large or small button is desired, set the `size` property to either `large` or `small` respectively. Omit the `size` property for a button with the default size. If a large or small button is desired, set the `size` property to either `large` or `small` respectively. Omit the `size` property for a button with the default size.
```jsx ```jsx
import React, { useState } from 'react';
import { Button, Radio } from 'antd'; import { Button, Radio } from 'antd';
import { DownloadOutlined } from '@ant-design/icons'; import { DownloadOutlined } from '@ant-design/icons';
class ButtonSize extends React.Component { export default () => {
state = { const [size, setSize] = useState('large');
size: 'large', const handleSizeChange = e => {
setSize(e.target.value);
}; };
handleSizeChange = e => { return (
this.setState({ size: e.target.value }); <>
}; <Radio.Group value={size} onChange={handleSizeChange}>
<Radio.Button value="large">Large</Radio.Button>
render() { <Radio.Button value="default">Default</Radio.Button>
const { size } = this.state; <Radio.Button value="small">Small</Radio.Button>
return ( </Radio.Group>
<> <br />
<Radio.Group value={size} onChange={this.handleSizeChange}> <br />
<Radio.Button value="large">Large</Radio.Button> <Button type="primary" size={size}>
<Radio.Button value="default">Default</Radio.Button> Primary
<Radio.Button value="small">Small</Radio.Button> </Button>
</Radio.Group> <Button size={size}>Default</Button>
<br /> <Button type="dashed" size={size}>
<br /> Dashed
<Button type="primary" size={size}> </Button>
Primary <br />
</Button> <Button type="link" size={size}>
<Button size={size}>Default</Button> Link
<Button type="dashed" size={size}> </Button>
Dashed <br />
</Button> <Button type="primary" icon={<DownloadOutlined />} size={size} />
<br /> <Button type="primary" shape="circle" icon={<DownloadOutlined />} size={size} />
<Button type="link" size={size}> <Button type="primary" shape="round" icon={<DownloadOutlined />} size={size} />
Link <Button type="primary" shape="round" icon={<DownloadOutlined />} size={size}>
</Button> Download
<br /> </Button>
<Button type="primary" icon={<DownloadOutlined />} size={size} /> <Button type="primary" icon={<DownloadOutlined />} size={size}>
<Button type="primary" shape="circle" icon={<DownloadOutlined />} size={size} /> Download
<Button type="primary" shape="round" icon={<DownloadOutlined />} size={size} /> </Button>
<Button type="primary" shape="round" icon={<DownloadOutlined />} size={size}> </>
Download );
</Button> };
<Button type="primary" icon={<DownloadOutlined />} size={size}>
Download
</Button>
</>
);
}
}
export default () => <ButtonSize />;
``` ```

View File

@ -14,38 +14,39 @@ title:
A basic calendar component with Year/Month switch. A basic calendar component with Year/Month switch.
```jsx ```jsx
import React, { useState } from 'react';
import { Calendar, Alert } from 'antd'; import { Calendar, Alert } from 'antd';
import moment from 'moment'; import moment from 'moment';
class App extends React.Component { export default () => {
state = { const [calendar, setCalendar] = useState({
value: moment('2017-01-25'), value: moment('2017-01-25'),
selectedValue: moment('2017-01-25'), selectedValue: moment('2017-01-25'),
}; });
onSelect = value => { const onSelect = value => {
this.setState({ setCalendar({
value, value,
selectedValue: value, selectedValue: value,
}); });
}; };
onPanelChange = value => { const onPanelChange = value => {
this.setState({ value }); setCalendar({
...calendar,
value,
});
}; };
render() { return (
const { value, selectedValue } = this.state; <>
return ( <Alert
<> message={`You selected date: ${
<Alert calendar.selectedValue && calendar.selectedValue.format('YYYY-MM-DD')
message={`You selected date: ${selectedValue && selectedValue.format('YYYY-MM-DD')}`} }`}
/> />
<Calendar value={value} onSelect={this.onSelect} onPanelChange={this.onPanelChange} /> <Calendar value={calendar.value} onSelect={onSelect} onPanelChange={onPanelChange} />
</> </>
); );
} };
}
export default App;
``` ```

View File

@ -14,55 +14,48 @@ title:
Shows a loading indicator while the contents of the card is being fetched. Shows a loading indicator while the contents of the card is being fetched.
```jsx ```jsx
import React, { useState } from 'react';
import { Skeleton, Switch, Card, Avatar } from 'antd'; import { Skeleton, Switch, Card, Avatar } from 'antd';
import { EditOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons'; import { EditOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons';
const { Meta } = Card; const { Meta } = Card;
class App extends React.Component { export default () => {
state = { const [loading, setLoading] = useState(true);
loading: true,
const onChange = checked => {
setLoading(!checked);
}; };
onChange = checked => { return (
this.setState({ loading: !checked }); <>
}; <Switch checked={!loading} onChange={onChange} />
render() { <Card style={{ width: 300, marginTop: 16 }} loading={loading}>
const { loading } = this.state; <Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random" />}
title="Card title"
description="This is the description"
/>
</Card>
return ( <Card
<> style={{ width: 300, marginTop: 16 }}
<Switch checked={!loading} onChange={this.onChange} /> actions={[
<SettingOutlined key="setting" />,
<Card style={{ width: 300, marginTop: 16 }} loading={loading}> <EditOutlined key="edit" />,
<EllipsisOutlined key="ellipsis" />,
]}
>
<Skeleton loading={loading} avatar active>
<Meta <Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random" />} avatar={<Avatar src="https://joeschmoe.io/api/v1/random" />}
title="Card title" title="Card title"
description="This is the description" description="This is the description"
/> />
</Card> </Skeleton>
</Card>
<Card </>
style={{ width: 300, marginTop: 16 }} );
actions={[ };
<SettingOutlined key="setting" />,
<EditOutlined key="edit" />,
<EllipsisOutlined key="ellipsis" />,
]}
>
<Skeleton loading={loading} avatar active>
<Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random" />}
title="Card title"
description="This is the description"
/>
</Skeleton>
</Card>
</>
);
}
}
export default App;
``` ```

View File

@ -517,17 +517,6 @@ describe('Cascader', () => {
errorSpy.mockRestore(); errorSpy.mockRestore();
}); });
it('displayRender & multiple', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
mount(<Cascader multiple displayRender={() => null} />);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: Cascader] `displayRender` not work on `multiple`. Please use `tagRender` instead.',
);
errorSpy.mockRestore();
});
it('should support showCheckedStrategy child', () => { it('should support showCheckedStrategy child', () => {
const multipleOptions = [ const multipleOptions = [
{ {

View File

@ -39,29 +39,22 @@ const options = [
}, },
]; ];
class CitySwitcher extends React.Component { export default () => {
state = { const [text, setText] = React.useState('Unselect');
text: 'Unselect',
const onChange = (value, selectedOptions) => {
const labeText = selectedOptions.map(o => o.label).join(', ');
setText(labeText);
}; };
onChange = (value, selectedOptions) => { return (
this.setState({ <span>
text: selectedOptions.map(o => o.label).join(', '), {text}
}); &nbsp;
}; <Cascader options={options} onChange={onChange}>
<a href="#">Change city</a>
render() { </Cascader>
return ( </span>
<span> );
{this.state.text} };
&nbsp;
<Cascader options={options} onChange={this.onChange}>
<a href="#">Change city</a>
</Cascader>
</span>
);
}
}
export default () => <CitySwitcher />;
``` ```

View File

@ -49,7 +49,6 @@ Cascade selection box.
| status | Set validation status | 'error' \| 'warning' | - | 4.19.0 | | status | Set validation status | 'error' \| 'warning' | - | 4.19.0 |
| style | The additional style | CSSProperties | - | | | style | The additional style | CSSProperties | - | |
| suffixIcon | The custom suffix icon | ReactNode | - | | | suffixIcon | The custom suffix icon | ReactNode | - | |
| tagRender | Customize tag render when `multiple` | (props) => ReactNode | - | 4.17.0 |
| value | The selected value | string\[] \| number\[] | - | | | value | The selected value | string\[] \| number\[] | - | |
| onChange | Callback when finishing cascader select | (value, selectedOptions) => void | - | | | onChange | Callback when finishing cascader select | (value, selectedOptions) => void | - | |
| onDropdownVisibleChange | Callback when popup shown or hidden | (value) => void | - | 4.17.0 | | onDropdownVisibleChange | Callback when popup shown or hidden | (value) => void | - | 4.17.0 |

View File

@ -14,7 +14,7 @@ import RightOutlined from '@ant-design/icons/RightOutlined';
import LoadingOutlined from '@ant-design/icons/LoadingOutlined'; import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
import LeftOutlined from '@ant-design/icons/LeftOutlined'; import LeftOutlined from '@ant-design/icons/LeftOutlined';
import { useContext } from 'react'; import { useContext } from 'react';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import type { SizeType } from '../config-provider/SizeContext'; import type { SizeType } from '../config-provider/SizeContext';
import SizeContext from '../config-provider/SizeContext'; import SizeContext from '../config-provider/SizeContext';
@ -162,19 +162,17 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
const mergedStatus = getMergedStatus(contextStatus, customStatus); const mergedStatus = getMergedStatus(contextStatus, customStatus);
// =================== Warning ===================== // =================== Warning =====================
if (process.env.NODE_ENV !== 'production') { warning(
devWarning( popupClassName === undefined,
popupClassName === undefined, 'Cascader',
'Cascader', '`popupClassName` is deprecated. Please use `dropdownClassName` instead.',
'`popupClassName` is deprecated. Please use `dropdownClassName` instead.', );
);
devWarning( warning(
!multiple || !props.displayRender, !multiple || !props.displayRender,
'Cascader', 'Cascader',
'`displayRender` not work on `multiple`. Please use `tagRender` instead.', '`displayRender` not work on `multiple`. Please use `tagRender` instead.',
); );
}
// =================== No Found ==================== // =================== No Found ====================
const mergedNotFoundContent = notFoundContent || renderEmpty('Cascader'); const mergedNotFoundContent = notFoundContent || renderEmpty('Cascader');

View File

@ -50,7 +50,6 @@ cover: https://gw.alipayobjects.com/zos/alicdn/UdS8y8xyZ/Cascader.svg
| status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 | | status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 |
| style | 自定义样式 | CSSProperties | - | | | style | 自定义样式 | CSSProperties | - | |
| suffixIcon | 自定义的选择框后缀图标 | ReactNode | - | | | suffixIcon | 自定义的选择框后缀图标 | ReactNode | - | |
| tagRender | 自定义 tag 内容,多选时生效 | (props) => ReactNode | - | 4.17.0 |
| value | 指定选中项 | string\[] \| number\[] | - | | | value | 指定选中项 | string\[] \| number\[] | - | |
| onChange | 选择完成后的回调 | (value, selectedOptions) => void | - | | | onChange | 选择完成后的回调 | (value, selectedOptions) => void | - | |
| onDropdownVisibleChange | 显示/隐藏浮层的回调 | (value) => void | - | 4.17.0 | | onDropdownVisibleChange | 显示/隐藏浮层的回调 | (value) => void | - | 4.17.0 |

View File

@ -5,7 +5,7 @@ import { useContext } from 'react';
import { FormItemInputContext } from '../form/context'; import { FormItemInputContext } from '../form/context';
import { GroupContext } from './Group'; import { GroupContext } from './Group';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
export interface AbstractCheckboxProps<T> { export interface AbstractCheckboxProps<T> {
prefixCls?: string; prefixCls?: string;
@ -67,7 +67,7 @@ const InternalCheckbox: React.ForwardRefRenderFunction<HTMLInputElement, Checkbo
React.useEffect(() => { React.useEffect(() => {
checkboxGroup?.registerValue(restProps.value); checkboxGroup?.registerValue(restProps.value);
devWarning( warning(
'checked' in restProps || !!checkboxGroup || !('value' in restProps), 'checked' in restProps || !!checkboxGroup || !('value' in restProps),
'Checkbox', 'Checkbox',
'`value` is not a valid prop, do you mean `checked`?', '`value` is not a valid prop, do you mean `checked`?',

View File

@ -2,7 +2,7 @@ import React from 'react';
import { render, fireEvent } from '../../../tests/utils'; import { render, fireEvent } from '../../../tests/utils';
import Checkbox from '..'; import Checkbox from '..';
import focusTest from '../../../tests/shared/focusTest'; import focusTest from '../../../tests/shared/focusTest';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest'; import rtlTest from '../../../tests/shared/rtlTest';

View File

@ -14,61 +14,44 @@ title:
Communicated with other components. Communicated with other components.
```jsx ```jsx
import React, { useState } from 'react';
import { Checkbox, Button } from 'antd'; import { Checkbox, Button } from 'antd';
class App extends React.Component { export default () => {
state = { const [checked, setChecked] = useState(true);
checked: true, const [disabled, setDisabled] = useState(false);
disabled: false,
const toggleChecked = () => {
setChecked(!checked);
}; };
toggleChecked = () => { const toggleDisable = () => {
this.setState({ checked: !this.state.checked }); setDisabled(!disabled);
}; };
toggleDisable = () => { const onChange = e => {
this.setState({ disabled: !this.state.disabled });
};
onChange = e => {
console.log('checked = ', e.target.checked); console.log('checked = ', e.target.checked);
this.setState({ setChecked(e.target.checked);
checked: e.target.checked,
});
}; };
render() { const label = `${checked ? 'Checked' : 'Unchecked'}-${disabled ? 'Disabled' : 'Enabled'}`;
const label = `${this.state.checked ? 'Checked' : 'Unchecked'}-${
this.state.disabled ? 'Disabled' : 'Enabled'
}`;
return (
<>
<p style={{ marginBottom: '20px' }}>
<Checkbox
checked={this.state.checked}
disabled={this.state.disabled}
onChange={this.onChange}
>
{label}
</Checkbox>
</p>
<p>
<Button type="primary" size="small" onClick={this.toggleChecked}>
{!this.state.checked ? 'Check' : 'Uncheck'}
</Button>
<Button
style={{ margin: '0 10px' }}
type="primary"
size="small"
onClick={this.toggleDisable}
>
{!this.state.disabled ? 'Disable' : 'Enable'}
</Button>
</p>
</>
);
}
}
export default App; return (
<>
<p style={{ marginBottom: '20px' }}>
<Checkbox checked={checked} disabled={disabled} onChange={onChange}>
{label}
</Checkbox>
</p>
<p>
<Button type="primary" size="small" onClick={toggleChecked}>
{!checked ? 'Check' : 'Uncheck'}
</Button>
<Button style={{ margin: '0 10px' }} type="primary" size="small" onClick={toggleDisable}>
{!disabled ? 'Disable' : 'Enable'}
</Button>
</p>
</>
);
};
``` ```

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import RcCollapse from 'rc-collapse'; import RcCollapse from 'rc-collapse';
import classNames from 'classnames'; import classNames from 'classnames';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
export type CollapsibleType = 'header' | 'disabled'; export type CollapsibleType = 'header' | 'disabled';
@ -23,7 +23,7 @@ export interface CollapsePanelProps {
} }
const CollapsePanel: React.FC<CollapsePanelProps> = props => { const CollapsePanel: React.FC<CollapsePanelProps> = props => {
devWarning( warning(
!('disabled' in props), !('disabled' in props),
'Collapse.Panel', 'Collapse.Panel',
'`disabled` is deprecated. Please use `collapsible="disabled"` instead.', '`disabled` is deprecated. Please use `collapsible="disabled"` instead.',

View File

@ -2,7 +2,7 @@ import React from 'react';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils'; import { act } from 'react-dom/test-utils';
import { sleep } from '../../../tests/utils'; import { sleep } from '../../../tests/utils';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
describe('Collapse', () => { describe('Collapse', () => {
// eslint-disable-next-line global-require // eslint-disable-next-line global-require

View File

@ -39,48 +39,36 @@ const genExtra = () => (
/> />
); );
class Demo extends React.Component { export default () => {
state = { const [expandIconPosition, setExpandIconPosition] = React.useState('left');
expandIconPosition: 'left',
const onPositionChange = position => {
setExpandIconPosition(position);
}; };
return (
onPositionChange = expandIconPosition => { <>
this.setState({ expandIconPosition }); <Collapse
}; defaultActiveKey={['1']}
onChange={callback}
render() { expandIconPosition={expandIconPosition}
const { expandIconPosition } = this.state; >
return ( <Panel header="This is panel header 1" key="1" extra={genExtra()}>
<> <div>{text}</div>
<Collapse </Panel>
defaultActiveKey={['1']} <Panel header="This is panel header 2" key="2" extra={genExtra()}>
onChange={callback} <div>{text}</div>
expandIconPosition={expandIconPosition} </Panel>
> <Panel header="This is panel header 3" key="3" extra={genExtra()}>
<Panel header="This is panel header 1" key="1" extra={genExtra()}> <div>{text}</div>
<div>{text}</div> </Panel>
</Panel> </Collapse>
<Panel header="This is panel header 2" key="2" extra={genExtra()}> <br />
<div>{text}</div> <span>Expand Icon Position: </span>
</Panel> <Select value={expandIconPosition} style={{ margin: '0 8px' }} onChange={onPositionChange}>
<Panel header="This is panel header 3" key="3" extra={genExtra()}> <Option value="left">left</Option>
<div>{text}</div> <Option value="right">right</Option>
</Panel> </Select>
</Collapse> </>
<br /> );
<span>Expand Icon Position: </span> };
<Select
value={expandIconPosition}
style={{ margin: '0 8px' }}
onChange={this.onPositionChange}
>
<Option value="left">left</Option>
<Option value="right">right</Option>
</Select>
</>
);
}
}
export default Demo;
``` ```

View File

@ -41,32 +41,33 @@ const Editor = ({ onChange, onSubmit, submitting, value }) => (
</> </>
); );
class App extends React.Component { export default () => {
state = { const [state, setState] = React.useState({
comments: [], comments: [],
submitting: false, submitting: false,
value: '', value: '',
}; });
handleSubmit = () => { const handleSubmit = () => {
if (!this.state.value) { if (!state.value) {
return; return;
} }
this.setState({ setState({
...state,
submitting: true, submitting: true,
}); });
setTimeout(() => { setTimeout(() => {
this.setState({ setState({
submitting: false, submitting: false,
value: '', value: '',
comments: [ comments: [
...this.state.comments, ...state.comments,
{ {
author: 'Han Solo', author: 'Han Solo',
avatar: 'https://joeschmoe.io/api/v1/random', avatar: 'https://joeschmoe.io/api/v1/random',
content: <p>{this.state.value}</p>, content: <p>{state.value}</p>,
datetime: moment().fromNow(), datetime: moment().fromNow(),
}, },
], ],
@ -74,33 +75,28 @@ class App extends React.Component {
}, 1000); }, 1000);
}; };
handleChange = e => { const handleChange = e => {
this.setState({ setState({
...state,
value: e.target.value, value: e.target.value,
}); });
}; };
render() { return (
const { comments, submitting, value } = this.state; <>
{state.comments.length > 0 && <CommentList comments={state.comments} />}
return ( <Comment
<> avatar={<Avatar src="https://joeschmoe.io/api/v1/random" alt="Han Solo" />}
{comments.length > 0 && <CommentList comments={comments} />} content={
<Comment <Editor
avatar={<Avatar src="https://joeschmoe.io/api/v1/random" alt="Han Solo" />} onChange={handleChange}
content={ onSubmit={handleSubmit}
<Editor submitting={state.submitting}
onChange={this.handleChange} value={state.value}
onSubmit={this.handleSubmit} />
submitting={submitting} }
value={value} />
/> </>
} );
/> };
</>
);
}
}
export default App;
``` ```

View File

@ -26546,7 +26546,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -27957,7 +27957,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -29368,7 +29368,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -30779,7 +30779,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -32190,7 +32190,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -33601,7 +33601,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>

View File

@ -1,7 +1,7 @@
import { kebabCase } from 'lodash'; import { kebabCase } from 'lodash';
import canUseDom from 'rc-util/lib/Dom/canUseDom'; import canUseDom from 'rc-util/lib/Dom/canUseDom';
import ConfigProvider from '..'; import ConfigProvider from '..';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
let mockCanUseDom = true; let mockCanUseDom = true;

View File

@ -5,7 +5,7 @@ import canUseDom from 'rc-util/lib/Dom/canUseDom';
import { TinyColor } from '@ctrl/tinycolor'; import { TinyColor } from '@ctrl/tinycolor';
import { generate } from '@ant-design/colors'; import { generate } from '@ant-design/colors';
import type { Theme } from './context'; import type { Theme } from './context';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
const dynamicStyleMark = `-ant-${Date.now()}-${Math.random()}`; const dynamicStyleMark = `-ant-${Date.now()}-${Math.random()}`;
@ -101,6 +101,6 @@ export function registerTheme(globalPrefixCls: string, theme: Theme) {
if (canUseDom()) { if (canUseDom()) {
updateCSS(style, `${dynamicStyleMark}-dynamic-theme`); updateCSS(style, `${dynamicStyleMark}-dynamic-theme`);
} else { } else {
devWarning(false, 'ConfigProvider', 'SSR do not support dynamic theme with css variables.'); warning(false, 'ConfigProvider', 'SSR do not support dynamic theme with css variables.');
} }
} }

View File

@ -14,6 +14,8 @@ title:
Components which support rtl direction are listed here, you can toggle the direction in the demo. Components which support rtl direction are listed here, you can toggle the direction in the demo.
```jsx ```jsx
import React, { useState } from 'react';
import { import {
Input, Input,
Col, Col,
@ -103,23 +105,22 @@ const cascaderOptions = [
}, },
]; ];
class Page extends React.Component { function Page(props) {
state = { const [state, setState] = useState({
currentStep: 0, currentStep: 0,
modalVisible: false, modalVisible: false,
badgeCount: 5, badgeCount: 5,
showBadge: true, showBadge: true,
}; });
selectBefore = ( const selectBefore = (
<Select defaultValue="Http://" style={{ width: 90 }}> <Select defaultValue="Http://" style={{ width: 90 }}>
<Option value="Http://">Http://</Option> <Option value="Http://">Http://</Option>
<Option value="Https://">Https://</Option> <Option value="Https://">Https://</Option>
</Select> </Select>
); );
selectAfter = ( const selectAfter = (
<Select defaultValue=".com" style={{ width: 80 }}> <Select defaultValue=".com" style={{ width: 80 }}>
<Option value=".com">.com</Option> <Option value=".com">.com</Option>
<Option value=".jp">.jp</Option> <Option value=".jp">.jp</Option>
@ -129,437 +130,438 @@ class Page extends React.Component {
); );
// ==== Cascader ==== // ==== Cascader ====
cascaderFilter = (inputValue, path) => const cascaderFilter = (inputValue, path) =>
path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1); path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
onCascaderChange = value => { const onCascaderChange = value => {
console.log(value); console.log(value);
}; };
// ==== End Cascader ==== // ==== End Cascader ====
// ==== Modal ==== // ==== Modal ====
showModal = () => { const showModal = () => {
this.setState({ setState({
...state,
modalVisible: true, modalVisible: true,
}); });
}; };
handleOk = e => { const handleOk = e => {
console.log(e); console.log(e);
this.setState({ setState({
...state,
modalVisible: false, modalVisible: false,
}); });
}; };
handleCancel = e => { const handleCancel = e => {
console.log(e); console.log(e);
this.setState({ setState({
...state,
modalVisible: false, modalVisible: false,
}); });
}; };
// ==== End Modal ==== // ==== End Modal ====
onStepsChange = currentStep => { const onStepsChange = currentStep => {
console.log('onChange:', currentStep); console.log('onChange:', currentStep);
this.setState({ currentStep }); setState({
...state,
currentStep,
});
}; };
// ==== Badge ==== // ==== Badge ====
increaseBadge = () => { const increaseBadge = () => {
const badgeCount = this.state.badgeCount + 1; const badgeCount = state.badgeCount + 1;
this.setState({ badgeCount }); setState({
...state,
badgeCount,
});
}; };
declineBadge = () => { const declineBadge = () => {
let badgeCount = this.state.badgeCount - 1; let badgeCount = state.badgeCount - 1;
if (badgeCount < 0) { if (badgeCount < 0) {
badgeCount = 0; badgeCount = 0;
} }
this.setState({ badgeCount }); setState({
...state,
badgeCount,
});
}; };
onChangeBadge = showBadge => { const onChangeBadge = showBadge => {
this.setState({ showBadge }); setState({
...state,
showBadge,
});
}; };
// ==== End Badge ====
render() { return (
const { currentStep } = this.state; <div className="direction-components">
return ( <Row>
<div className="direction-components"> <Col span={24}>
<Row> <Divider orientation="left">Cascader example</Divider>
<Col span={24}> <Cascader
<Divider orientation="left">Cascader example</Divider> suffixIcon={<SearchIcon />}
<Cascader options={cascaderOptions}
suffixIcon={<SearchIcon />} onChange={onCascaderChange}
options={cascaderOptions} placeholder="یک مورد انتخاب کنید"
onChange={this.onCascaderChange} popupPlacement={props.popupPlacement}
placeholder="یک مورد انتخاب کنید" />
popupPlacement={this.props.popupPlacement} &nbsp;&nbsp;&nbsp;&nbsp; With search:
/> <Cascader
&nbsp;&nbsp;&nbsp;&nbsp; With search: suffixIcon={<SmileOutlined />}
<Cascader options={cascaderOptions}
suffixIcon={<SmileOutlined />} onChange={onCascaderChange}
options={cascaderOptions} placeholder="Select an item"
onChange={this.onCascaderChange} popupPlacement={props.popupPlacement}
placeholder="Select an item" showSearch={cascaderFilter}
popupPlacement={this.props.popupPlacement} />
showSearch={this.cascaderFilter} </Col>
/> </Row>
</Col> <br />
</Row> <Row>
<br /> <Col span={12}>
<Row> <Divider orientation="left">Switch example</Divider>
<Col span={12}> &nbsp;&nbsp;
<Divider orientation="left">Switch example</Divider> <Switch defaultChecked />
&nbsp;&nbsp; &nbsp;&nbsp;
<Switch defaultChecked /> <Switch loading defaultChecked />
&nbsp;&nbsp; &nbsp;&nbsp;
<Switch loading defaultChecked /> <Switch size="small" loading />
&nbsp;&nbsp; </Col>
<Switch size="small" loading /> <Col span={12}>
</Col> <Divider orientation="left">Radio Group example</Divider>
<Col span={12}>
<Divider orientation="left">Radio Group example</Divider>
<Radio.Group defaultValue="c" buttonStyle="solid"> <Radio.Group defaultValue="c" buttonStyle="solid">
<Radio.Button value="a">تهران</Radio.Button> <Radio.Button value="a">تهران</Radio.Button>
<Radio.Button value="b" disabled> <Radio.Button value="b" disabled>
اصفهان اصفهان
</Radio.Button> </Radio.Button>
<Radio.Button value="c">فارس</Radio.Button> <Radio.Button value="c">فارس</Radio.Button>
<Radio.Button value="d">خوزستان</Radio.Button> <Radio.Button value="d">خوزستان</Radio.Button>
</Radio.Group> </Radio.Group>
</Col> </Col>
</Row> </Row>
<br /> <br />
<Row> <Row>
<Col span={12}> <Col span={12}>
<Divider orientation="left">Button example</Divider> <Divider orientation="left">Button example</Divider>
<div className="button-demo"> <div className="button-demo">
<Button type="primary" icon={<DownloadOutlined />} /> <Button type="primary" icon={<DownloadOutlined />} />
<Button type="primary" shape="circle" icon={<DownloadOutlined />} /> <Button type="primary" shape="circle" icon={<DownloadOutlined />} />
<Button type="primary" shape="round" icon={<DownloadOutlined />} /> <Button type="primary" shape="round" icon={<DownloadOutlined />} />
<Button type="primary" shape="round" icon={<DownloadOutlined />}> <Button type="primary" shape="round" icon={<DownloadOutlined />}>
Download Download
</Button>
<Button type="primary" icon={<DownloadOutlined />}>
Download
</Button>
<br />
<Button.Group>
<Button type="primary">
<LeftOutlined />
Backward
</Button> </Button>
<Button type="primary" icon={<DownloadOutlined />}> <Button type="primary">
Download Forward
<RightOutlined />
</Button> </Button>
<br /> </Button.Group>
<Button.Group> <Button type="primary" loading>
<Button type="primary"> Loading
<LeftOutlined /> </Button>
Backward <Button type="primary" size="small" loading>
</Button> Loading
<Button type="primary"> </Button>
Forward </div>
<RightOutlined /> </Col>
</Button> <Col span={12}>
</Button.Group> <Divider orientation="left">Tree example</Divider>
<Button type="primary" loading> <Tree
Loading showLine
</Button> checkable
<Button type="primary" size="small" loading> defaultExpandedKeys={['0-0-0', '0-0-1']}
Loading defaultSelectedKeys={['0-0-0', '0-0-1']}
</Button> defaultCheckedKeys={['0-0-0', '0-0-1']}
</div> >
</Col> <TreeNode title="parent 1" key="0-0">
<Col span={12}> <TreeNode title="parent 1-0" key="0-0-0" disabled>
<Divider orientation="left">Tree example</Divider> <TreeNode title="leaf" key="0-0-0-0" disableCheckbox />
<Tree <TreeNode title="leaf" key="0-0-0-1" />
showLine
checkable
defaultExpandedKeys={['0-0-0', '0-0-1']}
defaultSelectedKeys={['0-0-0', '0-0-1']}
defaultCheckedKeys={['0-0-0', '0-0-1']}
>
<TreeNode title="parent 1" key="0-0">
<TreeNode title="parent 1-0" key="0-0-0" disabled>
<TreeNode title="leaf" key="0-0-0-0" disableCheckbox />
<TreeNode title="leaf" key="0-0-0-1" />
</TreeNode>
<TreeNode title="parent 1-1" key="0-0-1">
<TreeNode title={<span style={{ color: '#1890ff' }}>sss</span>} key="0-0-1-0" />
</TreeNode>
</TreeNode> </TreeNode>
</Tree> <TreeNode title="parent 1-1" key="0-0-1">
</Col> <TreeNode title={<span style={{ color: '#1890ff' }}>sss</span>} key="0-0-1-0" />
</Row> </TreeNode>
<br /> </TreeNode>
<Row> </Tree>
<Col span={24}> </Col>
<Divider orientation="left">Input (Input Group) example</Divider> </Row>
<InputGroup size="large"> <br />
<Row gutter={8}> <Row>
<Col span={5}> <Col span={24}>
<Input defaultValue="0571" /> <Divider orientation="left">Input (Input Group) example</Divider>
</Col> <InputGroup size="large">
<Col span={8}> <Row gutter={8}>
<Input defaultValue="26888888" /> <Col span={5}>
<Input defaultValue="0571" />
</Col>
<Col span={8}>
<Input defaultValue="26888888" />
</Col>
</Row>
</InputGroup>
<br />
<InputGroup compact>
<Input style={{ width: '20%' }} defaultValue="0571" />
<Input style={{ width: '30%' }} defaultValue="26888888" />
</InputGroup>
<br />
<InputGroup compact>
<Select defaultValue="Option1">
<Option value="Option1">Option1</Option>
<Option value="Option2">Option2</Option>
</Select>
<Input style={{ width: '50%' }} defaultValue="input content" />
<InputNumber />
</InputGroup>
<br />
<Search placeholder="input search text" enterButton="Search" size="large" />
<br />
<br />
<div style={{ marginBottom: 16 }}>
<Input addonBefore={selectBefore} addonAfter={selectAfter} defaultValue="mysite" />
</div>
<br />
<Row>
<Col span={12}>
<Divider orientation="left">Select example</Divider>
<Select mode="multiple" defaultValue="مورچه" style={{ width: 120 }}>
<Option value="jack">Jack</Option>
<Option value="مورچه">مورچه</Option>
<Option value="disabled" disabled>
Disabled
</Option>
<Option value="Yiminghe">yiminghe</Option>
</Select>
<Select defaultValue="مورچه" style={{ width: 120 }} disabled>
<Option value="مورچه">مورچه</Option>
</Select>
<Select defaultValue="مورچه" style={{ width: 120 }} loading>
<Option value="مورچه">مورچه</Option>
</Select>
<Select
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="jack">Jack</Option>
<Option value="سعید">سعید</Option>
<Option value="tom">Tom</Option>
</Select>
</Col>
<Col span={12}>
<Divider orientation="left">TreeSelect example</Divider>
<div>
<TreeSelect
showSearch
style={{ width: '100%' }}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
placeholder="Please select"
allowClear
treeDefaultExpandAll
>
<TreeNode value="parent 1" title="parent 1" key="0-1">
<TreeNode value="parent 1-0" title="parent 1-0" key="0-1-1">
<TreeNode value="leaf1" title="my leaf" key="random" />
<TreeNode value="leaf2" title="your leaf" key="random1" />
</TreeNode>
<TreeNode value="parent 1-1" title="parent 1-1" key="random2">
<TreeNode
value="sss"
title={<b style={{ color: '#08c' }}>sss</b>}
key="random3"
/>
</TreeNode>
</TreeNode>
</TreeSelect>
</div>
</Col>
</Row>
<br />
<Row>
<Col span={24}>
<Divider orientation="left">Modal example</Divider>
<div>
<Button type="primary" onClick={showModal}>
Open Modal
</Button>
<Modal
title="پنچره ساده"
visible={state.modalVisible}
onOk={handleOk}
onCancel={handleCancel}
>
<p>نگاشته‌های خود را اینجا قراردهید</p>
<p>نگاشته‌های خود را اینجا قراردهید</p>
<p>نگاشته‌های خود را اینجا قراردهید</p>
</Modal>
</div>
</Col>
</Row>
<br />
<Row>
<Col span={24}>
<Divider orientation="left">Steps example</Divider>
<div>
<Steps progressDot current={state.currentStep}>
<Step title="Finished" description="This is a description." />
<Step title="In Progress" description="This is a description." />
<Step title="Waiting" description="This is a description." />
</Steps>
<br />
<Steps current={state.currentStep} onChange={onStepsChange}>
<Step title="Step 1" description="This is a description." />
<Step title="Step 2" description="This is a description." />
<Step title="Step 3" description="This is a description." />
</Steps>
</div>
</Col>
</Row>
<br />
<Row>
<Col span={12}>
<Divider orientation="left">Rate example</Divider>
<div>
<Rate defaultValue={2.5} />
<br />
<strong>* Note:</strong> Half star not implemented in RTL direction, it will be
supported after <a href="https://github.com/react-component/rate">rc-rate</a>{' '}
implement rtl support.
</div>
</Col>
<Col span={12}>
<Divider orientation="left">Badge example</Divider>
<div>
<div>
<Badge count={state.badgeCount}>
<a href="#" className="head-example" />
</Badge>
<ButtonGroup>
<Button onClick={declineBadge}>
<MinusOutlined />
</Button>
<Button onClick={increaseBadge}>
<PlusOutlined />
</Button>
</ButtonGroup>
</div>
<div style={{ marginTop: 10 }}>
<Badge dot={state.showBadge}>
<a href="#" className="head-example" />
</Badge>
<Switch onChange={onChangeBadge} checked={state.showBadge} />
</div>
</div>
</Col>
</Row>
</Col>
</Row>
<br />
<br />
<Row>
<Col span={24}>
<Divider orientation="left">Pagination example</Divider>
<Pagination showSizeChanger defaultCurrent={3} total={500} />
</Col>
</Row>
<br />
<Row>
<Col span={24}>
<Divider orientation="left">Grid System example</Divider>
<div className="grid-demo">
<div className="code-box-demo">
<p>
<strong>* Note:</strong> Every calculation in RTL grid system is from right side
(offset, push, etc.)
</p>
<Row>
<Col span={8}>col-8</Col>
<Col span={8} offset={8}>
col-8
</Col>
</Row>
<Row>
<Col span={6} offset={6}>
col-6 col-offset-6
</Col>
<Col span={6} offset={6}>
col-6 col-offset-6
</Col>
</Row>
<Row>
<Col span={12} offset={6}>
col-12 col-offset-6
</Col>
</Row>
<Row>
<Col span={18} push={6}>
col-18 col-push-6
</Col>
<Col span={6} pull={18}>
col-6 col-pull-18
</Col> </Col>
</Row> </Row>
</InputGroup>
<br />
<InputGroup compact>
<Input style={{ width: '20%' }} defaultValue="0571" />
<Input style={{ width: '30%' }} defaultValue="26888888" />
</InputGroup>
<br />
<InputGroup compact>
<Select defaultValue="Option1">
<Option value="Option1">Option1</Option>
<Option value="Option2">Option2</Option>
</Select>
<Input style={{ width: '50%' }} defaultValue="input content" />
<InputNumber />
</InputGroup>
<br />
<Search placeholder="input search text" enterButton="Search" size="large" />
<br />
<br />
<div style={{ marginBottom: 16 }}>
<Input
addonBefore={this.selectBefore}
addonAfter={this.selectAfter}
defaultValue="mysite"
/>
</div> </div>
<br /> </div>
<Row> </Col>
<Col span={12}> </Row>
<Divider orientation="left">Select example</Divider> </div>
<Select mode="multiple" defaultValue="مورچه" style={{ width: 120 }}> );
<Option value="jack">Jack</Option>
<Option value="مورچه">مورچه</Option>
<Option value="disabled" disabled>
Disabled
</Option>
<Option value="Yiminghe">yiminghe</Option>
</Select>
<Select defaultValue="مورچه" style={{ width: 120 }} disabled>
<Option value="مورچه">مورچه</Option>
</Select>
<Select defaultValue="مورچه" style={{ width: 120 }} loading>
<Option value="مورچه">مورچه</Option>
</Select>
<Select
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="jack">Jack</Option>
<Option value="سعید">سعید</Option>
<Option value="tom">Tom</Option>
</Select>
</Col>
<Col span={12}>
<Divider orientation="left">TreeSelect example</Divider>
<div>
<TreeSelect
showSearch
style={{ width: '100%' }}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
placeholder="Please select"
allowClear
treeDefaultExpandAll
>
<TreeNode value="parent 1" title="parent 1" key="0-1">
<TreeNode value="parent 1-0" title="parent 1-0" key="0-1-1">
<TreeNode value="leaf1" title="my leaf" key="random" />
<TreeNode value="leaf2" title="your leaf" key="random1" />
</TreeNode>
<TreeNode value="parent 1-1" title="parent 1-1" key="random2">
<TreeNode
value="sss"
title={<b style={{ color: '#08c' }}>sss</b>}
key="random3"
/>
</TreeNode>
</TreeNode>
</TreeSelect>
</div>
</Col>
</Row>
<br />
<Row>
<Col span={24}>
<Divider orientation="left">Modal example</Divider>
<div>
<Button type="primary" onClick={this.showModal}>
Open Modal
</Button>
<Modal
title="پنچره ساده"
visible={this.state.modalVisible}
onOk={this.handleOk}
onCancel={this.handleCancel}
>
<p>نگاشته‌های خود را اینجا قراردهید</p>
<p>نگاشته‌های خود را اینجا قراردهید</p>
<p>نگاشته‌های خود را اینجا قراردهید</p>
</Modal>
</div>
</Col>
</Row>
<br />
<Row>
<Col span={24}>
<Divider orientation="left">Steps example</Divider>
<div>
<Steps progressDot current={currentStep}>
<Step title="Finished" description="This is a description." />
<Step title="In Progress" description="This is a description." />
<Step title="Waiting" description="This is a description." />
</Steps>
<br />
<Steps current={currentStep} onChange={this.onStepsChange}>
<Step title="Step 1" description="This is a description." />
<Step title="Step 2" description="This is a description." />
<Step title="Step 3" description="This is a description." />
</Steps>
</div>
</Col>
</Row>
<br />
<Row>
<Col span={12}>
<Divider orientation="left">Rate example</Divider>
<div>
<Rate defaultValue={2.5} />
<br />
<strong>* Note:</strong> Half star not implemented in RTL direction, it will be
supported after <a href="https://github.com/react-component/rate">rc-rate</a>{' '}
implement rtl support.
</div>
</Col>
<Col span={12}>
<Divider orientation="left">Badge example</Divider>
<div>
<div>
<Badge count={this.state.badgeCount}>
<a href="#" className="head-example" />
</Badge>
<ButtonGroup>
<Button onClick={this.declineBadge}>
<MinusOutlined />
</Button>
<Button onClick={this.increaseBadge}>
<PlusOutlined />
</Button>
</ButtonGroup>
</div>
<div style={{ marginTop: 10 }}>
<Badge dot={this.state.showBadge}>
<a href="#" className="head-example" />
</Badge>
<Switch onChange={this.onChangeBadge} checked={this.state.showBadge} />
</div>
</div>
</Col>
</Row>
</Col>
</Row>
<br />
<br />
<Row>
<Col span={24}>
<Divider orientation="left">Pagination example</Divider>
<Pagination showSizeChanger defaultCurrent={3} total={500} />
</Col>
</Row>
<br />
<Row>
<Col span={24}>
<Divider orientation="left">Grid System example</Divider>
<div className="grid-demo">
<div className="code-box-demo">
<p>
<strong>* Note:</strong> Every calculation in RTL grid system is from right side
(offset, push, etc.)
</p>
<Row>
<Col span={8}>col-8</Col>
<Col span={8} offset={8}>
col-8
</Col>
</Row>
<Row>
<Col span={6} offset={6}>
col-6 col-offset-6
</Col>
<Col span={6} offset={6}>
col-6 col-offset-6
</Col>
</Row>
<Row>
<Col span={12} offset={6}>
col-12 col-offset-6
</Col>
</Row>
<Row>
<Col span={18} push={6}>
col-18 col-push-6
</Col>
<Col span={6} pull={18}>
col-6 col-pull-18
</Col>
</Row>
</div>
</div>
</Col>
</Row>
</div>
);
}
} }
class App extends React.Component { export default () => {
state = { const [direction, setDirection] = useState('ltr');
direction: 'ltr', const [popupPlacement, setPopupPlacement] = useState('bottomLeft');
popupPlacement: 'bottomLeft',
};
changeDirection = e => { const changeDirection = e => {
const directionValue = e.target.value; const directionValue = e.target.value;
this.setState({ direction: directionValue }); setDirection(directionValue);
if (directionValue === 'rtl') { if (directionValue === 'rtl') {
this.setState({ popupPlacement: 'bottomRight' }); setPopupPlacement('bottomRight');
} else { } else {
this.setState({ popupPlacement: 'bottomLeft' }); setPopupPlacement('bottomLeft');
} }
}; };
render() { return (
const { direction, popupPlacement } = this.state; <>
return ( <div style={{ marginBottom: 16 }}>
<> <span style={{ marginRight: 16 }}>Change direction of components: </span>
<div style={{ marginBottom: 16 }}> <Radio.Group defaultValue="ltr" onChange={changeDirection}>
<span style={{ marginRight: 16 }}>Change direction of components: </span> <Radio.Button key="ltr" value="ltr">
<Radio.Group defaultValue="ltr" onChange={this.changeDirection}> LTR
<Radio.Button key="ltr" value="ltr"> </Radio.Button>
LTR <Radio.Button key="rtl" value="rtl">
</Radio.Button> RTL
<Radio.Button key="rtl" value="rtl"> </Radio.Button>
RTL </Radio.Group>
</Radio.Button> </div>
</Radio.Group> <ConfigProvider direction={direction}>
</div> <Page className={direction} popupPlacement={popupPlacement} />
<ConfigProvider direction={direction}> </ConfigProvider>
<Page className={direction} popupPlacement={popupPlacement} /> </>
</ConfigProvider> );
</> };
);
}
}
export default App;
``` ```
```css ```css

View File

@ -55,84 +55,77 @@ const columns = [
}, },
]; ];
class Page extends React.Component { function Page() {
state = { const [visible, setVisible] = React.useState(false);
visible: false,
const showModal = () => {
setVisible(true);
}; };
showModal = () => { const hideModal = () => {
this.setState({ visible: true }); setVisible(false);
}; };
hideModal = () => { const info = () => {
this.setState({ visible: false }); Modal.info({
title: 'some info',
content: 'some info',
});
}; };
render() { const confirm = () => {
const info = () => { Modal.confirm({
Modal.info({ title: 'some info',
title: 'some info', content: 'some info',
content: 'some info', });
}); };
};
const confirm = () => { return (
Modal.confirm({ <div className="locale-components">
title: 'some info', <div className="example">
content: 'some info', <Pagination defaultCurrent={1} total={50} showSizeChanger />
});
};
return (
<div className="locale-components">
<div className="example">
<Pagination defaultCurrent={1} total={50} showSizeChanger />
</div>
<div className="example">
<Select showSearch style={{ width: 200 }}>
<Option value="jack">jack</Option>
<Option value="lucy">lucy</Option>
</Select>
<DatePicker />
<TimePicker />
<RangePicker style={{ width: 200 }} />
</div>
<div className="example">
<Button type="primary" onClick={this.showModal}>
Show Modal
</Button>
<Button onClick={info}>Show info</Button>
<Button onClick={confirm}>Show confirm</Button>
<Popconfirm title="Question?">
<a href="#">Click to confirm</a>
</Popconfirm>
</div>
<div className="example">
<Transfer dataSource={[]} showSearch targetKeys={[]} render={item => item.title} />
</div>
<div className="site-config-provider-calendar-wrapper">
<Calendar fullscreen={false} value={moment()} />
</div>
<div className="example">
<Table dataSource={[]} columns={columns} />
</div>
<Modal title="Locale Modal" visible={this.state.visible} onCancel={this.hideModal}>
<p>Locale Modal</p>
</Modal>
</div> </div>
); <div className="example">
} <Select showSearch style={{ width: 200 }}>
<Option value="jack">jack</Option>
<Option value="lucy">lucy</Option>
</Select>
<DatePicker />
<TimePicker />
<RangePicker style={{ width: 200 }} />
</div>
<div className="example">
<Button type="primary" onClick={showModal}>
Show Modal
</Button>
<Button onClick={info}>Show info</Button>
<Button onClick={confirm}>Show confirm</Button>
<Popconfirm title="Question?">
<a href="#">Click to confirm</a>
</Popconfirm>
</div>
<div className="example">
<Transfer dataSource={[]} showSearch targetKeys={[]} render={item => item.title} />
</div>
<div className="site-config-provider-calendar-wrapper">
<Calendar fullscreen={false} value={moment()} />
</div>
<div className="example">
<Table dataSource={[]} columns={columns} />
</div>
<Modal title="Locale Modal" visible={visible} onCancel={hideModal}>
<p>Locale Modal</p>
</Modal>
</div>
);
} }
class App extends React.Component { export default () => {
constructor() { const [locale, setLocale] = React.useState(enUS);
super();
this.state = {
locale: enUS,
};
}
changeLocale = e => { const changeLocale = e => {
const localeValue = e.target.value; const localeValue = e.target.value;
this.setState({ locale: localeValue }); setLocale(localeValue);
if (!localeValue) { if (!localeValue) {
moment.locale('en'); moment.locale('en');
} else { } else {
@ -140,32 +133,27 @@ class App extends React.Component {
} }
}; };
render() { return (
const { locale } = this.state; <div>
return ( <div className="change-locale">
<div> <span style={{ marginRight: 16 }}>Change locale of components: </span>
<div className="change-locale"> <Radio.Group value={locale} onChange={changeLocale}>
<span style={{ marginRight: 16 }}>Change locale of components: </span> <Radio.Button key="en" value={enUS}>
<Radio.Group value={locale} onChange={this.changeLocale}> English
<Radio.Button key="en" value={enUS}> </Radio.Button>
English <Radio.Button key="cn" value={zhCN}>
</Radio.Button> 中文
<Radio.Button key="cn" value={zhCN}> </Radio.Button>
中文 </Radio.Group>
</Radio.Button>
</Radio.Group>
</div>
<ConfigProvider locale={locale}>
<Page
key={locale ? locale.locale : 'en' /* Have to refresh for production environment */}
/>
</ConfigProvider>
</div> </div>
); <ConfigProvider locale={locale}>
} <Page
} key={locale ? locale.locale : 'en' /* Have to refresh for production environment */}
/>
export default App; </ConfigProvider>
</div>
);
};
``` ```
```css ```css

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import DatePicker from '..'; import DatePicker from '..';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
const { QuarterPicker } = DatePicker; const { QuarterPicker } = DatePicker;

View File

@ -13927,7 +13927,7 @@ exports[`renders ./components/date-picker/demo/disabled-date.md extend context c
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -16873,7 +16873,7 @@ exports[`renders ./components/date-picker/demo/disabled-date.md extend context c
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -19439,7 +19439,7 @@ exports[`renders ./components/date-picker/demo/extra-footer.md extend context co
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -22634,7 +22634,7 @@ exports[`renders ./components/date-picker/demo/extra-footer.md extend context co
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -28295,7 +28295,7 @@ exports[`renders ./components/date-picker/demo/mode.md extend context correctly
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -33676,7 +33676,7 @@ exports[`renders ./components/date-picker/demo/presetted-ranges.md extend contex
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -36864,7 +36864,7 @@ exports[`renders ./components/date-picker/demo/range-picker.md extend context co
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -45240,7 +45240,7 @@ exports[`renders ./components/date-picker/demo/start-end.md extend context corre
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -47190,7 +47190,7 @@ exports[`renders ./components/date-picker/demo/start-end.md extend context corre
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -57627,7 +57627,7 @@ exports[`renders ./components/date-picker/demo/switchable.md extend context corr
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -59585,7 +59585,7 @@ exports[`renders ./components/date-picker/demo/time.md extend context correctly
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -61037,7 +61037,7 @@ exports[`renders ./components/date-picker/demo/time.md extend context correctly
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>

View File

@ -15,65 +15,60 @@ debug: true
Determing which panel to show with `mode` and `onPanelChange`. Determing which panel to show with `mode` and `onPanelChange`.
```jsx ```jsx
import React, { useState } from 'react';
import { DatePicker, Space } from 'antd'; import { DatePicker, Space } from 'antd';
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
class ControlledDatePicker extends React.Component { function ControlledDatePicker() {
state = { mode: 'time' }; const [mode, setMode] = useState('time');
handleOpenChange = open => { const handleOpenChange = open => {
if (open) { if (open) {
this.setState({ mode: 'time' }); setMode('time');
} }
}; };
handlePanelChange = (value, mode) => { const handlePanelChange = (value, dateMode) => {
this.setState({ mode }); setMode(dateMode);
}; };
render() { return (
return ( <DatePicker
<DatePicker mode={mode}
mode={this.state.mode} showTime
showTime onOpenChange={handleOpenChange}
onOpenChange={this.handleOpenChange} onPanelChange={handlePanelChange}
onPanelChange={this.handlePanelChange} />
/> );
);
}
} }
class ControlledRangePicker extends React.Component { function ControlledRangePicker() {
state = { const [mode, setMode] = useState(['month', 'month']);
mode: ['month', 'month'], const [value, setValue] = useState([]);
value: [],
const handlePanelChange = (dateValue, dateMode) => {
setValue(dateValue);
setMode([
dateMode[0] === 'date' ? 'month' : dateMode[0],
dateMode[1] === 'date' ? 'month' : dateMode[1],
]);
}; };
handlePanelChange = (value, mode) => { const handleChange = dateValue => {
this.setState({ setValue(dateValue);
value,
mode: [mode[0] === 'date' ? 'month' : mode[0], mode[1] === 'date' ? 'month' : mode[1]],
});
}; };
handleChange = value => { return (
this.setState({ value }); <RangePicker
}; placeholder={['Start month', 'End month']}
format="YYYY-MM"
render() { value={value}
const { value, mode } = this.state; mode={mode}
return ( onChange={handleChange}
<RangePicker onPanelChange={handlePanelChange}
placeholder={['Start month', 'End month']} />
format="YYYY-MM" );
value={value}
mode={mode}
onChange={this.handleChange}
onPanelChange={this.handlePanelChange}
/>
);
}
} }
export default () => ( export default () => (

View File

@ -18,32 +18,25 @@ import { DatePicker, Radio, Space } from 'antd';
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
class PickerSizesDemo extends React.Component { export default () => {
state = { const [size, setSize] = React.useState('default');
size: 'default',
const handleSizeChange = e => {
setSize(e.target.value);
}; };
handleSizeChange = e => { return (
this.setState({ size: e.target.value }); <Space direction="vertical" size={12}>
}; <Radio.Group value={size} onChange={handleSizeChange}>
<Radio.Button value="large">Large</Radio.Button>
render() { <Radio.Button value="default">Default</Radio.Button>
const { size } = this.state; <Radio.Button value="small">Small</Radio.Button>
return ( </Radio.Group>
<Space direction="vertical" size={12}> <DatePicker size={size} />
<Radio.Group value={size} onChange={this.handleSizeChange}> <DatePicker size={size} picker="month" />
<Radio.Button value="large">Large</Radio.Button> <RangePicker size={size} />
<Radio.Button value="default">Default</Radio.Button> <DatePicker size={size} picker="week" />
<Radio.Button value="small">Small</Radio.Button> </Space>
</Radio.Group> );
<DatePicker size={size} /> };
<DatePicker size={size} picker="month" />
<RangePicker size={size} />
<DatePicker size={size} picker="week" />
</Space>
);
}
}
export default () => <PickerSizesDemo />;
``` ```

View File

@ -23,80 +23,76 @@ When `RangePicker` does not satisfied your requirements, try to implement simila
```jsx ```jsx
import { DatePicker, Space } from 'antd'; import { DatePicker, Space } from 'antd';
class DateRange extends React.Component { export default () => {
state = { const [state, setState] = React.useState({
startValue: null, startValue: null,
endValue: null, endValue: null,
endOpen: false, endOpen: false,
}; });
disabledStartDate = startValue => { const disabledStartDate = startValue => {
const { endValue } = this.state; const { endValue } = state;
if (!startValue || !endValue) { if (!startValue || !endValue) {
return false; return false;
} }
return startValue.valueOf() > endValue.valueOf(); return startValue.valueOf() > endValue.valueOf();
}; };
disabledEndDate = endValue => { const disabledEndDate = endValue => {
const { startValue } = this.state; const { startValue } = state;
if (!endValue || !startValue) { if (!endValue || !startValue) {
return false; return false;
} }
return endValue.valueOf() <= startValue.valueOf(); return endValue.valueOf() <= startValue.valueOf();
}; };
onChange = (field, value) => { const onChange = (field, value) => {
this.setState({ setState({
...state,
[field]: value, [field]: value,
}); });
}; };
onStartChange = value => { const onStartChange = value => {
this.onChange('startValue', value); onChange('startValue', value);
}; };
onEndChange = value => { const onEndChange = value => {
this.onChange('endValue', value); onChange('endValue', value);
}; };
handleStartOpenChange = open => { const handleStartOpenChange = open => {
if (!open) { if (!open) {
this.setState({ endOpen: true }); setState({ ...state, endOpen: true });
} }
}; };
handleEndOpenChange = open => { const handleEndOpenChange = open => {
this.setState({ endOpen: open }); setState({ ...state, endOpen: true });
}; };
render() { return (
const { startValue, endValue, endOpen } = this.state; <Space>
return ( <DatePicker
<Space> disabledDate={disabledStartDate}
<DatePicker showTime
disabledDate={this.disabledStartDate} format="YYYY-MM-DD HH:mm:ss"
showTime value={state.startValue}
format="YYYY-MM-DD HH:mm:ss" placeholder="Start"
value={startValue} onChange={onStartChange}
placeholder="Start" onOpenChange={handleStartOpenChange}
onChange={this.onStartChange} />
onOpenChange={this.handleStartOpenChange} <DatePicker
/> disabledDate={disabledEndDate}
<DatePicker showTime
disabledDate={this.disabledEndDate} format="YYYY-MM-DD HH:mm:ss"
showTime value={state.endValue}
format="YYYY-MM-DD HH:mm:ss" placeholder="End"
value={endValue} onChange={onEndChange}
placeholder="End" open={state.endOpen}
onChange={this.onEndChange} onOpenChange={handleEndOpenChange}
open={endOpen} />
onOpenChange={this.handleEndOpenChange} </Space>
/> );
</Space> };
);
}
}
export default () => <DateRange />;
``` ```

View File

@ -9,7 +9,7 @@ import type { GenerateConfig } from 'rc-picker/lib/generate/index';
import { forwardRef, useContext } from 'react'; import { forwardRef, useContext } from 'react';
import enUS from '../locale/en_US'; import enUS from '../locale/en_US';
import { getPlaceholder, transPlacement2DropdownAlign } from '../util'; import { getPlaceholder, transPlacement2DropdownAlign } from '../util';
import devWarning from '../../_util/devWarning'; import warning from '../../_util/warning';
import { ConfigContext } from '../../config-provider'; import { ConfigContext } from '../../config-provider';
import LocaleReceiver from '../../locale-provider/LocaleReceiver'; import LocaleReceiver from '../../locale-provider/LocaleReceiver';
import SizeContext from '../../config-provider/SizeContext'; import SizeContext from '../../config-provider/SizeContext';
@ -46,13 +46,7 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
...restProps ...restProps
} = props; } = props;
devWarning( warning(
picker !== 'quarter',
displayName!,
`DatePicker.${displayName} is legacy usage. Please use DatePicker[picker='${picker}'] directly.`,
);
devWarning(
picker !== 'quarter', picker !== 'quarter',
displayName!, displayName!,
`DatePicker.${displayName} is legacy usage. Please use DatePicker[picker='${picker}'] directly.`, `DatePicker.${displayName} is legacy usage. Please use DatePicker[picker='${picker}'] directly.`,

View File

@ -3,7 +3,7 @@ import MockDate from 'mockdate';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import Descriptions from '..'; import Descriptions from '..';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
describe('Descriptions', () => { describe('Descriptions', () => {
mountTest(Descriptions); mountTest(Descriptions);

View File

@ -16,72 +16,60 @@ Custom sizes to fit in a variety of containers.
```jsx ```jsx
import { Descriptions, Radio, Button } from 'antd'; import { Descriptions, Radio, Button } from 'antd';
class Demo extends React.Component { export default () => {
state = { const [size, setSize] = React.useState('default');
size: 'default',
};
onChange = e => { const onChange = e => {
console.log('size checked', e.target.value); console.log('size checked', e.target.value);
this.setState({ setSize(e.target.value);
size: e.target.value,
});
}; };
render() { return (
return ( <div>
<div> <Radio.Group onChange={onChange} value={size}>
<Radio.Group onChange={this.onChange} value={this.state.size}> <Radio value="default">default</Radio>
<Radio value="default">default</Radio> <Radio value="middle">middle</Radio>
<Radio value="middle">middle</Radio> <Radio value="small">small</Radio>
<Radio value="small">small</Radio> </Radio.Group>
</Radio.Group> <br />
<br /> <br />
<br /> <Descriptions
<Descriptions bordered
bordered title="Custom Size"
title="Custom Size" size={size}
size={this.state.size} extra={<Button type="primary">Edit</Button>}
extra={<Button type="primary">Edit</Button>} >
> <Descriptions.Item label="Product">Cloud Database</Descriptions.Item>
<Descriptions.Item label="Product">Cloud Database</Descriptions.Item> <Descriptions.Item label="Billing">Prepaid</Descriptions.Item>
<Descriptions.Item label="Billing">Prepaid</Descriptions.Item> <Descriptions.Item label="time">18:00:00</Descriptions.Item>
<Descriptions.Item label="time">18:00:00</Descriptions.Item> <Descriptions.Item label="Amount">$80.00</Descriptions.Item>
<Descriptions.Item label="Amount">$80.00</Descriptions.Item> <Descriptions.Item label="Discount">$20.00</Descriptions.Item>
<Descriptions.Item label="Discount">$20.00</Descriptions.Item> <Descriptions.Item label="Official">$60.00</Descriptions.Item>
<Descriptions.Item label="Official">$60.00</Descriptions.Item> <Descriptions.Item label="Config Info">
<Descriptions.Item label="Config Info"> Data disk type: MongoDB
Data disk type: MongoDB <br />
<br /> Database version: 3.4
Database version: 3.4 <br />
<br /> Package: dds.mongo.mid
Package: dds.mongo.mid <br />
<br /> Storage space: 10 GB
Storage space: 10 GB <br />
<br /> Replication factor: 3
Replication factor: 3 <br />
<br /> Region: East China 1<br />
Region: East China 1<br /> </Descriptions.Item>
</Descriptions.Item> </Descriptions>
</Descriptions> <br />
<br /> <br />
<br /> <Descriptions title="Custom Size" size={size} extra={<Button type="primary">Edit</Button>}>
<Descriptions <Descriptions.Item label="Product">Cloud Database</Descriptions.Item>
title="Custom Size" <Descriptions.Item label="Billing">Prepaid</Descriptions.Item>
size={this.state.size} <Descriptions.Item label="time">18:00:00</Descriptions.Item>
extra={<Button type="primary">Edit</Button>} <Descriptions.Item label="Amount">$80.00</Descriptions.Item>
> <Descriptions.Item label="Discount">$20.00</Descriptions.Item>
<Descriptions.Item label="Product">Cloud Database</Descriptions.Item> <Descriptions.Item label="Official">$60.00</Descriptions.Item>
<Descriptions.Item label="Billing">Prepaid</Descriptions.Item> </Descriptions>
<Descriptions.Item label="time">18:00:00</Descriptions.Item> </div>
<Descriptions.Item label="Amount">$80.00</Descriptions.Item> );
<Descriptions.Item label="Discount">$20.00</Descriptions.Item> };
<Descriptions.Item label="Official">$60.00</Descriptions.Item>
</Descriptions>
</div>
);
}
}
export default Demo;
``` ```

View File

@ -4,7 +4,7 @@ import classNames from 'classnames';
import toArray from 'rc-util/lib/Children/toArray'; import toArray from 'rc-util/lib/Children/toArray';
import type { Breakpoint, ScreenMap } from '../_util/responsiveObserve'; import type { Breakpoint, ScreenMap } from '../_util/responsiveObserve';
import ResponsiveObserve, { responsiveArray } from '../_util/responsiveObserve'; import ResponsiveObserve, { responsiveArray } from '../_util/responsiveObserve';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import Row from './Row'; import Row from './Row';
import DescriptionsItem from './Item'; import DescriptionsItem from './Item';
@ -54,7 +54,7 @@ function getFilledItem(
clone = cloneElement(node, { clone = cloneElement(node, {
span: rowRestCol, span: rowRestCol,
}); });
devWarning( warning(
span === undefined, span === undefined,
'Descriptions', 'Descriptions',
'Sum of column `span` in a line not match `column` of Descriptions.', 'Sum of column `span` in a line not match `column` of Descriptions.',

View File

@ -4,7 +4,7 @@ import classNames from 'classnames';
import RightOutlined from '@ant-design/icons/RightOutlined'; import RightOutlined from '@ant-design/icons/RightOutlined';
import DropdownButton from './dropdown-button'; import DropdownButton from './dropdown-button';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import { tuple } from '../_util/type'; import { tuple } from '../_util/type';
import { cloneElement } from '../_util/reactNode'; import { cloneElement } from '../_util/reactNode';
import getPlacements from '../_util/placements'; import getPlacements from '../_util/placements';
@ -105,7 +105,7 @@ const Dropdown: DropdownInterface = props => {
const overlayProps = overlayNode.props; const overlayProps = overlayNode.props;
// Warning if use other mode // Warning if use other mode
devWarning( warning(
!overlayProps.mode || overlayProps.mode === 'vertical', !overlayProps.mode || overlayProps.mode === 'vertical',
'Dropdown', 'Dropdown',
`mode="${overlayProps.mode}" is not supported for Dropdown's Menu.`, `mode="${overlayProps.mode}" is not supported for Dropdown's Menu.`,
@ -143,7 +143,7 @@ const Dropdown: DropdownInterface = props => {
if (placement.includes('Center')) { if (placement.includes('Center')) {
const newPlacement = placement.slice(0, placement.indexOf('Center')); const newPlacement = placement.slice(0, placement.indexOf('Center'));
devWarning( warning(
!placement.includes('Center'), !placement.includes('Center'),
'Dropdown', 'Dropdown',
`You are using '${placement}' placement in Dropdown, which is deprecated. Try to use '${newPlacement}' instead.`, `You are using '${placement}' placement in Dropdown, which is deprecated. Try to use '${newPlacement}' instead.`,

View File

@ -16,7 +16,7 @@ import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
import Row from '../grid/row'; import Row from '../grid/row';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import { tuple } from '../_util/type'; import { tuple } from '../_util/type';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import type { FormItemLabelProps, LabelTooltipType } from './FormItemLabel'; import type { FormItemLabelProps, LabelTooltipType } from './FormItemLabel';
import FormItemLabel from './FormItemLabel'; import FormItemLabel from './FormItemLabel';
import type { FormItemInputProps } from './FormItemInput'; import type { FormItemInputProps } from './FormItemInput';
@ -77,7 +77,7 @@ export interface FormItemProps<Values = any>
function hasValidName(name?: NamePath): Boolean { function hasValidName(name?: NamePath): Boolean {
if (name === null) { if (name === null) {
devWarning(false, 'Form.Item', '`null` is passed as `name` property'); warning(false, 'Form.Item', '`null` is passed as `name` property');
} }
return !(name === undefined || name === null); return !(name === undefined || name === null);
} }
@ -387,33 +387,33 @@ function FormItem<Values = any>(props: FormItemProps<Values>): React.ReactElemen
let childNode: React.ReactNode = null; let childNode: React.ReactNode = null;
devWarning( warning(
!(shouldUpdate && dependencies), !(shouldUpdate && dependencies),
'Form.Item', 'Form.Item',
"`shouldUpdate` and `dependencies` shouldn't be used together. See https://ant.design/components/form/#dependencies.", "`shouldUpdate` and `dependencies` shouldn't be used together. See https://ant.design/components/form/#dependencies.",
); );
if (Array.isArray(children) && hasName) { if (Array.isArray(children) && hasName) {
devWarning(false, 'Form.Item', '`children` is array of render props cannot have `name`.'); warning(false, 'Form.Item', '`children` is array of render props cannot have `name`.');
childNode = children; childNode = children;
} else if (isRenderProps && (!(shouldUpdate || dependencies) || hasName)) { } else if (isRenderProps && (!(shouldUpdate || dependencies) || hasName)) {
devWarning( warning(
!!(shouldUpdate || dependencies), !!(shouldUpdate || dependencies),
'Form.Item', 'Form.Item',
'`children` of render props only work with `shouldUpdate` or `dependencies`.', '`children` of render props only work with `shouldUpdate` or `dependencies`.',
); );
devWarning( warning(
!hasName, !hasName,
'Form.Item', 'Form.Item',
"Do not use `name` with `children` of render props since it's not a field.", "Do not use `name` with `children` of render props since it's not a field.",
); );
} else if (dependencies && !isRenderProps && !hasName) { } else if (dependencies && !isRenderProps && !hasName) {
devWarning( warning(
false, false,
'Form.Item', 'Form.Item',
'Must set `name` or use render props when `dependencies` is set.', 'Must set `name` or use render props when `dependencies` is set.',
); );
} else if (isValidElement(children)) { } else if (isValidElement(children)) {
devWarning( warning(
children.props.defaultValue === undefined, children.props.defaultValue === undefined,
'Form.Item', 'Form.Item',
'`defaultValue` will not work on controlled Field. You should use `initialValues` of Form instead.', '`defaultValue` will not work on controlled Field. You should use `initialValues` of Form instead.',
@ -449,7 +449,7 @@ function FormItem<Values = any>(props: FormItemProps<Values>): React.ReactElemen
} else if (isRenderProps && (shouldUpdate || dependencies) && !hasName) { } else if (isRenderProps && (shouldUpdate || dependencies) && !hasName) {
childNode = (children as RenderChildren)(context); childNode = (children as RenderChildren)(context);
} else { } else {
devWarning( warning(
!mergedName.length, !mergedName.length,
'Form.Item', 'Form.Item',
'`name` is only used for validate React element. If you are using Form.Item as layout display, please remove `name` instead.', '`name` is only used for validate React element. If you are using Form.Item as layout display, please remove `name` instead.',

View File

@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { List } from 'rc-field-form'; import { List } from 'rc-field-form';
import type { ValidatorRule, StoreValue } from 'rc-field-form/lib/interface'; import type { ValidatorRule, StoreValue } from 'rc-field-form/lib/interface';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import { FormItemPrefixContext } from './context'; import { FormItemPrefixContext } from './context';
@ -33,7 +33,7 @@ const FormList: React.FC<FormListProps> = ({
children, children,
...props ...props
}) => { }) => {
devWarning(!!props.name, 'Form.List', 'Miss `name` prop.'); warning(!!props.name, 'Form.List', 'Miss `name` prop.');
const { getPrefixCls } = React.useContext(ConfigContext); const { getPrefixCls } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('form', customizePrefixCls); const prefixCls = getPrefixCls('form', customizePrefixCls);

View File

@ -12877,7 +12877,7 @@ exports[`renders ./components/form/demo/time-related-controls.md extend context
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -16370,7 +16370,7 @@ exports[`renders ./components/form/demo/time-related-controls.md extend context
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -17808,7 +17808,7 @@ exports[`renders ./components/form/demo/time-related-controls.md extend context
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -22073,7 +22073,7 @@ exports[`renders ./components/form/demo/validate-static.md extend context correc
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>

View File

@ -4,7 +4,7 @@ import Item, { FormItemProps } from './FormItem';
import ErrorList, { ErrorListProps } from './ErrorList'; import ErrorList, { ErrorListProps } from './ErrorList';
import List, { FormListProps } from './FormList'; import List, { FormListProps } from './FormList';
import { FormProvider } from './context'; import { FormProvider } from './context';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import useFormInstance from './hooks/useFormInstance'; import useFormInstance from './hooks/useFormInstance';
type InternalFormType = typeof InternalForm; type InternalFormType = typeof InternalForm;
@ -32,7 +32,7 @@ Form.useFormInstance = useFormInstance;
Form.useWatch = useWatch; Form.useWatch = useWatch;
Form.Provider = FormProvider; Form.Provider = FormProvider;
Form.create = () => { Form.create = () => {
devWarning( warning(
false, false,
'Form', 'Form',
'antd v4 removed `Form.create`. Please remove or use `@ant-design/compatible` instead.', 'antd v4 removed `Form.create`. Please remove or use `@ant-design/compatible` instead.',

View File

@ -1,7 +1,7 @@
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
const Icon = () => { const Icon = () => {
devWarning(false, 'Icon', 'Empty Icon'); warning(false, 'Icon', 'Empty Icon');
return null; return null;
}; };

View File

@ -12,7 +12,7 @@ import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import { FormItemInputContext, NoFormStatus } from '../form/context'; import { FormItemInputContext, NoFormStatus } from '../form/context';
import { hasPrefixSuffix } from './utils'; import { hasPrefixSuffix } from './utils';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
export interface InputFocusOptions extends FocusOptions { export interface InputFocusOptions extends FocusOptions {
cursor?: 'start' | 'end' | 'all'; cursor?: 'start' | 'end' | 'all';
@ -158,7 +158,7 @@ const Input = forwardRef<InputRef, InputProps>((props, ref) => {
const prevHasPrefixSuffix = useRef<boolean>(inputHasPrefixSuffix); const prevHasPrefixSuffix = useRef<boolean>(inputHasPrefixSuffix);
useEffect(() => { useEffect(() => {
if (inputHasPrefixSuffix && !prevHasPrefixSuffix.current) { if (inputHasPrefixSuffix && !prevHasPrefixSuffix.current) {
devWarning( warning(
document.activeElement === inputRef.current?.input, document.activeElement === inputRef.current?.input,
'Input', 'Input',
`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`, `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

@ -2800,7 +2800,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>

View File

@ -63,7 +63,7 @@ export const Meta: FC<ListItemMetaProps> = ({
}; };
export interface ListItemTypeProps export interface ListItemTypeProps
extends ForwardRefExoticComponent<ListItemMetaProps & React.RefAttributes<HTMLElement>> { extends ForwardRefExoticComponent<ListItemProps & React.RefAttributes<HTMLElement>> {
Meta: typeof Meta; Meta: typeof Meta;
} }

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { render, mount } from 'enzyme'; import { render, mount } from 'enzyme';
import List from '..'; import List from '..';
import { noop } from '../../_util/warning';
describe('List.pagination', () => { describe('List.pagination', () => {
const data = [ const data = [
@ -65,7 +66,6 @@ describe('List.pagination', () => {
it('fires change event', () => { it('fires change event', () => {
const handlePaginationChange = jest.fn(); const handlePaginationChange = jest.fn();
const noop = () => {};
const wrapper = mount( const wrapper = mount(
createList({ createList({
pagination: { pagination: {

View File

@ -24451,7 +24451,7 @@ exports[`Locale Provider should display the text as by 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -34625,7 +34625,7 @@ exports[`Locale Provider should display the text as cs 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -39712,7 +39712,7 @@ exports[`Locale Provider should display the text as da 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -49886,7 +49886,7 @@ exports[`Locale Provider should display the text as el 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -54973,7 +54973,7 @@ exports[`Locale Provider should display the text as en 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -60060,7 +60060,7 @@ exports[`Locale Provider should display the text as en-gb 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -61497,7 +61497,7 @@ exports[`Locale Provider should display the text as en-gb 1`] = `
<div <div
class="ant-empty-description" class="ant-empty-description"
> >
No data No Data
</div> </div>
</div> </div>
</div> </div>
@ -61722,7 +61722,7 @@ exports[`Locale Provider should display the text as en-gb 1`] = `
<div <div
class="ant-empty-description" class="ant-empty-description"
> >
No data No Data
</div> </div>
</div> </div>
</div> </div>
@ -62794,7 +62794,7 @@ exports[`Locale Provider should display the text as en-gb 1`] = `
<div <div
class="ant-empty-description" class="ant-empty-description"
> >
No data No Data
</div> </div>
</div> </div>
</td> </td>
@ -70234,7 +70234,7 @@ exports[`Locale Provider should display the text as et 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -80408,7 +80408,7 @@ exports[`Locale Provider should display the text as fi 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -85495,7 +85495,7 @@ exports[`Locale Provider should display the text as fr 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -90582,7 +90582,7 @@ exports[`Locale Provider should display the text as fr 2`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -95669,7 +95669,7 @@ exports[`Locale Provider should display the text as fr 3`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -121104,7 +121104,7 @@ exports[`Locale Provider should display the text as hr 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -126191,7 +126191,7 @@ exports[`Locale Provider should display the text as hu 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -146539,7 +146539,7 @@ exports[`Locale Provider should display the text as it 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -156713,7 +156713,7 @@ exports[`Locale Provider should display the text as ka 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -197409,7 +197409,7 @@ exports[`Locale Provider should display the text as lv 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -212670,7 +212670,7 @@ exports[`Locale Provider should display the text as mn-mn 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -217757,7 +217757,7 @@ exports[`Locale Provider should display the text as ms-my 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -222844,7 +222844,7 @@ exports[`Locale Provider should display the text as nb 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -227931,7 +227931,7 @@ exports[`Locale Provider should display the text as ne-np 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -233018,7 +233018,7 @@ exports[`Locale Provider should display the text as nl 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -238105,7 +238105,7 @@ exports[`Locale Provider should display the text as nl-be 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -243192,7 +243192,7 @@ exports[`Locale Provider should display the text as pl 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -253366,7 +253366,7 @@ exports[`Locale Provider should display the text as pt-br 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -258453,7 +258453,7 @@ exports[`Locale Provider should display the text as ro 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -268627,7 +268627,7 @@ exports[`Locale Provider should display the text as sk 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -283888,7 +283888,7 @@ exports[`Locale Provider should display the text as sv 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -304236,7 +304236,7 @@ exports[`Locale Provider should display the text as uk 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -314410,7 +314410,7 @@ exports[`Locale Provider should display the text as vi 1`] = `
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>

View File

@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import memoizeOne from 'memoize-one'; import memoizeOne from 'memoize-one';
import type { ValidateMessages } from 'rc-field-form/lib/interface'; import type { ValidateMessages } from 'rc-field-form/lib/interface';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import type { ModalLocale } from '../modal/locale'; import type { ModalLocale } from '../modal/locale';
import { changeConfirmLocale } from '../modal/locale'; import { changeConfirmLocale } from '../modal/locale';
@ -62,7 +62,7 @@ export default class LocaleProvider extends React.Component<LocaleProviderProps,
super(props); super(props);
changeConfirmLocale(props.locale && props.locale.Modal); changeConfirmLocale(props.locale && props.locale.Modal);
devWarning( warning(
props._ANT_MARK__ === ANT_MARK, props._ANT_MARK__ === ANT_MARK,
'LocaleProvider', 'LocaleProvider',
'`LocaleProvider` is deprecated. Please use `locale` with `ConfigProvider` instead: http://u.ant.design/locale', '`LocaleProvider` is deprecated. Please use `locale` with `ConfigProvider` instead: http://u.ant.design/locale',

View File

@ -13,11 +13,16 @@ const localeValues: Locale = {
DatePicker, DatePicker,
TimePicker, TimePicker,
Calendar, Calendar,
global: {
placeholder: 'Please select',
},
Table: { Table: {
filterTitle: 'Filter menu', filterTitle: 'Filter menu',
filterConfirm: 'OK', filterConfirm: 'OK',
filterReset: 'Reset', filterReset: 'Reset',
filterEmptyText: 'No filters', filterEmptyText: 'No filters',
filterCheckall: 'Select all items',
filterSearchPlaceholder: 'Search in filters',
emptyText: 'No data', emptyText: 'No data',
selectAll: 'Select current page', selectAll: 'Select current page',
selectInvert: 'Invert current page', selectInvert: 'Invert current page',
@ -40,9 +45,16 @@ const localeValues: Locale = {
cancelText: 'Cancel', cancelText: 'Cancel',
}, },
Transfer: { Transfer: {
titles: ['', ''],
searchPlaceholder: 'Search here', searchPlaceholder: 'Search here',
itemUnit: 'item', itemUnit: 'item',
itemsUnit: 'items', itemsUnit: 'items',
remove: 'Remove',
selectCurrent: 'Select current page',
removeCurrent: 'Remove current page',
selectAll: 'Select all data',
removeAll: 'Remove all data',
selectInvert: 'Invert current page',
}, },
Upload: { Upload: {
uploading: 'Uploading...', uploading: 'Uploading...',
@ -52,9 +64,22 @@ const localeValues: Locale = {
downloadFile: 'Download file', downloadFile: 'Download file',
}, },
Empty: { Empty: {
description: 'No data', description: 'No Data',
},
Icon: {
icon: 'icon',
},
Text: {
edit: 'Edit',
copy: 'Copy',
copied: 'Copied',
expand: 'Expand',
},
PageHeader: {
back: 'Back',
}, },
Form: { Form: {
optional: '(optional)',
defaultValidateMessages: { defaultValidateMessages: {
default: 'Field validation error for ${label}', default: 'Field validation error for ${label}',
required: 'Please enter ${label}', required: 'Please enter ${label}',
@ -103,6 +128,9 @@ const localeValues: Locale = {
}, },
}, },
}, },
Image: {
preview: 'Preview',
},
}; };
export default localeValues; export default localeValues;

View File

@ -1,21 +1,39 @@
/* eslint-disable no-template-curly-in-string */
import Pagination from 'rc-pagination/lib/locale/uk_UA'; import Pagination from 'rc-pagination/lib/locale/uk_UA';
import DatePicker from '../date-picker/locale/uk_UA'; import DatePicker from '../date-picker/locale/uk_UA';
import TimePicker from '../time-picker/locale/uk_UA'; import TimePicker from '../time-picker/locale/uk_UA';
import Calendar from '../calendar/locale/uk_UA'; import Calendar from '../calendar/locale/uk_UA';
import type { Locale } from '../locale-provider'; import type { Locale } from '../locale-provider';
const typeTemplate = '${label} не є типом ${type}';
const localeValues: Locale = { const localeValues: Locale = {
locale: 'uk', locale: 'uk',
Pagination, Pagination,
DatePicker, DatePicker,
TimePicker, TimePicker,
Calendar, Calendar,
global: {
placeholder: 'Будь ласка, оберіть',
},
Table: { Table: {
filterTitle: 'Фільтрувати', filterTitle: 'Фільтрувати',
filterConfirm: 'OK', filterConfirm: 'OK',
filterReset: 'Скинути', filterReset: 'Скинути',
selectAll: 'Обрати всі', filterEmptyText: 'Фільтри відсутні',
filterCheckall: 'Обрати всі',
filterSearchPlaceholder: 'Пошук у фільтрах',
emptyText: 'Даних немає',
selectAll: 'Обрати всі на сторінці',
selectInvert: 'Інвертувати вибір', selectInvert: 'Інвертувати вибір',
selectNone: 'Очистити вибір',
selectionAll: 'Обрати всі',
sortTitle: 'Сортувати',
expand: 'Розгорнути рядок',
collapse: 'Згорнути рядок',
triggerDesc: 'Сортувати за спаданням',
triggerAsc: 'Сортувати за зростанням',
cancelSort: 'Відмінити сортування',
}, },
Modal: { Modal: {
okText: 'Гаразд', okText: 'Гаразд',
@ -27,9 +45,16 @@ const localeValues: Locale = {
cancelText: 'Скасувати', cancelText: 'Скасувати',
}, },
Transfer: { Transfer: {
titles: ['', ''],
searchPlaceholder: 'Введіть текст для пошуку', searchPlaceholder: 'Введіть текст для пошуку',
itemUnit: 'елем.', itemUnit: 'елем.',
itemsUnit: 'елем.', itemsUnit: 'елем.',
remove: 'Видалити',
selectCurrent: 'Вибрати поточну сторінку',
removeCurrent: 'Скасувати вибір на сторінці',
selectAll: 'Вибрати всі дані',
removeAll: 'Скасувати вибір',
selectInvert: 'Інвертувати поточну сторінку',
}, },
Upload: { Upload: {
uploading: 'Завантаження ...', uploading: 'Завантаження ...',
@ -41,6 +66,71 @@ const localeValues: Locale = {
Empty: { Empty: {
description: 'Даних немає', description: 'Даних немає',
}, },
Icon: {
icon: 'іконка',
},
Text: {
edit: 'Редагувати',
copy: 'Скопіювати',
copied: 'Скопійовано',
expand: 'Розширити',
},
PageHeader: {
back: 'Назад',
},
Form: {
optional: '(опціонально)',
defaultValidateMessages: {
default: 'Помилка валідації для поля ${label}',
required: 'Будь ласка, заповніть ${label}',
enum: 'Лише одне зі значень [${enum}] доступне для ${label}',
whitespace: 'Значення у полі ${label} не може бути пробілом',
date: {
format: 'Не валідний формат дати у ${label}',
parse: 'Значення ${label} не може бути приведене до дати',
invalid: 'Не валідна дата у ${label}',
},
types: {
string: typeTemplate,
method: typeTemplate,
array: typeTemplate,
object: typeTemplate,
number: typeTemplate,
date: typeTemplate,
boolean: typeTemplate,
integer: typeTemplate,
float: typeTemplate,
regexp: typeTemplate,
email: typeTemplate,
url: typeTemplate,
hex: typeTemplate,
},
string: {
len: '${label} має містити ${len} символів',
min: '${label} має містити не менш, ніж ${min} символів',
max: '${label} має містити не більш, ніж ${max} символів',
range: '${label} має містити ${min}-${max} символів',
},
number: {
len: '${label} має дорівнювати ${len}',
min: '${label} має бути не менш, ніж ${min}',
max: '${label} має бути не більш, ніж ${max}',
range: '${label} має бути в межах ${min}-${max}',
},
array: {
len: '${label} має містити ${len} елементи',
min: '${label} має містити не менш, ніж ${min} елементи',
max: '${label} має містити не більш, ніж ${max} елементи',
range: 'Кількість елементів в ${label} має бути в межах ${min}-${max}',
},
pattern: {
mismatch: '${label} не відповідає шаблону ${pattern}',
},
},
},
Image: {
preview: 'Попередній перегляд',
},
}; };
export default localeValues; export default localeValues;

View File

@ -15,13 +15,12 @@ import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest'; import rtlTest from '../../../tests/shared/rtlTest';
import { render, fireEvent } from '../../../tests/utils'; import { render, fireEvent } from '../../../tests/utils';
import collapseMotion from '../../_util/motion'; import collapseMotion from '../../_util/motion';
import { noop } from '../../_util/warning';
globalThis.IS_REACT_ACT_ENVIRONMENT = true; globalThis.IS_REACT_ACT_ENVIRONMENT = true;
const { SubMenu } = Menu; const { SubMenu } = Menu;
const noop = () => {};
describe('Menu', () => { describe('Menu', () => {
function triggerAllTimer() { function triggerAllTimer() {
for (let i = 0; i < 10; i += 1) { for (let i = 0; i < 10; i += 1) {

View File

@ -29,11 +29,12 @@ ReactDOM.render(<Alert message="After version 4.20.0, we provide a simpler usage
```jsx ```jsx
// works when >=4.20.0, recommended ✅ // works when >=4.20.0, recommended ✅
const items = [ const items = [
{ label: 'item 1' }, { label: 'item 1', key: 'item-1' }, // remember to pass the key prop
{ label: 'item 2' }, { label: 'item 2', key: 'item-2' }, // which is required
{ {
label: 'sub menu', label: 'sub menu',
children: [{ label: 'item 3' }], key: 'submenu'
children: [{ label: 'item 3', key: 'submenu-item-1' }],
}, },
]; ];
return <Menu items={items} />; return <Menu items={items} />;
@ -138,7 +139,7 @@ Define `type` as `group` to make as group:
const groupItem = { const groupItem = {
type: 'group', // Must have type: 'group', // Must have
label: 'My Group', label: 'My Group',
chidlren: [], children: [],
}; };
``` ```

View File

@ -8,7 +8,7 @@ import { forwardRef } from 'react';
import SubMenu, { SubMenuProps } from './SubMenu'; import SubMenu, { SubMenuProps } from './SubMenu';
import Item, { MenuItemProps } from './MenuItem'; import Item, { MenuItemProps } from './MenuItem';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import type { SiderContextProps } from '../layout/Sider'; import type { SiderContextProps } from '../layout/Sider';
import { SiderContext } from '../layout/Sider'; import { SiderContext } from '../layout/Sider';
import collapseMotion from '../_util/motion'; import collapseMotion from '../_util/motion';
@ -67,19 +67,19 @@ const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {
const mergedChildren = useItems(items) || children; const mergedChildren = useItems(items) || children;
// ======================== Warning ========================== // ======================== Warning ==========================
devWarning( warning(
!('inlineCollapsed' in props && props.mode !== 'inline'), !('inlineCollapsed' in props && props.mode !== 'inline'),
'Menu', 'Menu',
'`inlineCollapsed` should only be used when `mode` is inline.', '`inlineCollapsed` should only be used when `mode` is inline.',
); );
devWarning( warning(
!(props.siderCollapsed !== undefined && 'inlineCollapsed' in props), !(props.siderCollapsed !== undefined && 'inlineCollapsed' in props),
'Menu', 'Menu',
'`inlineCollapsed` not control Menu under Sider. Should set `collapsed` on Sider instead.', '`inlineCollapsed` not control Menu under Sider. Should set `collapsed` on Sider instead.',
); );
devWarning( warning(
!!items && !children, !!items && !children,
'Menu', 'Menu',
'`children` will be removed in next major version. Please use `items` instead.', '`children` will be removed in next major version. Please use `items` instead.',

View File

@ -30,11 +30,12 @@ ReactDOM.render(<Alert message="在 4.20.0 版本后,我们提供了 <Menu ite
```jsx ```jsx
// >=4.20.0 可用,推荐的写法 ✅ // >=4.20.0 可用,推荐的写法 ✅
const items = [ const items = [
{ label: '菜单项一' }, { label: '菜单项一', key: 'item-1' }, // 菜单项务必填写 key
{ label: '菜单项二' }, { label: '菜单项二', key: 'item-2' },
{ {
label: '子菜单', label: '子菜单',
children: [{ label: '子菜单项' }], key: 'submenu',
children: [{ label: '子菜单项', key: 'submenu-item-1' }],
}, },
]; ];
return <Menu items={items} />; return <Menu items={items} />;
@ -138,7 +139,7 @@ return <Menu items={items} />;
const groupItem = { const groupItem = {
type: 'group', // Must have type: 'group', // Must have
label: 'My Group', label: 'My Group',
chidlren: [], children: [],
}; };
``` ```

View File

@ -3,7 +3,7 @@ import classNames from 'classnames';
import type { ModalFuncProps } from './Modal'; import type { ModalFuncProps } from './Modal';
import Dialog from './Modal'; import Dialog from './Modal';
import ActionButton from '../_util/ActionButton'; import ActionButton from '../_util/ActionButton';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import ConfigProvider from '../config-provider'; import ConfigProvider from '../config-provider';
import { getTransitionName } from '../_util/motion'; import { getTransitionName } from '../_util/motion';
@ -44,7 +44,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
focusTriggerAfterClose, focusTriggerAfterClose,
} = props; } = props;
devWarning( warning(
!(typeof icon === 'string' && icon.length > 2), !(typeof icon === 'string' && icon.length > 2),
'Modal', 'Modal',
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`, `\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,

View File

@ -8,7 +8,7 @@ import { getConfirmLocale } from './locale';
import type { ModalFuncProps } from './Modal'; import type { ModalFuncProps } from './Modal';
import ConfirmDialog from './ConfirmDialog'; import ConfirmDialog from './ConfirmDialog';
import { globalConfig } from '../config-provider'; import { globalConfig } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import destroyFns from './destroyFns'; import destroyFns from './destroyFns';
let defaultRootPrefixCls = ''; let defaultRootPrefixCls = '';
@ -159,10 +159,6 @@ export function withConfirm(props: ModalFuncProps): ModalFuncProps {
} }
export function modalGlobalConfig({ rootPrefixCls }: { rootPrefixCls: string }) { export function modalGlobalConfig({ rootPrefixCls }: { rootPrefixCls: string }) {
devWarning( warning(false, 'Modal', 'Modal.config is deprecated. Please use ConfigProvider.config instead.');
false,
'Modal',
'Modal.config is deprecated. Please use ConfigProvider.config instead.',
);
defaultRootPrefixCls = rootPrefixCls; defaultRootPrefixCls = rootPrefixCls;
} }

View File

@ -7,7 +7,7 @@ import CheckCircleFilled from '@ant-design/icons/CheckCircleFilled';
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled'; import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import { tuple } from '../_util/type'; import { tuple } from '../_util/type';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import Line from './Line'; import Line from './Line';
import Circle from './Circle'; import Circle from './Circle';
import Steps from './Steps'; import Steps from './Steps';
@ -101,7 +101,7 @@ const Progress: React.FC<ProgressProps> = (props: ProgressProps) => {
const progressStatus = getProgressStatus(); const progressStatus = getProgressStatus();
const progressInfo = renderProcessInfo(prefixCls, progressStatus); const progressInfo = renderProcessInfo(prefixCls, progressStatus);
devWarning( warning(
!('successPercent' in props), !('successPercent' in props),
'Progress', 'Progress',
'`successPercent` is deprecated. Please use `success.percent` instead.', '`successPercent` is deprecated. Please use `success.percent` instead.',

View File

@ -1,4 +1,4 @@
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
export function validProgress(progress: number | undefined) { export function validProgress(progress: number | undefined) {
if (!progress || progress < 0) { if (!progress || progress < 0) {
@ -23,7 +23,7 @@ export function getSuccessPercent({
let percent = successPercent; let percent = successPercent;
/** @deprecated Use `percent` instead */ /** @deprecated Use `percent` instead */
if (success && 'progress' in success) { if (success && 'progress' in success) {
devWarning( warning(
false, false,
'Progress', 'Progress',
'`success.progress` is deprecated. Please use `success.percent` instead.', '`success.progress` is deprecated. Please use `success.percent` instead.',

View File

@ -8,7 +8,7 @@ import type { RadioProps, RadioChangeEvent } from './interface';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import RadioGroupContext, { RadioOptionTypeContext } from './context'; import RadioGroupContext, { RadioOptionTypeContext } from './context';
import DisabledContext from '../config-provider/DisabledContext'; import DisabledContext from '../config-provider/DisabledContext';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
const InternalRadio: React.ForwardRefRenderFunction<HTMLElement, RadioProps> = (props, ref) => { const InternalRadio: React.ForwardRefRenderFunction<HTMLElement, RadioProps> = (props, ref) => {
const groupContext = React.useContext(RadioGroupContext); const groupContext = React.useContext(RadioGroupContext);
@ -19,9 +19,7 @@ const InternalRadio: React.ForwardRefRenderFunction<HTMLElement, RadioProps> = (
const mergedRef = composeRef(ref, innerRef); const mergedRef = composeRef(ref, innerRef);
const { isFormItemInput } = useContext(FormItemInputContext); const { isFormItemInput } = useContext(FormItemInputContext);
React.useEffect(() => { warning(!('optionType' in props), 'Radio', '`optionType` is only support in Radio.Group.');
devWarning(!('optionType' in props), 'Radio', '`optionType` is only support in Radio.Group.');
}, []);
const onChange = (e: RadioChangeEvent) => { const onChange = (e: RadioChangeEvent) => {
props.onChange?.(e); props.onChange?.(e);

View File

@ -6,7 +6,7 @@ import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled';
import WarningFilled from '@ant-design/icons/WarningFilled'; import WarningFilled from '@ant-design/icons/WarningFilled';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import noFound from './noFound'; import noFound from './noFound';
import serverError from './serverError'; import serverError from './serverError';
@ -52,7 +52,7 @@ const ExceptionStatus = Object.keys(ExceptionMap);
const renderIcon = (prefixCls: string, { status, icon }: ResultProps) => { const renderIcon = (prefixCls: string, { status, icon }: ResultProps) => {
const className = classNames(`${prefixCls}-icon`); const className = classNames(`${prefixCls}-icon`);
devWarning( warning(
!(typeof icon === 'string' && icon.length > 2), !(typeof icon === 'string' && icon.length > 2),
'Result', 'Result',
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`, `\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,

View File

@ -2,7 +2,7 @@ import React from 'react';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import Switch from '..'; import Switch from '..';
import focusTest from '../../../tests/shared/focusTest'; import focusTest from '../../../tests/shared/focusTest';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest'; import rtlTest from '../../../tests/shared/rtlTest';
import { sleep } from '../../../tests/utils'; import { sleep } from '../../../tests/utils';

View File

@ -7,7 +7,7 @@ import Wave from '../_util/wave';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import SizeContext from '../config-provider/SizeContext'; import SizeContext from '../config-provider/SizeContext';
import DisabledContext from '../config-provider/DisabledContext'; import DisabledContext from '../config-provider/DisabledContext';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
export type SwitchSize = 'small' | 'default'; export type SwitchSize = 'small' | 'default';
export type SwitchChangeEventHandler = (checked: boolean, event: MouseEvent) => void; export type SwitchChangeEventHandler = (checked: boolean, event: MouseEvent) => void;
@ -49,7 +49,7 @@ const Switch = React.forwardRef<unknown, SwitchProps>(
}, },
ref, ref,
) => { ) => {
devWarning( warning(
'checked' in props || !('value' in props), 'checked' in props || !('value' in props),
'Switch', 'Switch',
'`value` is not a valid prop, do you mean `checked`?', '`value` is not a valid prop, do you mean `checked`?',

View File

@ -46,7 +46,7 @@ import type { SizeType } from '../config-provider/SizeContext';
import SizeContext from '../config-provider/SizeContext'; import SizeContext from '../config-provider/SizeContext';
import Column from './Column'; import Column from './Column';
import ColumnGroup from './ColumnGroup'; import ColumnGroup from './ColumnGroup';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import useBreakpoint from '../grid/hooks/useBreakpoint'; import useBreakpoint from '../grid/hooks/useBreakpoint';
export { ColumnsType, TablePaginationConfig }; export { ColumnsType, TablePaginationConfig };
@ -137,7 +137,7 @@ function InternalTable<RecordType extends object = any>(
showSorterTooltip = true, showSorterTooltip = true,
} = props; } = props;
devWarning( warning(
!(typeof rowKey === 'function' && rowKey.length > 1), !(typeof rowKey === 'function' && rowKey.length > 1),
'Table', 'Table',
'`index` parameter of `rowKey` function is deprecated. There is no guarantee that it will work as expected.', '`index` parameter of `rowKey` function is deprecated. There is no guarantee that it will work as expected.',
@ -355,12 +355,12 @@ function InternalTable<RecordType extends object = any>(
} }
const { current = 1, total, pageSize = DEFAULT_PAGE_SIZE } = mergedPagination; const { current = 1, total, pageSize = DEFAULT_PAGE_SIZE } = mergedPagination;
devWarning(current > 0, 'Table', '`current` should be positive number.'); warning(current > 0, 'Table', '`current` should be positive number.');
// Dynamic table data // Dynamic table data
if (mergedData.length < total!) { if (mergedData.length < total!) {
if (mergedData.length > pageSize) { if (mergedData.length > pageSize) {
devWarning( warning(
false, false,
'Table', 'Table',
'`dataSource` length is less than `pagination.total` but large than `pagination.pageSize`. Please make sure your config correct data with async mode.', '`dataSource` length is less than `pagination.total` but large than `pagination.pageSize`. Please make sure your config correct data with async mode.',

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import Table from '..'; import Table from '..';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
describe('Table.order', () => { describe('Table.order', () => {
window.requestAnimationFrame = callback => window.setTimeout(callback, 16); window.requestAnimationFrame = callback => window.setTimeout(callback, 16);

View File

@ -5,7 +5,7 @@ import React from 'react';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import Table from '..'; import Table from '..';
import scrollTo from '../../_util/scrollTo'; import scrollTo from '../../_util/scrollTo';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
describe('Table.pagination', () => { describe('Table.pagination', () => {
const columns = [ const columns = [

View File

@ -3,7 +3,7 @@ import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import Table from '..'; import Table from '..';
import Checkbox from '../../checkbox'; import Checkbox from '../../checkbox';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
import ConfigProvider from '../../config-provider'; import ConfigProvider from '../../config-provider';
import { render } from '../../../tests/utils'; import { render } from '../../../tests/utils';

View File

@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import devWarning from '../../../_util/devWarning'; import warning from '../../../_util/warning';
import type { import type {
TransformColumns, TransformColumns,
ColumnsType, ColumnsType,
@ -226,7 +226,7 @@ function useFilter<RecordType>({
return filterStates; return filterStates;
} }
devWarning( warning(
filteredKeysIsAllControlled, filteredKeysIsAllControlled,
'Table', 'Table',
'Columns should all contain `filteredValue` or not contain `filteredValue`.', 'Columns should all contain `filteredValue` or not contain `filteredValue`.',

View File

@ -13,7 +13,7 @@ import Checkbox from '../../checkbox';
import Dropdown from '../../dropdown'; import Dropdown from '../../dropdown';
import Menu from '../../menu'; import Menu from '../../menu';
import Radio from '../../radio'; import Radio from '../../radio';
import devWarning from '../../_util/devWarning'; import warning from '../../_util/warning';
import type { import type {
TableRowSelection, TableRowSelection,
Key, Key,
@ -171,16 +171,11 @@ export default function useSelection<RecordType>(
const checkboxProps = (getCheckboxProps ? getCheckboxProps(record) : null) || {}; const checkboxProps = (getCheckboxProps ? getCheckboxProps(record) : null) || {};
map.set(key, checkboxProps); map.set(key, checkboxProps);
if ( warning(
process.env.NODE_ENV !== 'production' && !('checked' in checkboxProps || 'defaultChecked' in checkboxProps),
('checked' in checkboxProps || 'defaultChecked' in checkboxProps) 'Table',
) { 'Do not set `checked` or `defaultChecked` in `getCheckboxProps`. Please use `selectedRowKeys` instead.',
devWarning( );
false,
'Table',
'Do not set `checked` or `defaultChecked` in `getCheckboxProps`. Please use `selectedRowKeys` instead.',
);
}
}); });
return map; return map;
}, [flattedData, getRowKey, getCheckboxProps]); }, [flattedData, getRowKey, getCheckboxProps]);
@ -313,7 +308,7 @@ export default function useSelection<RecordType>(
const keys = Array.from(keySet); const keys = Array.from(keySet);
if (onSelectInvert) { if (onSelectInvert) {
devWarning( warning(
false, false,
'Table', 'Table',
'`onSelectInvert` will be removed in future. Please use `onChange` instead.', '`onSelectInvert` will be removed in future. Please use `onChange` instead.',
@ -349,13 +344,11 @@ export default function useSelection<RecordType>(
(columns: ColumnsType<RecordType>): ColumnsType<RecordType> => { (columns: ColumnsType<RecordType>): ColumnsType<RecordType> => {
// >>>>>>>>>>> Skip if not exists `rowSelection` // >>>>>>>>>>> Skip if not exists `rowSelection`
if (!rowSelection) { if (!rowSelection) {
if (process.env.NODE_ENV !== 'production') { warning(
devWarning( !columns.includes(SELECTION_COLUMN),
!columns.includes(SELECTION_COLUMN), 'Table',
'Table', '`rowSelection` is not config but `SELECTION_COLUMN` exists in the `columns`.',
'`rowSelection` is not config but `SELECTION_COLUMN` exists in the `columns`.', );
);
}
return columns.filter(col => col !== SELECTION_COLUMN); return columns.filter(col => col !== SELECTION_COLUMN);
} }
@ -504,7 +497,7 @@ export default function useSelection<RecordType>(
let mergedIndeterminate: boolean; let mergedIndeterminate: boolean;
if (expandType === 'nest') { if (expandType === 'nest') {
mergedIndeterminate = indeterminate; mergedIndeterminate = indeterminate;
devWarning( warning(
typeof checkboxProps?.indeterminate !== 'boolean', typeof checkboxProps?.indeterminate !== 'boolean',
'Table', 'Table',
'set `indeterminate` using `rowSelection.getCheckboxProps` is not allowed with tree structured dataSource.', 'set `indeterminate` using `rowSelection.getCheckboxProps` is not allowed with tree structured dataSource.',
@ -646,12 +639,13 @@ export default function useSelection<RecordType>(
// Deduplicate selection column // Deduplicate selection column
const selectionColumnIndex = cloneColumns.indexOf(SELECTION_COLUMN); const selectionColumnIndex = cloneColumns.indexOf(SELECTION_COLUMN);
if (
process.env.NODE_ENV !== 'production' && warning(
cloneColumns.filter(col => col === SELECTION_COLUMN).length > 1 cloneColumns.filter(col => col === SELECTION_COLUMN).length <= 1,
) { 'Table',
devWarning(false, 'Table', 'Multiple `SELECTION_COLUMN` exist in `columns`.'); 'Multiple `SELECTION_COLUMN` exist in `columns`.',
} );
cloneColumns = cloneColumns.filter( cloneColumns = cloneColumns.filter(
(column, index) => column !== SELECTION_COLUMN || index === selectionColumnIndex, (column, index) => column !== SELECTION_COLUMN || index === selectionColumnIndex,
); );

View File

@ -128,7 +128,6 @@ One of the Table `columns` prop for describing the table's columns, Column has t
| defaultFilteredValue | Default filtered values | string\[] | - | | | defaultFilteredValue | Default filtered values | string\[] | - | |
| filterResetToDefaultFilteredValue | click the reset button, whether to restore the default filter | boolean | false | | | filterResetToDefaultFilteredValue | click the reset button, whether to restore the default filter | boolean | false | |
| defaultSortOrder | Default order of sorted values | `ascend` \| `descend` | - | | | defaultSortOrder | Default order of sorted values | `ascend` \| `descend` | - | |
| editable | Whether column can be edited | boolean | false | |
| ellipsis | The ellipsis cell content, not working with sorter and filters for now.<br />tableLayout would be `fixed` when `ellipsis` is `true` or `{ showTitle?: boolean }` | boolean \| {showTitle?: boolean } | false | showTitle: 4.3.0 | | ellipsis | The ellipsis cell content, not working with sorter and filters for now.<br />tableLayout would be `fixed` when `ellipsis` is `true` or `{ showTitle?: boolean }` | boolean \| {showTitle?: boolean } | false | showTitle: 4.3.0 |
| filterDropdown | Customized filter overlay | ReactNode \| (props: [FilterDropdownProps](https://github.com/ant-design/ant-design/blob/ecc54dda839619e921c0ace530408871f0281c2a/components/table/interface.tsx#L79)) => ReactNode | - | | | filterDropdown | Customized filter overlay | ReactNode \| (props: [FilterDropdownProps](https://github.com/ant-design/ant-design/blob/ecc54dda839619e921c0ace530408871f0281c2a/components/table/interface.tsx#L79)) => ReactNode | - | |
| filterDropdownVisible | Whether `filterDropdown` is visible | boolean | - | | | filterDropdownVisible | Whether `filterDropdown` is visible | boolean | - | |
@ -317,3 +316,7 @@ Table can not tell what state used in `columns.render`, so it always need fully
### How to handle fixed column display over the mask layout? ### How to handle fixed column display over the mask layout?
Fixed column use `z-index` to make it over other columns. You will find sometime fixed columns also over your mask layout. You can set `z-index` on your mask layout to resolve. Fixed column use `z-index` to make it over other columns. You will find sometime fixed columns also over your mask layout. You can set `z-index` on your mask layout to resolve.
### How to custom render Table CheckboxFor example, adding Tooltip?
Since `4.1.0`, You can use [`rowSelection.renderCell`](https://ant.design/components/table/#rowSelection) to custom render Table Checkbox. If you want to add Tooltip, please refer to this [demo](https://codesandbox.io/s/table-row-tooltip-v79j2v).

View File

@ -63,7 +63,6 @@ const columns = [
## API ## API
### Table ### Table
| 参数 | 说明 | 类型 | 默认值 | 版本 | | 参数 | 说明 | 类型 | 默认值 | 版本 |
@ -130,7 +129,6 @@ const columns = [
| defaultFilteredValue | 默认筛选值 | string\[] | - | | | defaultFilteredValue | 默认筛选值 | string\[] | - | |
| filterResetToDefaultFilteredValue | 点击重置按钮的时候,是否恢复默认筛选值 | boolean | false | | | filterResetToDefaultFilteredValue | 点击重置按钮的时候,是否恢复默认筛选值 | boolean | false | |
| defaultSortOrder | 默认排序顺序 | `ascend` \| `descend` | - | | | defaultSortOrder | 默认排序顺序 | `ascend` \| `descend` | - | |
| editable | 是否可编辑 | boolean | false | |
| ellipsis | 超过宽度将自动省略,暂不支持和排序筛选一起使用。<br />设置为 `true``{ showTitle?: boolean }` 时,表格布局将变成 `tableLayout="fixed"`。 | boolean \| { showTitle?: boolean } | false | showTitle: 4.3.0 | | ellipsis | 超过宽度将自动省略,暂不支持和排序筛选一起使用。<br />设置为 `true``{ showTitle?: boolean }` 时,表格布局将变成 `tableLayout="fixed"`。 | boolean \| { showTitle?: boolean } | false | showTitle: 4.3.0 |
| filterDropdown | 可以自定义筛选菜单,此函数只负责渲染图层,需要自行编写各种交互 | ReactNode \| (props: [FilterDropdownProps](https://github.com/ant-design/ant-design/blob/ecc54dda839619e921c0ace530408871f0281c2a/components/table/interface.tsx#L79)) => ReactNode | - | | | filterDropdown | 可以自定义筛选菜单,此函数只负责渲染图层,需要自行编写各种交互 | ReactNode \| (props: [FilterDropdownProps](https://github.com/ant-design/ant-design/blob/ecc54dda839619e921c0ace530408871f0281c2a/components/table/interface.tsx#L79)) => ReactNode | - | |
| filterDropdownVisible | 用于控制自定义筛选菜单是否可见 | boolean | - | | | filterDropdownVisible | 用于控制自定义筛选菜单是否可见 | boolean | - | |
@ -318,3 +316,7 @@ Table 移除了在 v3 中废弃的 `onRowClick`、`onRowDoubleClick`、`onRowMou
### 固定列穿透到最上层该怎么办? ### 固定列穿透到最上层该怎么办?
固定列通过 `z-index` 属性将其悬浮于非固定列之上,这使得有时候你会发现在 Table 上放置遮罩层时固定列会被透过的情况。为遮罩层设置更高的 `z-index` 覆盖住固定列即可。 固定列通过 `z-index` 属性将其悬浮于非固定列之上,这使得有时候你会发现在 Table 上放置遮罩层时固定列会被透过的情况。为遮罩层设置更高的 `z-index` 覆盖住固定列即可。
### 如何自定义渲染可选列的勾选框(比如增加 Tooltip
`4.1.0` 起,可以通过 [rowSelection](https://ant.design/components/table-cn/#rowSelection) 的 `renderCell` 属性控制,可以参考此处 [Demo](https://codesandbox.io/s/table-row-tooltip-v79j2v) 实现展示 Tooltip 需求或其他自定义的需求。

View File

@ -7,7 +7,7 @@ import EllipsisOutlined from '@ant-design/icons/EllipsisOutlined';
import PlusOutlined from '@ant-design/icons/PlusOutlined'; import PlusOutlined from '@ant-design/icons/PlusOutlined';
import CloseOutlined from '@ant-design/icons/CloseOutlined'; import CloseOutlined from '@ant-design/icons/CloseOutlined';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import type { SizeType } from '../config-provider/SizeContext'; import type { SizeType } from '../config-provider/SizeContext';
import SizeContext from '../config-provider/SizeContext'; import SizeContext from '../config-provider/SizeContext';
@ -53,7 +53,7 @@ function Tabs({
} }
const rootPrefixCls = getPrefixCls(); const rootPrefixCls = getPrefixCls();
devWarning( warning(
!('onPrevClick' in props) && !('onNextClick' in props), !('onPrevClick' in props) && !('onNextClick' in props),
'Tabs', 'Tabs',
'`onPrevClick` and `onNextClick` has been removed. Please use `onTabScroll` instead.', '`onPrevClick` and `onNextClick` has been removed. Please use `onTabScroll` instead.',

View File

@ -1314,7 +1314,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -2637,7 +2637,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -3414,7 +3414,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -4838,7 +4838,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -6249,7 +6249,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -7661,7 +7661,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -9115,7 +9115,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -10526,7 +10526,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -11938,7 +11938,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -12828,7 +12828,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -13250,7 +13250,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -14709,7 +14709,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -16144,7 +16144,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -17574,7 +17574,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -19004,7 +19004,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -20422,7 +20422,7 @@ exports[`renders ./components/time-picker/demo/status.md extend context correctl
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -21834,7 +21834,7 @@ exports[`renders ./components/time-picker/demo/status.md extend context correctl
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -23293,7 +23293,7 @@ exports[`renders ./components/time-picker/demo/status.md extend context correctl
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -24751,7 +24751,7 @@ exports[`renders ./components/time-picker/demo/status.md extend context correctl
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -26160,7 +26160,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>
@ -27572,7 +27572,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>

View File

@ -1467,7 +1467,7 @@ Array [
type="button" type="button"
> >
<span> <span>
Ok OK
</span> </span>
</button> </button>
</li> </li>

View File

@ -4,7 +4,7 @@ import moment from 'moment';
import TimePicker from '..'; import TimePicker from '..';
import focusTest from '../../../tests/shared/focusTest'; import focusTest from '../../../tests/shared/focusTest';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
import rtlTest from '../../../tests/shared/rtlTest'; import rtlTest from '../../../tests/shared/rtlTest';
describe('TimePicker', () => { describe('TimePicker', () => {

View File

@ -2,7 +2,7 @@ import type { Moment } from 'moment';
import * as React from 'react'; import * as React from 'react';
import DatePicker from '../date-picker'; import DatePicker from '../date-picker';
import type { PickerTimeProps, RangePickerTimeProps } from '../date-picker/generatePicker'; import type { PickerTimeProps, RangePickerTimeProps } from '../date-picker/generatePicker';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import type { InputStatus } from '../_util/statusUtils'; import type { InputStatus } from '../_util/statusUtils';
const { TimePicker: InternalTimePicker, RangePicker: InternalRangePicker } = DatePicker; const { TimePicker: InternalTimePicker, RangePicker: InternalRangePicker } = DatePicker;
@ -39,7 +39,7 @@ const TimePicker = React.forwardRef<any, TimePickerProps>(
return renderExtraFooter; return renderExtraFooter;
} }
if (addon) { if (addon) {
devWarning( warning(
false, false,
'TimePicker', 'TimePicker',
'`addon` is deprecated. Please use `renderExtraFooter` instead.', '`addon` is deprecated. Please use `renderExtraFooter` instead.',

View File

@ -10,7 +10,7 @@ import type { ConfigConsumerProps, RenderEmptyHandler } from '../config-provider
import { ConfigConsumer } from '../config-provider'; import { ConfigConsumer } from '../config-provider';
import type { TransferListBodyProps } from './ListBody'; import type { TransferListBodyProps } from './ListBody';
import type { PaginationType } from './interface'; import type { PaginationType } from './interface';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import { FormItemInputContext } from '../form/context'; import { FormItemInputContext } from '../form/context';
import type { InputStatus } from '../_util/statusUtils'; import type { InputStatus } from '../_util/statusUtils';
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils'; import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
@ -136,7 +136,7 @@ class Transfer<RecordType extends TransferItem = TransferItem> extends React.Com
}; };
} }
devWarning( warning(
!pagination || !children, !pagination || !children,
'Transfer', 'Transfer',
'`pagination` not support customize render list.', '`pagination` not support customize render list.',

View File

@ -7,7 +7,7 @@ import type { BaseOptionType, DefaultOptionType } from 'rc-tree-select/lib/TreeS
import type { BaseSelectRef } from 'rc-select'; import type { BaseSelectRef } from 'rc-select';
import { useContext } from 'react'; import { useContext } from 'react';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import type { AntTreeNodeProps, TreeProps } from '../tree'; import type { AntTreeNodeProps, TreeProps } from '../tree';
import type { SwitcherIcon } from '../tree/Tree'; import type { SwitcherIcon } from '../tree/Tree';
import getIcons from '../select/utils/iconUtil'; import getIcons from '../select/utils/iconUtil';
@ -90,7 +90,7 @@ const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionTyp
} = React.useContext(ConfigContext); } = React.useContext(ConfigContext);
const size = React.useContext(SizeContext); const size = React.useContext(SizeContext);
devWarning( warning(
multiple !== false || !treeCheckable, multiple !== false || !treeCheckable,
'TreeSelect', 'TreeSelect',
'`multiple` will always be `true` when `treeCheckable` is true', '`multiple` will always be `true` when `treeCheckable` is true',

View File

@ -56,7 +56,7 @@
} }
// >>> Checkbox // >>> Checkbox
&-checkbox { &-checkbox {
.@{tree-prefix-cls}-rtl& { .@{tree-prefix-cls}-rtl & {
margin: ((@tree-title-height - @checkbox-size) / 2) 0 0 8px; margin: ((@tree-title-height - @checkbox-size) / 2) 0 0 8px;
} }
} }

View File

@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import type { BlockProps } from './Base'; import type { BlockProps } from './Base';
import Base from './Base'; import Base from './Base';
@ -13,7 +13,7 @@ const Link: React.ForwardRefRenderFunction<HTMLElement, LinkProps> = (
{ ellipsis, rel, ...restProps }, { ellipsis, rel, ...restProps },
ref, ref,
) => { ) => {
devWarning( warning(
typeof ellipsis !== 'object', typeof ellipsis !== 'object',
'Typography.Link', 'Typography.Link',
'`ellipsis` only supports boolean value.', '`ellipsis` only supports boolean value.',

View File

@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import omit from 'rc-util/lib/omit'; import omit from 'rc-util/lib/omit';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import type { BlockProps, EllipsisConfig } from './Base'; import type { BlockProps, EllipsisConfig } from './Base';
import Base from './Base'; import Base from './Base';
@ -21,7 +21,7 @@ const Text: React.ForwardRefRenderFunction<HTMLSpanElement, TextProps> = (
return ellipsis; return ellipsis;
}, [ellipsis]); }, [ellipsis]);
devWarning( warning(
typeof ellipsis !== 'object' || typeof ellipsis !== 'object' ||
!ellipsis || !ellipsis ||
(!('expandable' in ellipsis) && !('rows' in ellipsis)), (!('expandable' in ellipsis) && !('rows' in ellipsis)),

View File

@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
import type { BlockProps } from './Base'; import type { BlockProps } from './Base';
import Base from './Base'; import Base from './Base';
import { tupleNum } from '../_util/type'; import { tupleNum } from '../_util/type';
@ -21,7 +21,7 @@ const Title: React.ForwardRefRenderFunction<HTMLHeadingElement, TitleProps> = (p
if (TITLE_ELE_LIST.indexOf(level) !== -1) { if (TITLE_ELE_LIST.indexOf(level) !== -1) {
component = `h${level}`; component = `h${level}`;
} else { } else {
devWarning( warning(
false, false,
'Typography.Title', 'Typography.Title',
'Title only accept `1 | 2 | 3 | 4 | 5` as `level` value. And `5` need 4.6.0+ version.', 'Title only accept `1 | 2 | 3 | 4 | 5` as `level` value. And `5` need 4.6.0+ version.',

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { composeRef } from 'rc-util/lib/ref'; import { composeRef } from 'rc-util/lib/ref';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
export interface TypographyProps { export interface TypographyProps {
id?: string; id?: string;
@ -35,7 +35,7 @@ const Typography: React.ForwardRefRenderFunction<{}, InternalTypographyProps> =
let mergedRef = ref; let mergedRef = ref;
if (setContentRef) { if (setContentRef) {
devWarning(false, 'Typography', '`setContentRef` is deprecated. Please use `ref` instead.'); warning(false, 'Typography', '`setContentRef` is deprecated. Please use `ref` instead.');
mergedRef = composeRef(ref, setContentRef); mergedRef = composeRef(ref, setContentRef);
} }

View File

@ -18,7 +18,7 @@ import { file2Obj, getFileItem, removeFileItem, updateFileList } from './utils';
import LocaleReceiver from '../locale-provider/LocaleReceiver'; import LocaleReceiver from '../locale-provider/LocaleReceiver';
import defaultLocale from '../locale/default'; import defaultLocale from '../locale/default';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import warning from '../_util/warning';
export const LIST_IGNORE = `__LIST_IGNORE_${Date.now()}__`; export const LIST_IGNORE = `__LIST_IGNORE_${Date.now()}__`;
@ -59,19 +59,17 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
const upload = React.useRef<any>(); const upload = React.useRef<any>();
React.useEffect(() => { warning(
devWarning( 'fileList' in props || !('value' in props),
'fileList' in props || !('value' in props), 'Upload',
'Upload', '`value` is not a valid prop, do you mean `fileList`?',
'`value` is not a valid prop, do you mean `fileList`?', );
);
devWarning( warning(
!('transformFile' in props), !('transformFile' in props),
'Upload', 'Upload',
'`transformFile` is deprecated. Please use `beforeUpload` directly.', '`transformFile` is deprecated. Please use `beforeUpload` directly.',
); );
}, []);
// Control mode will auto fill file uid if not provided // Control mode will auto fill file uid if not provided
React.useMemo(() => { React.useMemo(() => {

View File

@ -8,7 +8,7 @@ import Upload from '..';
import Form from '../../form'; import Form from '../../form';
import { getFileItem, removeFileItem, isImageUrl } from '../utils'; import { getFileItem, removeFileItem, isImageUrl } from '../utils';
import { setup, teardown } from './mock'; import { setup, teardown } from './mock';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/warning';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest'; import rtlTest from '../../../tests/shared/rtlTest';
import { sleep, render, fireEvent } from '../../../tests/utils'; import { sleep, render, fireEvent } from '../../../tests/utils';

View File

@ -1,6 +1,6 @@
{ {
"name": "antd", "name": "antd",
"version": "4.20.2", "version": "4.20.4",
"description": "An enterprise-class UI design language and React components implementation", "description": "An enterprise-class UI design language and React components implementation",
"title": "Ant Design", "title": "Ant Design",
"keywords": [ "keywords": [
@ -159,9 +159,9 @@
"scroll-into-view-if-needed": "^2.2.25" "scroll-into-view-if-needed": "^2.2.25"
}, },
"devDependencies": { "devDependencies": {
"@ant-design/bisheng-plugin": "^3.0.1", "@ant-design/bisheng-plugin": "^3.2.0",
"@ant-design/hitu": "^0.0.0-alpha.13", "@ant-design/hitu": "^0.0.0-alpha.13",
"@ant-design/tools": "^14.0.2", "@ant-design/tools": "^15.0.1",
"@docsearch/css": "^3.0.0", "@docsearch/css": "^3.0.0",
"@qixian.cs/github-contributors-list": "^1.0.3", "@qixian.cs/github-contributors-list": "^1.0.3",
"@stackblitz/sdk": "^1.3.0", "@stackblitz/sdk": "^1.3.0",
@ -187,7 +187,7 @@
"antd-img-crop": "^4.0.0", "antd-img-crop": "^4.0.0",
"array-move": "^4.0.0", "array-move": "^4.0.0",
"babel-plugin-add-react-displayname": "^0.0.5", "babel-plugin-add-react-displayname": "^0.0.5",
"bisheng": "^3.3.0", "bisheng": "^3.5.0",
"bisheng-plugin-description": "^0.1.4", "bisheng-plugin-description": "^0.1.4",
"bisheng-plugin-react": "^1.2.0", "bisheng-plugin-react": "^1.2.0",
"bisheng-plugin-toc": "^0.4.4", "bisheng-plugin-toc": "^0.4.4",
@ -223,17 +223,18 @@
"full-icu": "^1.3.0", "full-icu": "^1.3.0",
"glob": "^8.0.1", "glob": "^8.0.1",
"http-server": "^14.0.0", "http-server": "^14.0.0",
"husky": "^7.0.1", "husky": "^8.0.1",
"identity-obj-proxy": "^3.0.0", "identity-obj-proxy": "^3.0.0",
"immer": "^9.0.1", "immer": "^9.0.1",
"immutability-helper": "^3.0.0", "immutability-helper": "^3.0.0",
"inquirer": "^8.0.0", "inquirer": "^8.0.0",
"intersection-observer": "^0.12.0", "intersection-observer": "^0.12.0",
"isomorphic-fetch": "^3.0.0", "isomorphic-fetch": "^3.0.0",
"jest": "^27.0.3", "jest": "^28.0.3",
"jest-axe": "^6.0.0", "jest-axe": "^6.0.0",
"jest-environment-node": "^27.4.4", "jest-environment-jsdom": "^28.0.2",
"jest-image-snapshot": "^4.5.1", "jest-environment-node": "^28.0.2",
"@ant-design/jest-image-snapshot": "^4.5.2",
"jest-puppeteer": "^6.0.0", "jest-puppeteer": "^6.0.0",
"jquery": "^3.4.1", "jquery": "^3.4.1",
"jsdom": "^19.0.0", "jsdom": "^19.0.0",

View File

@ -162,29 +162,31 @@ module.exports = {
} }
// Split chunks // Split chunks
config.optimization.splitChunks = { if (config.mode === 'production') {
...config.optimization.splitChunks, config.optimization.splitChunks = {
cacheGroups: { ...config.optimization.splitChunks,
vendors: { cacheGroups: {
test: /[/\\]node_modules[/\\]@ant-design[/\\]icon/, vendors: {
name: 'anticon', test: /[/\\]node_modules[/\\]@ant-design[/\\]icon/,
chunks: 'initial', name: 'anticon',
maxSize: 1024 * 1024, chunks: 'initial',
}, maxSize: 1024 * 1024,
components: { },
test(module) { components: {
return ( test(module) {
module.resource && return (
module.resource.includes('ant-design/components') && module.resource &&
!module.resource.includes('demo') && module.resource.includes('ant-design/components') &&
!module.resource.endsWith('md') !module.resource.includes('demo') &&
); !module.resource.endsWith('md')
);
},
name: 'components',
chunks: 'initial',
}, },
name: 'components',
chunks: 'initial',
}, },
}, };
}; }
return config; return config;
}, },

View File

@ -223,8 +223,10 @@ class Demo extends React.Component {
'const { $1 } = ReactRouterDOM;', 'const { $1 } = ReactRouterDOM;',
) )
.replace(/([A-Za-z]*)\s+as\s+([A-Za-z]*)/, '$1:$2') .replace(/([A-Za-z]*)\s+as\s+([A-Za-z]*)/, '$1:$2')
.replace(/export default/, 'const Demo =')}\n\n${ .replace(/export default/, 'const ComponentDemo =')}\n\n${
react18 ? 'createRoot(mountNode).render(<Demo />)' : 'ReactDOM.render(<Demo />, mountNode)' react18
? 'createRoot(mountNode).render(<ComponentDemo />)'
: 'ReactDOM.render(<ComponentDemo />, mountNode)'
};\n`, };\n`,
css: prefillStyle, css: prefillStyle,
editors: '001', editors: '001',
@ -253,8 +255,10 @@ class Demo extends React.Component {
react18 react18
? `import React from 'react';\nimport { createRoot } from 'react-dom/client';\n` ? `import React from 'react';\nimport { createRoot } from 'react-dom/client';\n`
: '' : ''
}${sourceCode.replace(/export default/, 'const Demo =')}\n\n${ }${sourceCode.replace(/export default/, 'const ComponentDemo =')}\n\n${
react18 ? 'createRoot(mountNode).render(<Demo />)' : 'ReactDOM.render(<Demo />, mountNode)' react18
? 'createRoot(mountNode).render(<ComponentDemo />)'
: 'ReactDOM.render(<ComponentDemo />, mountNode)'
};\n`, };\n`,
css: prefillStyle, css: prefillStyle,
json: JSON.stringify( json: JSON.stringify(

View File

@ -3,7 +3,7 @@ import React from 'react';
import AntdIcon, { createFromIconfontCN } from '@ant-design/icons'; import AntdIcon, { createFromIconfontCN } from '@ant-design/icons';
import { withThemeSuffix, removeTypeTheme, getThemeFromTypeName } from './utils'; import { withThemeSuffix, removeTypeTheme, getThemeFromTypeName } from './utils';
import warning from '../../../../components/_util/devWarning'; import warning from '../../../../components/_util/warning';
const IconFont = createFromIconfontCN({ const IconFont = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/font_1329669_t1u72b9zk8s.js', scriptUrl: '//at.alicdn.com/t/font_1329669_t1u72b9zk8s.js',

View File

@ -1,4 +1,4 @@
import warning from '../../../../components/_util/devWarning'; import warning from '../../../../components/_util/warning';
// These props make sure that the SVG behaviours like general text. // These props make sure that the SVG behaviours like general text.
// Reference: https://blog.prototypr.io/align-svg-icons-to-text-and-say-goodbye-to-font-icons-d44b3d7b26b4 // Reference: https://blog.prototypr.io/align-svg-icons-to-text-and-say-goodbye-to-font-icons-d44b3d7b26b4

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