mirror of
https://github.com/ant-design/ant-design.git
synced 2025-08-06 16:06:28 +08:00
merge master
This commit is contained in:
commit
cbeecdc41f
1
.jest.js
1
.jest.js
@ -25,6 +25,7 @@ module.exports = {
|
||||
'^react-dnd-touch-backend$': 'react-dnd-touch-backend/dist/cjs',
|
||||
'^react-dnd-test-backend$': 'react-dnd-test-backend/dist/cjs',
|
||||
'^react-dnd-test-utils$': 'react-dnd-test-utils/dist/cjs',
|
||||
'\\.(css|less)$': 'identity-obj-proxy',
|
||||
},
|
||||
testPathIgnorePatterns: ['/node_modules/', 'dekko', 'node', 'image.test.js'],
|
||||
transform: {
|
||||
|
@ -37,7 +37,7 @@ function isSelectOptionOrSelectOptGroup(child: any): Boolean {
|
||||
return child && child.type && (child.type.isSelectOption || child.type.isSelectOptGroup);
|
||||
}
|
||||
|
||||
const AutoComplete: React.RefForwardingComponent<Select, AutoCompleteProps> = (props, ref) => {
|
||||
const AutoComplete: React.ForwardRefRenderFunction<Select, AutoCompleteProps> = (props, ref) => {
|
||||
const { prefixCls: customizePrefixCls, className, children, dataSource } = props;
|
||||
const childNodes: React.ReactElement[] = toArray(children);
|
||||
|
||||
|
@ -928,7 +928,7 @@ Array [
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -1052,12 +1052,13 @@ Array [
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-content ant-tabs-content-top"
|
||||
style="margin-left:-100%"
|
||||
>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
@ -1070,7 +1071,7 @@ Array [
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
|
@ -57,7 +57,7 @@ export interface CardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 't
|
||||
tabProps?: TabsProps;
|
||||
}
|
||||
|
||||
interface CardInterface extends React.FC<CardProps> {
|
||||
export interface CardInterface extends React.FC<CardProps> {
|
||||
Grid: typeof Grid;
|
||||
Meta: typeof Meta;
|
||||
}
|
||||
|
@ -79,7 +79,7 @@
|
||||
display: inline-block;
|
||||
color: @comment-action-color;
|
||||
> span {
|
||||
padding-right: 10px;
|
||||
margin-right: 10px;
|
||||
color: @comment-action-color;
|
||||
font-size: @comment-font-size-sm;
|
||||
cursor: pointer;
|
||||
|
@ -34,8 +34,8 @@
|
||||
> li {
|
||||
> span {
|
||||
.@{comment-prefix-cls}-rtl & {
|
||||
padding-right: 0;
|
||||
padding-left: 10px;
|
||||
margin-right: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ export const ConfigConsumer = ConfigContext.Consumer;
|
||||
// =========================== withConfigConsumer ===========================
|
||||
// We need define many types here. So let's put in the block region
|
||||
type IReactComponent<P = any> =
|
||||
| React.StatelessComponent<P>
|
||||
| React.FC<P>
|
||||
| React.ComponentClass<P>
|
||||
| React.ClassicComponentClass<P>;
|
||||
|
||||
|
@ -59,7 +59,7 @@ The following APIs are shared by DatePicker, YearPicker, MonthPicker, RangePicke
|
||||
| mode | picker panel mode([Cannot select year or month anymore?](/docs/react/faq#When-set-mode-to-DatePicker/RangePicker,-cannot-select-year-or-month-anymore?) | `time` \| `date` \| `month` \| `year` \| `decade` | - | |
|
||||
| open | open state of picker | boolean | - | |
|
||||
| picker | Set picker type | `date` \| `week` \| `month` \| `quarter` (4.1.0) \| `year` | `date` | |
|
||||
| placeholder | placeholder of date input | string\|RangePicker\[] | - | |
|
||||
| placeholder | placeholder of date input | string \| \[string,string] | - | |
|
||||
| popupStyle | to customize the style of the popup calendar | CSSProperties | {} | |
|
||||
| size | determine the size of the input box, the height of `large` and `small`, are 40px and 24px respectively, while default size is 32px | `large` \| `middle` \| `small` | - | |
|
||||
| bordered | whether has border style | Boolean | true | |
|
||||
|
@ -61,7 +61,7 @@ import 'moment/locale/zh-cn';
|
||||
| mode | 日期面板的状态([设置后无法选择年份/月份?](/docs/react/faq#当我指定了-DatePicker/RangePicker-的-mode-属性后,点击后无法选择年份/月份?)) | `time` \| `date` \| `month` \| `year` \| `decade` | - | |
|
||||
| open | 控制弹层是否展开 | boolean | - | |
|
||||
| picker | 设置选择器类型 | `date` \| `week` \| `month` \| `quarter` (4.1.0) \| `year` | `date` | |
|
||||
| placeholder | 输入框提示文字 | string\|RangePicker\[] | - | |
|
||||
| placeholder | 输入框提示文字 | string \| \[string, string] | - | |
|
||||
| popupStyle | 额外的弹出日历样式 | CSSProperties | {} | |
|
||||
| size | 输入框大小,`large` 高度为 40px,`small` 为 24px,默认是 32px | `large` \| `middle` \| `small` | 无 | |
|
||||
| bordered | 是否有边框 | Boolean | true | |
|
||||
|
@ -2,7 +2,6 @@
|
||||
@import '../../style/mixins/index';
|
||||
|
||||
@divider-prefix-cls: ~'@{ant-prefix}-divider';
|
||||
@divider-text-padding: 1em;
|
||||
|
||||
.@{divider-prefix-cls} {
|
||||
.reset-component;
|
||||
@ -51,22 +50,22 @@
|
||||
&-horizontal&-with-text-left {
|
||||
&::before {
|
||||
top: 50%;
|
||||
width: 5%;
|
||||
width: @divider-orientation-margin;
|
||||
}
|
||||
&::after {
|
||||
top: 50%;
|
||||
width: 95%;
|
||||
width: 100% - @divider-orientation-margin;
|
||||
}
|
||||
}
|
||||
|
||||
&-horizontal&-with-text-right {
|
||||
&::before {
|
||||
top: 50%;
|
||||
width: 95%;
|
||||
width: 100% - @divider-orientation-margin;
|
||||
}
|
||||
&::after {
|
||||
top: 50%;
|
||||
width: 5%;
|
||||
width: @divider-orientation-margin;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,12 +11,12 @@
|
||||
&-horizontal&-with-text-left {
|
||||
&::before {
|
||||
.@{divider-prefix-cls}-rtl& {
|
||||
width: 95%;
|
||||
width: 100% - @divider-orientation-margin;
|
||||
}
|
||||
}
|
||||
&::after {
|
||||
.@{divider-prefix-cls}-rtl& {
|
||||
width: 5%;
|
||||
width: @divider-orientation-margin;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,12 +24,12 @@
|
||||
&-horizontal&-with-text-right {
|
||||
&::before {
|
||||
.@{divider-prefix-cls}-rtl& {
|
||||
width: 5%;
|
||||
width: @divider-orientation-margin;
|
||||
}
|
||||
}
|
||||
&::after {
|
||||
.@{divider-prefix-cls}-rtl& {
|
||||
width: 95%;
|
||||
width: 100% - @divider-orientation-margin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ function FormItem(props: FormItemProps): React.ReactElement {
|
||||
nameRef.current = [...mergedName];
|
||||
if (fieldKey) {
|
||||
const fieldKeys = Array.isArray(fieldKey) ? fieldKey : [fieldKey];
|
||||
nameRef.current = [...mergedName.slice(-1), ...fieldKeys];
|
||||
nameRef.current = [...mergedName.slice(0, -1), ...fieldKeys];
|
||||
}
|
||||
updateItemErrors(nameRef.current.join('__SPLIT__'), errors);
|
||||
}
|
||||
|
@ -10,11 +10,6 @@ import { sleep } from '../../../tests/utils';
|
||||
|
||||
jest.mock('scroll-into-view-if-needed');
|
||||
|
||||
const delay = (timeout = 0) =>
|
||||
new Promise(resolve => {
|
||||
setTimeout(resolve, timeout);
|
||||
});
|
||||
|
||||
describe('Form', () => {
|
||||
mountTest(Form);
|
||||
mountTest(Form.Item);
|
||||
@ -27,7 +22,7 @@ describe('Form', () => {
|
||||
|
||||
async function change(wrapper, index, value) {
|
||||
wrapper.find(Input).at(index).simulate('change', { target: { value } });
|
||||
await delay(50);
|
||||
await sleep(100);
|
||||
wrapper.update();
|
||||
}
|
||||
|
||||
@ -45,133 +40,6 @@ describe('Form', () => {
|
||||
scrollIntoView.mockRestore();
|
||||
});
|
||||
|
||||
describe('List', () => {
|
||||
function testList(name, renderField) {
|
||||
it(name, async () => {
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.List name="list">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
{fields.map(field => renderField(field))}
|
||||
<Button className="add" onClick={add}>
|
||||
Add
|
||||
</Button>
|
||||
<Button
|
||||
className="remove"
|
||||
onClick={() => {
|
||||
remove(1);
|
||||
}}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
async function operate(className) {
|
||||
wrapper.find(className).last().simulate('click');
|
||||
await delay();
|
||||
wrapper.update();
|
||||
}
|
||||
|
||||
await operate('.add');
|
||||
expect(wrapper.find(Input).length).toBe(1);
|
||||
|
||||
await operate('.add');
|
||||
expect(wrapper.find(Input).length).toBe(2);
|
||||
|
||||
await change(wrapper, 1, '');
|
||||
wrapper.update();
|
||||
await sleep(300);
|
||||
expect(wrapper.find('.ant-form-item-explain').length).toBe(1);
|
||||
|
||||
await operate('.remove');
|
||||
wrapper.update();
|
||||
expect(wrapper.find(Input).length).toBe(1);
|
||||
expect(wrapper.find('.ant-form-item-explain').length).toBe(0);
|
||||
});
|
||||
}
|
||||
|
||||
testList('operation correctly', field => (
|
||||
<Form.Item {...field} rules={[{ required: true }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
));
|
||||
|
||||
testList('nest noStyle', field => (
|
||||
<Form.Item key={field.key}>
|
||||
<Form.Item noStyle {...field} rules={[{ required: true }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
));
|
||||
|
||||
it('correct onFinish values', async () => {
|
||||
async function click(wrapper, className) {
|
||||
wrapper.find(className).last().simulate('click');
|
||||
await delay();
|
||||
wrapper.update();
|
||||
}
|
||||
|
||||
const onFinish = jest.fn().mockImplementation(() => {});
|
||||
|
||||
const wrapper = mount(
|
||||
<Form
|
||||
onFinish={v => {
|
||||
if (typeof v.list[0] === 'object') {
|
||||
/* old version led to SyntheticEvent be passed as an value here
|
||||
that led to weird infinite loop somewhere and OutOfMemory crash */
|
||||
v = new Error('We expect value to be a primitive here');
|
||||
}
|
||||
onFinish(v);
|
||||
}}
|
||||
>
|
||||
<Form.List name="list">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
{fields.map(field => (
|
||||
// key is in a field
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Form.Item {...field}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
))}
|
||||
<Button className="add" onClick={add}>
|
||||
Add
|
||||
</Button>
|
||||
<Button className="remove" onClick={() => remove(0)}>
|
||||
Remove
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
await click(wrapper, '.add');
|
||||
await change(wrapper, 0, 'input1');
|
||||
wrapper.find('form').simulate('submit');
|
||||
await delay();
|
||||
expect(onFinish).toHaveBeenLastCalledWith({ list: ['input1'] });
|
||||
|
||||
await click(wrapper, '.add');
|
||||
await change(wrapper, 1, 'input2');
|
||||
await click(wrapper, '.add');
|
||||
await change(wrapper, 2, 'input3');
|
||||
wrapper.find('form').simulate('submit');
|
||||
await delay();
|
||||
expect(onFinish).toHaveBeenLastCalledWith({ list: ['input1', 'input2', 'input3'] });
|
||||
|
||||
await click(wrapper, '.remove'); // will remove first input
|
||||
wrapper.find('form').simulate('submit');
|
||||
await delay();
|
||||
expect(onFinish).toHaveBeenLastCalledWith({ list: ['input2', 'input3'] });
|
||||
});
|
||||
});
|
||||
|
||||
it('noStyle Form.Item', async () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
@ -300,7 +168,7 @@ describe('Form', () => {
|
||||
|
||||
expect(scrollIntoView).not.toHaveBeenCalled();
|
||||
wrapper.find('form').simulate('submit');
|
||||
await delay(50);
|
||||
await sleep(50);
|
||||
expect(scrollIntoView).toHaveBeenCalled();
|
||||
expect(onFinishFailed).toHaveBeenCalled();
|
||||
|
||||
@ -401,7 +269,7 @@ describe('Form', () => {
|
||||
expect(wrapper.find('.ant-form-item-explain').first().text()).toEqual("'name' is required");
|
||||
|
||||
await change(wrapper, 0, 'p');
|
||||
await delay(100);
|
||||
await sleep(100);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-form-item-explain').first().text()).toEqual('not a p');
|
||||
}
|
||||
@ -585,9 +453,9 @@ describe('Form', () => {
|
||||
);
|
||||
|
||||
wrapper.find('form').simulate('submit');
|
||||
await delay(100);
|
||||
await sleep(100);
|
||||
wrapper.update();
|
||||
await delay(100);
|
||||
await sleep(100);
|
||||
expect(wrapper.find('.ant-form-item-explain').first().text()).toEqual('Bamboo is good!');
|
||||
});
|
||||
|
||||
@ -642,7 +510,7 @@ describe('Form', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await delay();
|
||||
await sleep();
|
||||
|
||||
expect(renderTimes).toEqual(1);
|
||||
expect(wrapper.find('input').props().value).toEqual('a');
|
||||
|
167
components/form/__tests__/list.test.js
Normal file
167
components/form/__tests__/list.test.js
Normal file
@ -0,0 +1,167 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import raf from 'raf';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import Form from '..';
|
||||
import Input from '../../input';
|
||||
import Button from '../../button';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
|
||||
jest.mock('raf');
|
||||
|
||||
describe('Form.List', () => {
|
||||
raf.mockImplementation(callback => window.setTimeout(callback));
|
||||
|
||||
afterAll(() => {
|
||||
raf.mockRestore();
|
||||
});
|
||||
|
||||
async function change(wrapper, index, value) {
|
||||
wrapper.find(Input).at(index).simulate('change', { target: { value } });
|
||||
await sleep();
|
||||
wrapper.update();
|
||||
}
|
||||
|
||||
function testList(name, renderField) {
|
||||
it(name, async () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.List name="list">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
{fields.map(field => renderField(field))}
|
||||
<Button className="add" onClick={add}>
|
||||
Add
|
||||
</Button>
|
||||
<Button
|
||||
className="remove-0"
|
||||
onClick={() => {
|
||||
remove(0);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
className="remove-1"
|
||||
onClick={() => {
|
||||
remove(1);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
function operate(className) {
|
||||
act(() => {
|
||||
wrapper.find(className).last().simulate('click');
|
||||
jest.runAllTimers();
|
||||
});
|
||||
wrapper.update();
|
||||
}
|
||||
|
||||
operate('.add');
|
||||
expect(wrapper.find(Input).length).toBe(1);
|
||||
|
||||
operate('.add');
|
||||
expect(wrapper.find(Input).length).toBe(2);
|
||||
|
||||
operate('.add');
|
||||
expect(wrapper.find(Input).length).toBe(3);
|
||||
|
||||
await change(wrapper, 2, '');
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-form-item-explain div').length).toBe(1);
|
||||
|
||||
operate('.remove-0');
|
||||
expect(wrapper.find(Input).length).toBe(2);
|
||||
expect(wrapper.find('.ant-form-item-explain div').length).toBe(1);
|
||||
|
||||
operate('.remove-1');
|
||||
expect(wrapper.find(Input).length).toBe(1);
|
||||
expect(wrapper.find('.ant-form-item-explain div').length).toBe(0);
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
}
|
||||
|
||||
testList('operation correctly', field => (
|
||||
<Form.Item {...field} rules={[{ required: true }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
));
|
||||
|
||||
testList('nest noStyle', field => (
|
||||
<Form.Item key={field.key}>
|
||||
<Form.Item noStyle {...field} rules={[{ required: true }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
));
|
||||
|
||||
it('correct onFinish values', async () => {
|
||||
async function click(wrapper, className) {
|
||||
wrapper.find(className).last().simulate('click');
|
||||
await sleep();
|
||||
wrapper.update();
|
||||
}
|
||||
|
||||
const onFinish = jest.fn().mockImplementation(() => {});
|
||||
|
||||
const wrapper = mount(
|
||||
<Form
|
||||
onFinish={v => {
|
||||
if (typeof v.list[0] === 'object') {
|
||||
/* old version led to SyntheticEvent be passed as an value here
|
||||
that led to weird infinite loop somewhere and OutOfMemory crash */
|
||||
v = new Error('We expect value to be a primitive here');
|
||||
}
|
||||
onFinish(v);
|
||||
}}
|
||||
>
|
||||
<Form.List name="list">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
{fields.map(field => (
|
||||
// key is in a field
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Form.Item {...field}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
))}
|
||||
<Button className="add" onClick={add}>
|
||||
Add
|
||||
</Button>
|
||||
<Button className="remove" onClick={() => remove(0)}>
|
||||
Remove
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
await click(wrapper, '.add');
|
||||
await change(wrapper, 0, 'input1');
|
||||
wrapper.find('form').simulate('submit');
|
||||
await sleep();
|
||||
expect(onFinish).toHaveBeenLastCalledWith({ list: ['input1'] });
|
||||
|
||||
await click(wrapper, '.add');
|
||||
await change(wrapper, 1, 'input2');
|
||||
await click(wrapper, '.add');
|
||||
await change(wrapper, 2, 'input3');
|
||||
wrapper.find('form').simulate('submit');
|
||||
await sleep();
|
||||
expect(onFinish).toHaveBeenLastCalledWith({ list: ['input1', 'input2', 'input3'] });
|
||||
|
||||
await click(wrapper, '.remove'); // will remove first input
|
||||
wrapper.find('form').simulate('submit');
|
||||
await sleep();
|
||||
expect(onFinish).toHaveBeenLastCalledWith({ list: ['input2', 'input3'] });
|
||||
});
|
||||
});
|
@ -15,7 +15,7 @@ export interface GroupProps {
|
||||
compact?: boolean;
|
||||
}
|
||||
|
||||
const Group: React.StatelessComponent<GroupProps> = props => (
|
||||
const Group: React.FC<GroupProps> = props => (
|
||||
<ConfigConsumer>
|
||||
{({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, className = '' } = props;
|
||||
|
@ -21,7 +21,7 @@ interface ModalLocale {
|
||||
justOkText: string;
|
||||
}
|
||||
|
||||
const HookModal: React.RefForwardingComponent<HookModalRef, HookModalProps> = (
|
||||
const HookModal: React.ForwardRefRenderFunction<HookModalRef, HookModalProps> = (
|
||||
{ afterClose, config },
|
||||
ref,
|
||||
) => {
|
||||
|
@ -1264,7 +1264,7 @@ exports[`renders ./components/page-header/demo/responsive.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
|
@ -4,12 +4,15 @@ import * as React from 'react';
|
||||
import omit from 'omit.js';
|
||||
import classNames from 'classnames';
|
||||
import RcSelect, { Option, OptGroup, SelectProps as RcSelectProps } from 'rc-select';
|
||||
import { OptionProps } from 'rc-select/lib/Option';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import getIcons from './utils/iconUtil';
|
||||
import SizeContext, { SizeType } from '../config-provider/SizeContext';
|
||||
|
||||
type RawValue = string | number;
|
||||
|
||||
export { OptionProps };
|
||||
|
||||
export type OptionType = typeof Option;
|
||||
|
||||
export interface LabeledValue {
|
||||
|
@ -33,7 +33,7 @@ Provide a placeholder while you wait for content to load, or to visualise conten
|
||||
| Property | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| active | Show animation effect, only valid when used avatar independently. | boolean | false |
|
||||
| size | Set the size of avatar | number \| `large` \| `small` \| `default` } | - |
|
||||
| size | Set the size of avatar | number \| `large` \| `small` \| `default` | - |
|
||||
| shape | Set the shape of avatar | `circle` \| `square` | - |
|
||||
|
||||
### SkeletonTitleProps
|
||||
@ -59,7 +59,7 @@ Provide a placeholder while you wait for content to load, or to visualise conten
|
||||
|
||||
### SkeletonInputProps
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ---------------------- | ------------------------------- | ------- |
|
||||
| active | Show animation effect | boolean | false |
|
||||
| size | Set the size of button | `large` \| `small` \| `default` | - |
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | --------------------- | ------------------------------- | ------- |
|
||||
| active | Show animation effect | boolean | false |
|
||||
| size | Set the size of input | `large` \| `small` \| `default` | - |
|
||||
|
@ -63,4 +63,4 @@ cover: https://gw.alipayobjects.com/zos/alicdn/KpcciCJgv/Skeleton.svg
|
||||
| 属性 | 说明 | 类型 | 默认值 |
|
||||
| ------ | ---------------- | ------------------------------- | ------ |
|
||||
| active | 是否展示动画效果 | boolean | false |
|
||||
| size | 设置按钮的大小 | `large` \| `small` \| `default` | - |
|
||||
| size | 设置输入框的大小 | `large` \| `small` \| `default` | - |
|
||||
|
@ -241,6 +241,10 @@
|
||||
@descriptions-item-label-colon-margin-right: 8px;
|
||||
@descriptions-item-label-colon-margin-left: 2px;
|
||||
|
||||
// Divider
|
||||
@divider-text-padding: 1em;
|
||||
@divider-orientation-margin: 5%;
|
||||
|
||||
// Dropdown
|
||||
@dropdown-selected-color: @primary-color;
|
||||
@dropdown-menu-submenu-disabled-bg: @component-background;
|
||||
|
@ -272,7 +272,7 @@ describe('Table.sorter', () => {
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/pull/12264#discussion_r218053034
|
||||
it('should sort from begining state when toggle from different columns', () => {
|
||||
it('should sort from beginning state when toggle from different columns', () => {
|
||||
const columns = [
|
||||
{
|
||||
title: 'name',
|
||||
@ -790,4 +790,55 @@ describe('Table.sorter', () => {
|
||||
.hasClass('active'),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('onChange with correct sorter for multiple', () => {
|
||||
const groupColumns = [
|
||||
{
|
||||
title: 'Math Score',
|
||||
dataIndex: 'math',
|
||||
sorter: { multiple: 1 },
|
||||
},
|
||||
{
|
||||
title: 'English Score',
|
||||
dataIndex: 'english',
|
||||
sorter: { multiple: 2 },
|
||||
},
|
||||
];
|
||||
|
||||
const groupData = [
|
||||
{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
chinese: 98,
|
||||
math: 60,
|
||||
english: 70,
|
||||
},
|
||||
];
|
||||
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<Table columns={groupColumns} data={groupData} onChange={onChange} />);
|
||||
|
||||
function clickToMatchExpect(index, sorter) {
|
||||
wrapper.find('.ant-table-column-sorters').at(index).simulate('click');
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
expect.objectContaining(sorter),
|
||||
expect.anything(),
|
||||
);
|
||||
|
||||
onChange.mockReset();
|
||||
}
|
||||
|
||||
// First
|
||||
clickToMatchExpect(0, { field: 'math', order: 'ascend' });
|
||||
clickToMatchExpect(0, { field: 'math', order: 'descend' });
|
||||
clickToMatchExpect(0, { field: 'math', order: undefined });
|
||||
|
||||
// Last
|
||||
clickToMatchExpect(1, { field: 'english', order: 'ascend' });
|
||||
clickToMatchExpect(1, { field: 'english', order: 'descend' });
|
||||
clickToMatchExpect(1, { field: 'english', order: undefined });
|
||||
});
|
||||
});
|
||||
|
@ -231,7 +231,7 @@ function generateSorterInfo<RecordType>(
|
||||
// https://github.com/ant-design/ant-design/pull/19226
|
||||
if (list.length === 0 && sorterStates.length) {
|
||||
return {
|
||||
...stateToInfo(sorterStates[0]),
|
||||
...stateToInfo(sorterStates[sorterStates.length - 1]),
|
||||
column: undefined,
|
||||
};
|
||||
}
|
||||
|
@ -102,14 +102,14 @@ exports[`renders ./components/tabs/demo/basic.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -219,14 +219,14 @@ exports[`renders ./components/tabs/demo/card.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -347,14 +347,14 @@ exports[`renders ./components/tabs/demo/card-top.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -523,7 +523,7 @@ exports[`renders ./components/tabs/demo/custom-add-trigger.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -639,14 +639,14 @@ exports[`renders ./components/tabs/demo/custom-tab-bar.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -757,14 +757,14 @@ exports[`renders ./components/tabs/demo/custom-tab-bar-node.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -875,14 +875,14 @@ exports[`renders ./components/tabs/demo/disabled.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -1106,14 +1106,14 @@ exports[`renders ./components/tabs/demo/editable-card.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -1235,14 +1235,14 @@ exports[`renders ./components/tabs/demo/extra.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -1374,12 +1374,13 @@ exports[`renders ./components/tabs/demo/icon.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-content ant-tabs-content-top"
|
||||
style="margin-left:-100%"
|
||||
>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
@ -1953,12 +1954,13 @@ exports[`renders ./components/tabs/demo/nest.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-content ant-tabs-content-top"
|
||||
style="margin-left:-100%"
|
||||
>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
@ -1973,126 +1975,126 @@ exports[`renders ./components/tabs/demo/nest.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -2103,7 +2105,7 @@ exports[`renders ./components/tabs/demo/nest.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -2288,14 +2290,14 @@ exports[`renders ./components/tabs/demo/position.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -2471,14 +2473,14 @@ exports[`renders ./components/tabs/demo/size.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -2585,14 +2587,14 @@ exports[`renders ./components/tabs/demo/size.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
@ -2980,12 +2982,13 @@ exports[`renders ./components/tabs/demo/slide.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-content ant-tabs-content-top"
|
||||
style="margin-left:-100%"
|
||||
>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
@ -3000,196 +3003,196 @@ exports[`renders ./components/tabs/demo/slide.md correctly 1`] = `
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
style="visibility:hidden;height:0;overflow-y:hidden"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
|
@ -7,11 +7,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
有四个位置,`tabPosition="left|right|top|bottom"`。
|
||||
有四个位置,`tabPosition="left|right|top|bottom"`。在移动端下,`left|right` 会自动切换成 `top`。
|
||||
|
||||
## en-US
|
||||
|
||||
Tab's position: left, right, top or bottom.
|
||||
Tab's position: left, right, top or bottom. Will auto switch to `top` in mobile.
|
||||
|
||||
```jsx
|
||||
import { Tabs, Select, Space } from 'antd';
|
||||
|
@ -42,7 +42,7 @@ import moment from 'moment';
|
||||
| inputReadOnly | Set the `readonly` attribute of the input tag (avoids virtual keyboard on touch devices) | boolean | false | |
|
||||
| minuteStep | interval between minutes in picker | number | 1 | |
|
||||
| open | whether to popup panel | boolean | false | |
|
||||
| placeholder | display when there's no value | string | "Select a time" | |
|
||||
| placeholder | display when there's no value | string \| \[string, string] | "Select a time" | |
|
||||
| popupClassName | className of panel | string | - | |
|
||||
| popupStyle | style of panel | CSSProperties | - | |
|
||||
| secondStep | interval between seconds in picker | number | 1 | |
|
||||
|
@ -42,7 +42,7 @@ import moment from 'moment';
|
||||
| inputReadOnly | 设置输入框为只读(避免在移动设备上打开虚拟键盘) | boolean | false | |
|
||||
| minuteStep | 分钟选项间隔 | number | 1 | |
|
||||
| open | 面板是否打开 | boolean | false | |
|
||||
| placeholder | 没有值的时候显示的内容 | string | "请选择时间" | |
|
||||
| placeholder | 没有值的时候显示的内容 | string \| \[string, string] | "请选择时间" | |
|
||||
| popupClassName | 弹出层类名 | string | - | |
|
||||
| popupStyle | 弹出层样式对象 | object | - | |
|
||||
| secondStep | 秒选项间隔 | number | 1 | |
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import DeleteOutlined from '@ant-design/icons/DeleteOutlined';
|
||||
import { TransferItem, TransferLocale } from '.';
|
||||
import defaultLocale from '../locale/default';
|
||||
import Checkbox from '../checkbox';
|
||||
|
@ -19,7 +19,7 @@ interface InternalTypographyProps extends TypographyProps {
|
||||
setContentRef?: (node: HTMLElement) => void;
|
||||
}
|
||||
|
||||
const Typography: React.RefForwardingComponent<{}, InternalTypographyProps> = (
|
||||
const Typography: React.ForwardRefRenderFunction<{}, InternalTypographyProps> = (
|
||||
{
|
||||
prefixCls: customizePrefixCls,
|
||||
component = 'article',
|
||||
|
@ -91,7 +91,7 @@ exports[`renders ./components/typography/demo/basic.md correctly 1`] = `
|
||||
Esc
|
||||
</kbd>
|
||||
</span>
|
||||
to exist...
|
||||
to exit...
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
|
@ -57,7 +57,7 @@ ReactDOM.render(
|
||||
</Paragraph>
|
||||
|
||||
<Paragraph>
|
||||
Press <Text keyboard>Esc</Text> to exist...
|
||||
Press <Text keyboard>Esc</Text> to exit...
|
||||
</Paragraph>
|
||||
|
||||
<Divider />
|
||||
|
@ -20,7 +20,7 @@ According to our [release schedule](changelog#Release-Schedule), we maintain two
|
||||
|
||||
## Bugs
|
||||
|
||||
We are using [GitHub Issues](https://github.com/ant-design/ant-design/issues) for bug tracking. The best way to get your bug fixed is using our [issue helper](http://new-issue.ant.design) and provide reproduction steps with this [template](https://u.ant.design/codesandbox-repro).
|
||||
We are using [GitHub Issues](https://github.com/ant-design/ant-design/issues) for bug tracking. The best way to get your bug fixed is by using our [issue helper](http://new-issue.ant.design) and provide reproduction steps with this [template](https://u.ant.design/codesandbox-repro).
|
||||
|
||||
Before you report a bug, please make sure you've searched existing issues, and read our [FAQ](/docs/react/faq).
|
||||
|
||||
|
@ -4,7 +4,7 @@ order: 2
|
||||
title: Cases
|
||||
---
|
||||
|
||||
Starting in April 2015, more and more products of Ant Financial follow Ant Design specification, covering multiple business lines and more than 80 applications. Designed for enterprise-class complex UIs, used by both professional and non-professional designers, Ant Design has a low learning curve that helps you getting started fast and achieve rapid results.
|
||||
Starting in April 2015, more and more products of Ant Financial follow Ant Design specification, covering multiple business lines and more than 80 applications. Designed for enterprise-class complex UIs, used by both professional and non-professional designers, Ant Design has a low learning curve that helps you get started fast and achieve rapid results.
|
||||
|
||||
Currently, there are many products and sites using Ant Design. If your solutions are using Ant Design, please [leave us a message](https://github.com/ant-design/ant-design/issues/477).
|
||||
|
||||
|
@ -136,7 +136,7 @@
|
||||
"rc-steps": "~4.0.0",
|
||||
"rc-switch": "~3.2.0",
|
||||
"rc-table": "~7.7.2",
|
||||
"rc-tabs": "~11.3.1",
|
||||
"rc-tabs": "~11.4.1",
|
||||
"rc-tooltip": "~4.2.0",
|
||||
"rc-tree": "~3.3.0",
|
||||
"rc-tree-select": "~4.0.0",
|
||||
@ -147,7 +147,6 @@
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rc-virtual-list": "^1.1.0",
|
||||
"@ant-design/bisheng-plugin": "^2.3.0",
|
||||
"@ant-design/colors": "^4.0.0",
|
||||
"@ant-design/hitu": "^0.0.0-alpha.13",
|
||||
@ -209,6 +208,7 @@
|
||||
"glob": "^7.1.4",
|
||||
"http-server": "^0.12.0",
|
||||
"husky": "^4.0.3",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"ignore-emit-webpack-plugin": "^2.0.2",
|
||||
"immutability-helper": "^3.0.0",
|
||||
"inquirer": "^7.1.0",
|
||||
@ -235,6 +235,7 @@
|
||||
"rc-queue-anim": "^1.6.12",
|
||||
"rc-scroll-anim": "^2.5.8",
|
||||
"rc-tween-one": "^2.4.1",
|
||||
"rc-virtual-list": "^1.1.0",
|
||||
"react": "^16.9.0",
|
||||
"react-color": "^2.17.3",
|
||||
"react-copy-to-clipboard": "^5.0.1",
|
||||
|
@ -144,5 +144,6 @@ module.exports = {
|
||||
'app.docs.components.icon.pic-searcher.result-tip': 'Match the following icons for you:',
|
||||
'app.docs.components.icon.pic-searcher.th-icon': 'Icon',
|
||||
'app.docs.components.icon.pic-searcher.th-score': 'Probability',
|
||||
'app.components.overview.search': 'Search in components',
|
||||
},
|
||||
};
|
||||
|
@ -1,19 +1,32 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { Link } from 'bisheng/router';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Divider, Row, Col, Card, Typography, Tag, Space } from 'antd';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { Input, Divider, Row, Col, Card, Typography, Tag, Space } from 'antd';
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import { getChildren } from 'jsonml.js/lib/utils';
|
||||
import { getMetaDescription, getLocalizedPathname, getThemeConfig, getMenuItems } from '../utils';
|
||||
import './ComponentOverview.less';
|
||||
|
||||
const onClickCard = href => {
|
||||
window.gtag('event', '点击', {
|
||||
event_category: '组件总览卡片',
|
||||
event_label: href,
|
||||
});
|
||||
if (window.gtag) {
|
||||
window.gtag('event', '点击', {
|
||||
event_category: '组件总览卡片',
|
||||
event_label: href,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const reportSearch = debounce(value => {
|
||||
if (window.gtag) {
|
||||
window.gtag('event', '搜索', {
|
||||
event_category: '组件总览卡片',
|
||||
event_label: value,
|
||||
});
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
const { Title } = Typography;
|
||||
const ComponentOverview = ({
|
||||
componentsData = [],
|
||||
@ -23,7 +36,7 @@ const ComponentOverview = ({
|
||||
},
|
||||
utils: { toReactComponent },
|
||||
}) => {
|
||||
const { locale } = useIntl();
|
||||
const { locale, formatMessage } = useIntl();
|
||||
const documentTitle = `${title} - Ant Design`;
|
||||
const contentChild = getMetaDescription(getChildren(content));
|
||||
const themeConfig = getThemeConfig();
|
||||
@ -33,6 +46,7 @@ const ComponentOverview = ({
|
||||
themeConfig.categoryOrder,
|
||||
themeConfig.typeOrder,
|
||||
);
|
||||
const [search, setSearch] = useState('');
|
||||
|
||||
return (
|
||||
<section className="markdown">
|
||||
@ -44,47 +58,69 @@ const ComponentOverview = ({
|
||||
<h1>{title}</h1>
|
||||
{toReactComponent(['section', { className: 'markdown' }].concat(getChildren(content)))}
|
||||
<Divider />
|
||||
<Input
|
||||
value={search}
|
||||
placeholder={formatMessage({ id: 'app.components.overview.search' })}
|
||||
className="components-overview-search"
|
||||
onChange={e => {
|
||||
setSearch(e.target.value);
|
||||
reportSearch(e.target.value);
|
||||
}}
|
||||
autoFocus // eslint-disable-line jsx-a11y/no-autofocus
|
||||
suffix={<SearchOutlined />}
|
||||
/>
|
||||
<Divider />
|
||||
{menuItems
|
||||
.filter(i => i.order > -1)
|
||||
.map(group => (
|
||||
<div key={group.title} className="components-overview">
|
||||
<Title level={2} className="components-overview-group-title">
|
||||
<Space align="center">
|
||||
{group.title}
|
||||
<Tag style={{ display: 'block' }}>{group.children.length}</Tag>
|
||||
</Space>
|
||||
</Title>
|
||||
<Row gutter={[24, 24]}>
|
||||
{group.children
|
||||
.sort((a, b) => a.title.charCodeAt(0) - b.title.charCodeAt(0))
|
||||
.map(component => {
|
||||
const url = `${component.filename
|
||||
.replace(/(\/index)?((\.zh-cn)|(\.en-us))?\.md$/i, '')
|
||||
.toLowerCase()}/`;
|
||||
const href = getLocalizedPathname(url, locale === 'zh-CN');
|
||||
return (
|
||||
<Col xs={24} sm={12} lg={8} xl={6} key={component.title}>
|
||||
<Link to={href} onClick={() => onClickCard(href)}>
|
||||
<Card
|
||||
size="small"
|
||||
className="components-overview-card"
|
||||
title={
|
||||
<div className="components-overview-title">
|
||||
{component.title} {component.subtitle}
|
||||
.map(group => {
|
||||
const components = group.children.filter(
|
||||
component =>
|
||||
!search.trim() ||
|
||||
component.title.toLowerCase().includes(search.trim().toLowerCase()) ||
|
||||
(component.subtitle || '').toLowerCase().includes(search.trim().toLowerCase()),
|
||||
);
|
||||
return (
|
||||
<div key={group.title} className="components-overview">
|
||||
{components.length > 0 && (
|
||||
<Title level={2} className="components-overview-group-title">
|
||||
<Space align="center">
|
||||
{group.title}
|
||||
<Tag style={{ display: 'block' }}>{components.length}</Tag>
|
||||
</Space>
|
||||
</Title>
|
||||
)}
|
||||
<Row gutter={[24, 24]}>
|
||||
{components
|
||||
.sort((a, b) => a.title.charCodeAt(0) - b.title.charCodeAt(0))
|
||||
.map(component => {
|
||||
const url = `${component.filename
|
||||
.replace(/(\/index)?((\.zh-cn)|(\.en-us))?\.md$/i, '')
|
||||
.toLowerCase()}/`;
|
||||
const href = getLocalizedPathname(url, locale === 'zh-CN');
|
||||
return (
|
||||
<Col xs={24} sm={12} lg={8} xl={6} key={component.title}>
|
||||
<Link to={href} onClick={() => onClickCard(href)}>
|
||||
<Card
|
||||
size="small"
|
||||
className="components-overview-card"
|
||||
title={
|
||||
<div className="components-overview-title">
|
||||
{component.title} {component.subtitle}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="components-overview-img">
|
||||
<img src={component.cover} alt={component.title} />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="components-overview-img">
|
||||
<img src={component.cover} alt={component.title} />
|
||||
</div>
|
||||
</Card>
|
||||
</Link>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
))}
|
||||
</Card>
|
||||
</Link>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
@ -26,3 +26,20 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.components-overview-search {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
font-size: 20px;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
|
||||
input {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.anticon {
|
||||
color: #bbb;
|
||||
}
|
||||
}
|
||||
|
@ -140,5 +140,6 @@ module.exports = {
|
||||
'app.docs.components.icon.pic-searcher.result-tip': '为您匹配到以下图标:',
|
||||
'app.docs.components.icon.pic-searcher.th-icon': '图标',
|
||||
'app.docs.components.icon.pic-searcher.th-score': '匹配度',
|
||||
'app.components.overview.search': '搜索组件',
|
||||
},
|
||||
};
|
||||
|
@ -8,4 +8,6 @@ export function resetMockDate() {
|
||||
MockDate.reset();
|
||||
}
|
||||
|
||||
export const sleep = (timeout = 0) => new Promise(resolve => setTimeout(resolve, timeout));
|
||||
const globalTimeout = global.setTimeout;
|
||||
|
||||
export const sleep = (timeout = 0) => new Promise(resolve => globalTimeout(resolve, timeout));
|
||||
|
Loading…
Reference in New Issue
Block a user