Merge pull request #16282 from ant-design/merge-master

Merge master
This commit is contained in:
偏右 2019-04-25 09:46:32 +08:00 committed by GitHub
commit 5d7b83f281
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 397 additions and 150 deletions

View File

@ -16,6 +16,7 @@ Please makes sure that these form are filled before submitting your pull request
- [ ] TypeScript definition update
- [ ] Refactoring
- [ ] Code style optimization
- [ ] Test Case
- [ ] Branch merge
- [ ] Other (about what?)

View File

@ -16,6 +16,7 @@
- [ ] TypeScript 定义更新
- [ ] 重构
- [ ] 代码风格优化
- [ ] 测试用例
- [ ] 分支合并
- [ ] 其他改动(是关于什么的改动?)

View File

@ -15,6 +15,15 @@ timeline: true
---
## 3.16.5
`2019-04-22`
- 🐞 Fix Table in Firefox miss bottom line when sorter enabled. [#16174](https://github.com/ant-design/ant-design/pull/16174)
- 🐞 Fix List crash when `pagination` is `null`. [#16231](https://github.com/ant-design/ant-design/pull/16231)
- TypeScript
- 🐞 Fix typescript `hoist-non-react-statics` has no default export warning with `allowSyntheticDefaultImports: false`. [#16224](https://github.com/ant-design/ant-design/pull/16224)
## 3.16.4
`2019-04-21`

View File

@ -15,6 +15,15 @@ timeline: true
---
## 3.16.5
`2019-04-22`
- 🐞 修复 Firefox 中 Table 使用 sorter 丢失线框的样式问题。[#16174](https://github.com/ant-design/ant-design/pull/16174)
- 🐞 修复 List 中设置 `pagination``null` 时报错的问题。[#16231](https://github.com/ant-design/ant-design/pull/16231)
- TypeScript
- 🐞 修复 `allowSyntheticDefaultImports: false``hoist-non-react-statics` 报错的问题。[#16224](https://github.com/ant-design/ant-design/pull/16224)
## 3.16.4
`2019-04-21`

View File

@ -0,0 +1,7 @@
import * as React from 'react';
export function cloneElement(element: React.ReactNode, ...restArgs: any[]) {
if (!React.isValidElement(element)) return element;
return React.cloneElement(element, ...restArgs);
}

View File

@ -7,7 +7,13 @@ import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationF
import ResizeObserver from '../_util/resizeObserver';
import warning from '../_util/warning';
import { addObserveTarget, removeObserveTarget, getTargetRect } from './utils';
import {
addObserveTarget,
removeObserveTarget,
getTargetRect,
getFixedTop,
getFixedBottom,
} from './utils';
function getDefaultTarget() {
return typeof window !== 'undefined' ? window : null;
@ -109,6 +115,27 @@ class Affix extends React.Component<AffixProps, AffixState> {
(this.updatePosition as any).cancel();
}
getOffsetTop = () => {
const { offset, offsetBottom } = this.props;
let { offsetTop } = this.props;
if (typeof offsetTop === 'undefined') {
offsetTop = offset;
warning(
typeof offset === 'undefined',
'Affix',
'`offset` is deprecated. Please use `offsetTop` instead.',
);
}
if (offsetBottom === undefined && offsetTop === undefined) {
offsetTop = 0;
}
return offsetTop;
};
getOffsetBottom = () => {
return this.props.offsetBottom;
};
savePlaceholderNode = (node: HTMLDivElement) => {
this.placeholderNode = node;
};
@ -120,8 +147,42 @@ class Affix extends React.Component<AffixProps, AffixState> {
// =================== Measure ===================
// Handle realign logic
@throttleByAnimationFrameDecorator()
updatePosition(event?: Event | null) {
this.prepareMeasure(event);
}
@throttleByAnimationFrameDecorator()
lazyUpdatePosition(event: Event) {
const { target } = this.props;
const { affixStyle } = this.state;
// Check position change before measure to make Safari smooth
if (target && affixStyle) {
const offsetTop = this.getOffsetTop();
const offsetBottom = this.getOffsetBottom();
const targetNode = target();
if (targetNode) {
const targetRect = getTargetRect(targetNode);
const placeholderReact = getTargetRect(this.placeholderNode);
const fixedTop = getFixedTop(placeholderReact, targetRect, offsetTop);
const fixedBottom = getFixedBottom(placeholderReact, targetRect, offsetBottom);
if (
(fixedTop !== undefined && affixStyle.top === fixedTop) ||
(fixedBottom !== undefined && affixStyle.bottom === fixedBottom)
) {
return;
}
}
}
// Directly call prepare measure since it's already throttled.
this.prepareMeasure(event);
}
// @ts-ignore TS6133
updatePosition(e?: Event) {
prepareMeasure = (event?: Event | null) => {
// event param is used before. Keep compatible ts define here.
this.setState({
status: AffixStatus.Prepare,
@ -136,28 +197,17 @@ class Affix extends React.Component<AffixProps, AffixState> {
onTestUpdatePosition();
}
}
}
};
measure = () => {
const { status, lastAffix } = this.state;
const { target, offset, offsetBottom, onChange } = this.props;
const { target, onChange } = this.props;
if (status !== AffixStatus.Prepare || !this.fixedNode || !this.placeholderNode || !target) {
return;
}
let { offsetTop } = this.props;
if (typeof offsetTop === 'undefined') {
offsetTop = offset;
warning(
typeof offset === 'undefined',
'Affix',
'`offset` is deprecated. Please use `offsetTop` instead.',
);
}
if (offsetBottom === undefined && offsetTop === undefined) {
offsetTop = 0;
}
const offsetTop = this.getOffsetTop();
const offsetBottom = this.getOffsetBottom();
const targetNode = target();
if (!targetNode) {
@ -169,11 +219,13 @@ class Affix extends React.Component<AffixProps, AffixState> {
};
const targetRect = getTargetRect(targetNode);
const placeholderReact = getTargetRect(this.placeholderNode);
const fixedTop = getFixedTop(placeholderReact, targetRect, offsetTop);
const fixedBottom = getFixedBottom(placeholderReact, targetRect, offsetBottom);
if (offsetTop !== undefined && targetRect.top > placeholderReact.top - offsetTop) {
if (fixedTop !== undefined) {
newState.affixStyle = {
position: 'fixed',
top: offsetTop + targetRect.top,
top: fixedTop,
width: placeholderReact.width,
height: placeholderReact.height,
};
@ -181,14 +233,10 @@ class Affix extends React.Component<AffixProps, AffixState> {
width: placeholderReact.width,
height: placeholderReact.height,
};
} else if (
offsetBottom !== undefined &&
targetRect.bottom < placeholderReact.bottom + offsetBottom
) {
const targetBottomOffset = targetNode === window ? 0 : window.innerHeight - targetRect.bottom;
} else if (fixedBottom !== undefined) {
newState.affixStyle = {
position: 'fixed',
bottom: offsetBottom + targetBottomOffset,
bottom: fixedBottom,
width: placeholderReact.width,
height: placeholderReact.height,
};

View File

@ -1,6 +1,33 @@
import addEventListener from 'rc-util/lib/Dom/addEventListener';
import Affix from './';
export type BindElement = HTMLElement | Window | null | undefined;
export type Rect = ClientRect | DOMRect;
export function getTargetRect(target: BindElement): ClientRect {
return target !== window
? (target as HTMLElement).getBoundingClientRect()
: ({ top: 0, bottom: window.innerHeight } as ClientRect);
}
export function getFixedTop(placeholderReact: Rect, targetRect: Rect, offsetTop: number | undefined) {
if (offsetTop !== undefined && targetRect.top > placeholderReact.top - offsetTop) {
return offsetTop + targetRect.top;
}
return undefined;
}
export function getFixedBottom(placeholderReact: Rect, targetRect: Rect, offsetBottom: number | undefined) {
if (
offsetBottom !== undefined &&
targetRect.bottom < placeholderReact.bottom + offsetBottom
) {
const targetBottomOffset = window.innerHeight - targetRect.bottom;
return offsetBottom + targetBottomOffset;
}
return undefined;
}
// ======================== Observer ========================
const TRIGGER_EVENTS = [
'resize',
@ -44,7 +71,7 @@ export function addObserveTarget(target: HTMLElement | Window | null, affix: Aff
TRIGGER_EVENTS.forEach(eventName => {
entity!.eventHandlers[eventName] = addEventListener(target, eventName, (event: Event) => {
entity!.affixList.forEach(affix => {
affix.updatePosition(event);
affix.lazyUpdatePosition(event);
});
});
});
@ -72,9 +99,3 @@ export function removeObserveTarget(affix: Affix): void {
});
}
}
export function getTargetRect(target: HTMLElement | Window | null): ClientRect {
return target !== window
? (target as HTMLElement).getBoundingClientRect()
: ({ top: 0, bottom: window.innerHeight } as ClientRect);
}

View File

@ -186,7 +186,7 @@ export type WrappedFormUtils<V = any> = {
): (node: React.ReactNode) => React.ReactNode;
};
export interface FormComponentProps<V = any> {
export interface WrappedFormInternalProps<V = any> {
form: WrappedFormUtils<V>;
}
@ -194,6 +194,10 @@ export interface RcBaseFormProps {
wrappedComponentRef?: any;
}
export interface FormComponentProps<V = any> extends WrappedFormInternalProps<V>, RcBaseFormProps {
form: WrappedFormUtils<V>;
}
export default class Form extends React.Component<FormProps, any> {
static defaultProps = {
colon: true,

View File

@ -59,3 +59,33 @@ const formOptions: FormCreateOption<WithCreateOptionsProps> = { mapPropsToFields
const WithCreateOptionsForm = Form.create(formOptions)(WithCreateOptions);
<WithCreateOptionsForm username="foo" />;
// Should work with forwardRef & wrappedComponentRef
// https://github.com/ant-design/ant-design/issues/16229
if (React.forwardRef) {
interface ForwardProps extends FormComponentProps {
str: string;
}
const ForwardDemo = React.forwardRef(({ str }: ForwardProps, ref: React.Ref<HTMLDivElement>) => {
return <div ref={ref}>{str || ''}</div>;
});
const WrappedForwardDemo = Form.create<ForwardProps>()(ForwardDemo);
<WrappedForwardDemo str="" />;
}
interface WrappedRefProps extends FormComponentProps {
str: string;
test?: () => void;
}
class WrapRefDemo extends React.Component<WrappedRefProps> {
public getForm() {
return this.props.form;
}
public render() {
return <div>{this.props.str || ''}</div>;
}
}
const WrappedWrapRefDemo = Form.create<WrappedRefProps>()(WrapRefDemo);
<WrappedWrapRefDemo str="" wrappedComponentRef={() => null} />;

View File

@ -1,9 +1,19 @@
import * as React from 'react';
import hoistNonReactStatics from 'hoist-non-react-statics';
import * as hoistNonReactStatics from 'hoist-non-react-statics';
import { Omit } from '../_util/type';
import { FormComponentProps } from './Form';
import { WrappedFormInternalProps } from './Form';
// Copy from @types/react-redux https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-redux/index.d.ts
export type Matching<InjectedProps, DecorationTargetProps> = {
[P in keyof DecorationTargetProps]: P extends keyof InjectedProps
? InjectedProps[P] extends DecorationTargetProps[P]
? DecorationTargetProps[P]
: InjectedProps[P]
: DecorationTargetProps[P];
};
export type GetProps<C> = C extends React.ComponentType<infer P> ? P : never;
export type ConnectedComponentClass<
C extends React.ComponentType<any>,
P
@ -11,8 +21,8 @@ export type ConnectedComponentClass<
WrappedComponent: C;
};
export type FormWrappedProps<TOwnProps extends FormComponentProps> =
export type FormWrappedProps<TOwnProps extends WrappedFormInternalProps> =
<
C extends React.ComponentType
C extends React.ComponentType<Matching<TOwnProps, GetProps<C>>>
>(component: C)
=> ConnectedComponentClass<C, Omit<TOwnProps, keyof FormComponentProps>>;
=> ConnectedComponentClass<C, Omit<TOwnProps, keyof WrappedFormInternalProps>>;

View File

@ -12,7 +12,7 @@ When a numeric value needs to be provided.
## API
| property | description | type | default |
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| autoFocus | get focus when component mounted | boolean | false |
| defaultValue | initial value | number | |

View File

@ -4,6 +4,7 @@ import classNames from 'classnames';
import { ListGridType, ColumnType } from './index';
import { Col } from '../grid';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import { cloneElement } from '../_util/reactNode';
export interface ListItemProps extends React.HTMLAttributes<HTMLDivElement> {
className?: string;
@ -130,11 +131,7 @@ export default class Item extends React.Component<ListItemProps, any> {
{extra}
</div>,
]
: [
children,
actionsContent,
extra ? React.cloneElement(extra as React.ReactElement<any>, { key: 'extra' }) : null,
]}
: [children, actionsContent, cloneElement(extra, { key: 'extra' })]}
</Tag>
);

View File

@ -195,4 +195,12 @@ describe('List.pagination', () => {
.render(),
).toMatchSnapshot();
});
it('should not crash when pagination is null', () => {
mount(
createList({
pagination: null,
}),
);
});
});

View File

@ -93,7 +93,7 @@ export default class List<T> extends React.Component<ListProps<T>, ListState> {
super(props);
const { pagination } = props;
const paginationObj = typeof pagination === 'object' ? pagination : {};
const paginationObj = pagination && typeof pagination === 'object' ? pagination : {};
this.state = {
paginationCurrent: paginationObj.defaultCurrent || 1,

View File

@ -42,78 +42,74 @@
margin: 0;
padding: 0;
list-style: none;
}
.@{list-prefix-cls}-item {
&-item {
display: flex;
align-items: center;
padding: @list-item-padding;
&-content {
color: @text-color;
}
&-meta {
display: flex;
align-items: center;
padding: @list-item-padding;
&-no-flex {
display: block;
flex: 1;
align-items: flex-start;
font-size: 0;
&-avatar {
margin-right: @list-item-meta-avatar-margin-right;
}
&-content {
color: @text-color;
flex: 1 0;
}
&-meta {
display: flex;
flex: 1;
align-items: flex-start;
font-size: 0;
&-avatar {
margin-right: @list-item-meta-avatar-margin-right;
}
&-content {
flex: 1 0;
}
&-title {
margin-bottom: 4px;
&-title {
margin-bottom: 4px;
color: @text-color;
font-size: @font-size-base;
line-height: 22px;
> a {
color: @text-color;
font-size: @font-size-base;
line-height: 22px;
> a {
color: @text-color;
transition: all 0.3s;
&:hover {
color: @primary-color;
}
transition: all 0.3s;
&:hover {
color: @primary-color;
}
}
&-description {
color: @text-color-secondary;
font-size: @font-size-base;
line-height: 22px;
}
}
&-action {
flex: 0 0 auto;
margin-left: 48px;
padding: 0;
font-size: 0;
list-style: none;
& > li {
position: relative;
display: inline-block;
padding: 0 8px;
color: @text-color-secondary;
font-size: @font-size-base;
line-height: 22px;
text-align: center;
cursor: pointer;
}
& > li:first-child {
padding-left: 0;
}
&-split {
position: absolute;
top: 50%;
right: 0;
width: 1px;
height: 14px;
margin-top: -7px;
background-color: @border-color-split;
}
&-description {
color: @text-color-secondary;
font-size: @font-size-base;
line-height: 22px;
}
}
&-action {
flex: 0 0 auto;
margin-left: 48px;
padding: 0;
font-size: 0;
list-style: none;
& > li {
position: relative;
display: inline-block;
padding: 0 8px;
color: @text-color-secondary;
font-size: @font-size-base;
line-height: 22px;
text-align: center;
cursor: pointer;
}
& > li:first-child {
padding-left: 0;
}
&-split {
position: absolute;
top: 50%;
right: 0;
width: 1px;
height: 14px;
margin-top: -7px;
background-color: @border-color-split;
}
}
}
@ -212,6 +208,20 @@
padding-bottom: 0;
border-bottom: none;
}
// ============================ without flex ============================
&-item-no-flex {
display: block;
}
// Horizontal
&:not(.@{list-prefix-cls}-vertical) {
.@{list-prefix-cls}-item-no-flex {
.@{list-prefix-cls}-item-action {
float: right;
}
}
}
}
@import './bordered';

View File

@ -109716,7 +109716,7 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-pagination-item-link"
>
<i
aria-label="icon: left"
aria-label="icona: left"
class="anticon anticon-left"
>
<svg
@ -109791,7 +109791,7 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-pagination-item-link"
>
<i
aria-label="icon: right"
aria-label="icona: right"
class="anticon anticon-right"
>
<svg
@ -109844,7 +109844,7 @@ exports[`Locale Provider should display the text as it 1`] = `
unselectable="on"
>
<i
aria-label="icon: down"
aria-label="icona: down"
class="anticon anticon-down ant-select-arrow-icon"
>
<svg
@ -109910,7 +109910,7 @@ exports[`Locale Provider should display the text as it 1`] = `
unselectable="on"
>
<i
aria-label="icon: down"
aria-label="icona: down"
class="anticon anticon-down ant-select-arrow-icon"
>
<svg
@ -109944,7 +109944,7 @@ exports[`Locale Provider should display the text as it 1`] = `
value=""
/>
<i
aria-label="icon: calendar"
aria-label="icona: calendar"
class="anticon anticon-calendar ant-calendar-picker-icon"
>
<svg
@ -110753,7 +110753,7 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-time-picker-icon"
>
<i
aria-label="icon: clock-circle"
aria-label="icona: clock-circle"
class="anticon anticon-clock-circle ant-time-picker-clock-icon"
>
<svg
@ -111711,7 +111711,7 @@ exports[`Locale Provider should display the text as it 1`] = `
value=""
/>
<i
aria-label="icon: calendar"
aria-label="icona: calendar"
class="anticon anticon-calendar ant-calendar-picker-icon"
>
<svg
@ -113246,7 +113246,7 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-popover-message"
>
<i
aria-label="icon: exclamation-circle"
aria-label="icona: exclamation-circle"
class="anticon anticon-exclamation-circle"
>
<svg
@ -113325,7 +113325,7 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-transfer-list-header-selected"
>
<span>
0 articolo
0 elemento
</span>
<span
class="ant-transfer-list-header-title"
@ -113349,7 +113349,7 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-transfer-list-search-action"
>
<i
aria-label="icon: search"
aria-label="icona: search"
class="anticon anticon-search"
>
<svg
@ -113402,7 +113402,7 @@ exports[`Locale Provider should display the text as it 1`] = `
type="button"
>
<i
aria-label="icon: right"
aria-label="icona: right"
class="anticon anticon-right"
>
<svg
@ -113427,7 +113427,7 @@ exports[`Locale Provider should display the text as it 1`] = `
type="button"
>
<i
aria-label="icon: left"
aria-label="icona: left"
class="anticon anticon-left"
>
<svg
@ -113473,7 +113473,7 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-transfer-list-header-selected"
>
<span>
0 articolo
0 elemento
</span>
<span
class="ant-transfer-list-header-title"
@ -113497,7 +113497,7 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-transfer-list-search-action"
>
<i
aria-label="icon: search"
aria-label="icona: search"
class="anticon anticon-search"
>
<svg
@ -113578,7 +113578,7 @@ exports[`Locale Provider should display the text as it 1`] = `
unselectable="on"
>
<i
aria-label="icon: down"
aria-label="icona: down"
class="anticon anticon-down ant-select-arrow-icon"
>
<svg
@ -113629,7 +113629,7 @@ exports[`Locale Provider should display the text as it 1`] = `
unselectable="on"
>
<i
aria-label="icon: down"
aria-label="icona: down"
class="anticon anticon-down ant-select-arrow-icon"
>
<svg
@ -114630,7 +114630,7 @@ exports[`Locale Provider should display the text as it 1`] = `
</div>
</span>
<i
aria-label="icon: filter"
aria-label="icona: filter"
class="anticon anticon-filter ant-dropdown-trigger"
tabindex="-1"
title="Menù Filtro"
@ -114734,7 +114734,7 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-modal-close-x"
>
<i
aria-label="icon: close"
aria-label="icona: close"
class="anticon anticon-close ant-modal-close-icon"
>
<svg

View File

@ -9,6 +9,9 @@ export default {
DatePicker,
TimePicker,
Calendar,
global: {
placeholder: 'Selezionare',
},
Table: {
filterTitle: 'Menù Filtro',
filterConfirm: 'OK',
@ -28,7 +31,7 @@ export default {
},
Transfer: {
searchPlaceholder: 'Cerca qui',
itemUnit: 'articolo',
itemUnit: 'elemento',
itemsUnit: 'elementi',
},
Upload: {
@ -40,4 +43,13 @@ export default {
Empty: {
description: 'Nessun dato',
},
Icon: {
icon: 'icona',
},
Text: {
edit: 'modifica',
copy: 'copia',
copied: 'copia effettuata',
expand: 'espandi',
},
};

View File

@ -30,6 +30,7 @@
font-weight: 500;
font-size: @font-size-lg;
line-height: 22px;
word-wrap: break-word;
}
&-content {

View File

@ -18,27 +18,32 @@ import { Select } from 'antd';
const Option = Select.Option;
function handleChange(value) {
function onChange(value) {
console.log(`selected ${value}`);
}
function handleBlur() {
function onBlur() {
console.log('blur');
}
function handleFocus() {
function onFocus() {
console.log('focus');
}
function onSearch(val) {
console.log('search:', val);
}
ReactDOM.render(
<Select
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
onChange={handleChange}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
onSearch={onSearch}
filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
>
<Option value="jack">Jack</Option>

View File

@ -528,12 +528,9 @@
}
&-selected {
&,
&:hover {
color: @text-color;
font-weight: @select-item-selected-font-weight;
background-color: @background-color-light;
}
color: @text-color;
font-weight: @select-item-selected-font-weight;
background-color: @background-color-light;
}
&-active {

View File

@ -47,8 +47,8 @@
box-shadow: 0 2px 4px 0 @switch-shadow-color;
}
&:active::before,
&:active::after {
&:not(&-disabled):active::before,
&:not(&-disabled):active::after {
width: 24px;
}

View File

@ -74,7 +74,7 @@
> .@{table-prefix-cls}-tbody > tr > td {
padding: @table-padding-vertical-sm @table-padding-horizontal-sm;
}
> .@{table-prefix-cls}-thead > tr > th {
> .@{table-prefix-cls}-thead > tr {
background-color: transparent;
border-bottom: @border-width-base @border-style-base @border-color-split;
}

View File

@ -146,6 +146,7 @@
// https://github.com/ant-design/ant-design/issues/9104
& &-card-bar&-bottom-bar &-tab {
height: auto;
border-top: 0;
border-bottom: @border-width-base @border-style-base @border-color-split;
border-radius: 0 0 @border-radius-base @border-radius-base;

View File

@ -11,6 +11,15 @@
.antCheckboxFn(@checkbox-prefix-cls: ~'@{ant-prefix}-tree-checkbox');
.@{tree-prefix-cls} {
/* see https://github.com/ant-design/ant-design/issues/16259 */
&-checkbox-checked::after {
position: absolute;
top: 16.67%;
left: 0;
width: 100%;
height: 66.67%;
}
.reset-component;
margin: 0;

View File

@ -51,19 +51,19 @@
.@{typography-prefix-cls} {
color: @text-color;
&-secondary {
&&-secondary {
color: @text-color-secondary;
}
&-warning {
&&-warning {
color: @text-color-warning;
}
&-danger {
&&-danger {
color: @text-color-danger;
}
&-disabled {
&&-disabled {
color: @disabled-color;
cursor: not-allowed;
user-select: none;

View File

@ -28,6 +28,8 @@ Before you reporting a bug, please make sure you've searched exists issues, and
If you intend to change the public API or introduce new feature, we also recommend use our [issue helper](http://new-issue.ant.design) to create a feature request issue.
If you want to help on new API, please ref [API Naming Rules](https://github.com/ant-design/ant-design/wiki/API-Naming-rules) to name it.
## Your First Pull Request
Working on your first Pull Request? You can learn how from this free video series:

View File

@ -28,6 +28,8 @@ toc: false
如果你有改进我们的 API 或者新增功能的想法,我们同样推荐你使用我们提供的 [issue 小助手](http://new-issue.ant.design) 来新建一个添加新功能的 issue。
如果你希望协助开发新的 API请参考 [API 规范](https://github.com/ant-design/ant-design/wiki/API-Naming-rules) 进行命名。
## 第一次贡献
如果你还不清楚怎么在 GitHub 上提 Pull Request ,可以阅读下面这篇文章来学习:

View File

@ -1,6 +1,6 @@
{
"name": "antd",
"version": "3.16.4",
"version": "3.16.5",
"title": "Ant Design",
"description": "An enterprise-class UI design language and React-based implementation",
"homepage": "http://ant.design/",
@ -76,7 +76,7 @@
"rc-pagination": "~1.17.7",
"rc-progress": "~2.3.0",
"rc-rate": "~2.5.0",
"rc-select": "~9.0.0",
"rc-select": "~9.1.0",
"rc-slider": "~8.6.5",
"rc-steps": "~3.3.0",
"rc-switch": "~1.9.0",
@ -141,7 +141,7 @@
"immutability-helper": "^3.0.0",
"intersection-observer": "^0.5.0",
"jest": "^24.0.0",
"jsdom": "^14.0.0",
"jsdom": "^15.0.0",
"jsonml.js": "^0.1.0",
"lint-staged": "^8.0.2",
"logrocket": "^0.6.19",
@ -189,7 +189,7 @@
"stylelint-config-prettier": "^5.0.0",
"stylelint-config-rational-order": "^0.1.0",
"stylelint-config-standard": "^18.2.0",
"stylelint-declaration-block-no-ignored-properties": "^1.1.0",
"stylelint-declaration-block-no-ignored-properties": "^2.0.0",
"stylelint-order": "^3.0.0",
"typescript": "~3.4.1",
"unified": "^7.0.0",

63
scripts/apiCollection.js Normal file
View File

@ -0,0 +1,63 @@
// Read all the api from current documents
const glob = require('glob');
const fs = require('fs');
const COMPONENT_NAME = /components\/([^/]*)/;
const PROP_NAME = /^\s*\|\s*([^\s|]*)/;
const components = {};
function mappingPropLine(component, line) {
const propMatch = line.match(PROP_NAME);
if (!propMatch) return;
const propName = propMatch[1];
if (!/^[a-z]/.test(propName)) return;
components[component] = Array.from(new Set([...(components[component] || []), propName]));
}
function apiReport(entities) {
const apis = {};
Object.keys(entities).forEach(component => {
const apiList = entities[component];
apiList.forEach(api => {
if (typeof apis[api] === 'function') {
apis[api] = [];
}
apis[api] = [...(apis[api] || []), component];
});
});
return apis;
}
function printReport(apis) {
const apiList = Object.keys(apis).map(api => ({
name: api,
componentList: apis[api],
}));
apiList.sort((a, b) => b.componentList.length - a.componentList.length);
console.log('| name | components | comments |');
console.log('| ---- | ---------- | -------- |');
apiList.forEach(({ name, componentList }) => {
console.log('|', name, '|', componentList.join(', '), '| |');
});
}
glob('components/*/*.md', (error, files) => {
files.forEach(filePath => {
// Read md file to parse content
const content = fs.readFileSync(filePath, 'utf8');
const component = filePath.match(COMPONENT_NAME)[1];
// Parse lines to get API
const lines = content.split(/[\r\n]+/);
lines.forEach(line => {
mappingPropLine(component, line);
});
});
printReport(apiReport(components));
});