Merge pull request #24905 from ant-design/feature-merge-master

chore: Feature merge master
This commit is contained in:
二货机器人 2020-06-11 11:36:14 +08:00 committed by GitHub
commit c842fcc71b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 468 additions and 313 deletions

View File

@ -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: {

View File

@ -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);

View File

@ -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>

View File

@ -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;
}

View File

@ -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;

View File

@ -34,8 +34,8 @@
> li {
> span {
.@{comment-prefix-cls}-rtl & {
padding-right: 0;
padding-left: 10px;
margin-right: 0;
margin-left: 10px;
}
}
}

View File

@ -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>;

View File

@ -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 | |

View File

@ -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 | |

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}

View File

@ -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');

View 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'] });
});
});

View File

@ -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;

View File

@ -21,7 +21,7 @@ interface ModalLocale {
justOkText: string;
}
const HookModal: React.RefForwardingComponent<HookModalRef, HookModalProps> = (
const HookModal: React.ForwardRefRenderFunction<HookModalRef, HookModalProps> = (
{ afterClose, config },
ref,
) => {

View File

@ -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>

View File

@ -741,7 +741,7 @@ exports[`renders ./components/select/demo/custom-tag-render.md correctly 1`] = `
gold
<span
aria-label="close"
class="anticon anticon-close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>
@ -770,7 +770,7 @@ exports[`renders ./components/select/demo/custom-tag-render.md correctly 1`] = `
cyan
<span
aria-label="close"
class="anticon anticon-close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>

View File

@ -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 {

View File

@ -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` | - |

View File

@ -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` | - |

View File

@ -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;

View File

@ -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 });
});
});

View File

@ -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,
};
}

View File

@ -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>

View File

@ -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';

View File

@ -15,7 +15,7 @@ Array [
Tag 1
<span
aria-label="close"
class="anticon anticon-close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>
@ -45,7 +45,7 @@ Array [
Tag 2
<span
aria-label="close"
class="anticon anticon-close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>
@ -75,7 +75,7 @@ Array [
Tag 3
<span
aria-label="close"
class="anticon anticon-close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>
@ -152,7 +152,7 @@ Array [
Tag 2
<span
aria-label="close"
class="anticon anticon-close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>
@ -178,7 +178,7 @@ Array [
Prevent Default
<span
aria-label="close"
class="anticon anticon-close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>
@ -356,7 +356,7 @@ Array [
</span>
<span
aria-label="close"
class="anticon anticon-close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>
@ -384,7 +384,7 @@ Array [
</span>
<span
aria-label="close"
class="anticon anticon-close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>
@ -444,7 +444,7 @@ Array [
Movies
<span
aria-label="close"
class="anticon anticon-close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>
@ -483,7 +483,7 @@ Array [
>
Tag1
<div
class="ant-tag-customize-close"
class="ant-tag-close-icon"
>
关 闭
</div>
@ -493,7 +493,7 @@ Array [
>
Tag2
<div
class="ant-tag-customize-close"
class="ant-tag-close-icon"
>
<span
aria-label="close-circle"

View File

@ -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 | |

View File

@ -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 | |

View File

@ -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';

View File

@ -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',

View File

@ -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"

View File

@ -57,7 +57,7 @@ ReactDOM.render(
</Paragraph>
<Paragraph>
Press <Text keyboard>Esc</Text> to exist...
Press <Text keyboard>Esc</Text> to exit...
</Paragraph>
<Divider />

View File

@ -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).

View File

@ -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).

View File

@ -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",

View File

@ -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',
},
};

View File

@ -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>
);
};

View File

@ -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;
}
}

View File

@ -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': '搜索组件',
},
};

View File

@ -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));