Browse Source

Merge branch 'master' into feature

pull/16837/head
诸岳 6 years ago
parent
commit
7a728daca9
  1. 6
      .github/PULL_REQUEST_TEMPLATE.md
  2. 5
      .github/PULL_REQUEST_TEMPLATE/pr_cn.md
  3. 17
      CHANGELOG.en-US.md
  4. 17
      CHANGELOG.zh-CN.md
  5. 2
      components/breadcrumb/Breadcrumb.tsx
  6. 2
      components/breadcrumb/index.zh-CN.md
  7. 11
      components/button/__tests__/__snapshots__/index.test.js.snap
  8. 11
      components/button/__tests__/index.test.js
  9. 27
      components/button/button.tsx
  10. 9
      components/carousel/__tests__/index.test.js
  11. 7
      components/carousel/index.tsx
  12. 4
      components/cascader/style/index.less
  13. 2
      components/drawer/style/drawer.less
  14. 2
      components/form/Form.tsx
  15. 11
      components/form/index.en-US.md
  16. 11
      components/form/index.zh-CN.md
  17. 2
      components/form/style/index.less
  18. 5
      components/input/__tests__/__snapshots__/demo.test.js.snap
  19. 8
      components/list/index.tsx
  20. 12
      components/pagination/style/index.less
  21. 2
      components/select/index.zh-CN.md
  22. 4
      components/spin/style/index.less
  23. 2
      components/style/color/colorPalette.less
  24. 15
      components/table/Table.tsx
  25. 32
      components/table/__tests__/Table.rowSelection.test.js
  26. 80
      components/table/__tests__/__snapshots__/demo.test.js.snap
  27. 75
      components/table/demo/edit-cell.md
  28. 105
      components/table/demo/edit-row.md
  29. 11
      components/tree/Tree.tsx
  30. 2
      docs/react/use-in-typescript.en-US.md
  31. 6
      docs/react/use-in-typescript.zh-CN.md
  32. 4
      package.json
  33. 10
      site/theme/template/Content/Article.jsx
  34. 10
      site/theme/template/Content/ComponentDoc.jsx
  35. 33
      site/theme/template/Content/MainContent.jsx
  36. 374
      site/theme/template/IconDisplay/fields.ts
  37. 40
      site/theme/template/IconDisplay/index.tsx

6
.github/PULL_REQUEST_TEMPLATE.md

@ -43,8 +43,10 @@ Please makes sure that these form are filled before submitting your pull request
Describe changes from userside, and list all potential break changes or other risks.
--->
- English Changelog:
- Chinese Changelog (optional):
| Language | Changelog |
| ---------- | --------- |
| 🇺🇸 English | |
| 🇨🇳 Chinese | |
### ☑️ Self Check before Merge

5
.github/PULL_REQUEST_TEMPLATE/pr_cn.md

@ -43,7 +43,10 @@
> 从用户角度描述具体变化,以及可能的 breaking change 和其他风险?
-->
- 英文:
| 语言 | 更新描述 |
| ------- | -------- |
| 🇺🇸 英文 | |
| 🇨🇳 中文 | |
- 中文(可选):

17
CHANGELOG.en-US.md

@ -15,6 +15,23 @@ timeline: true
---
## 3.18.2
`2019-05-20`
- 🐞 Fix space missing for Button with mixed content. [#15342](https://github.com/ant-design/ant-design/issues/15342)
- 🐞 Fix active status missing for Carousel when `children` is changed. [#16583](https://github.com/ant-design/ant-design/issues/16583)
- 🐞 Fix panel not close when DatePicker is `blur` by upgrading `rc-calendar` requirement to version `9.13.3`. [#16588](https://github.com/ant-design/ant-design/issues/16588)
- 🐞 Fix style disorder for Form.Item with `help` prop and `margin-bottom` is negative. [#16584](https://github.com/ant-design/ant-design/pull/16584) [@sbusch](https://github.com/sbusch)
- 🐞 Fix Spin not align when set `font-size` style. [#15206](https://github.com/ant-design/ant-design/issues/15206)
- 🐞 Fix `selectedRows` missing when there is `childrenColumnName` in Table. [#16614](https://github.com/ant-design/ant-design/issues/16614)
- TypeScript
- ⚡️ Improve the definition of `children` prop for Breadcrumb. [#16550](https://github.com/ant-design/ant-design/pull/16550) [@Gin-X](https://github.com/Gin-X)
- ⚡️ Improve the definition of `onFieldsChange` params for Form. [#16577](https://github.com/ant-design/ant-design/pull/16577) [@SylvanasGone](https://github.com/SylvanasGone)
- ⚡️ Improve the definition of `dataSource` and `renderItem` for List. [#16587](https://github.com/ant-design/ant-design/issues/16587)
- ⚡️ Improve the definition of `onDragEnter` params for Tree. [#16638](https://github.com/ant-design/ant-design/pull/16638) [@eruca](https://github.com/eruca)
- ⚡️ Improve the definition of `event` for Tree。[#16624](https://github.com/ant-design/ant-design/pull/16624) [@ztplz](https://github.com/ztplz)
## 3.18.1
`2019-05-13`

17
CHANGELOG.zh-CN.md

@ -15,6 +15,23 @@ timeline: true
---
## 3.18.2
`2019-05-20`
- 🐞 修复 Button 组件中插入文本时空格丢失的问题。[#15342](https://github.com/ant-design/ant-design/issues/15342)
- 🐞 修复 Carousel 组件的 `children` 数量变化时,面板指示点的选中状态不正常的问题。[#16583](https://github.com/ant-design/ant-design/issues/16583)
- 🐞 升级 `rc-calendar` 依赖到 `9.13.3` 版本,以修复 DatePicker 组件在失去焦点时面板不会关闭的问题。[#16588](https://github.com/ant-design/ant-design/issues/16588)
- 🐞 修复 Form.Item 组件带有 `help` 信息,并且 `margin-bottom` 为负数时,导致之后的元素样式错乱的问题。[#16584](https://github.com/ant-design/ant-design/pull/16584) [@sbusch](https://github.com/sbusch)
- 🐞 修复 Spin 组件在设置 `font-size` 样式时没有水平居中的问题。[#15206](https://github.com/ant-design/ant-design/issues/15206)
- 🐞 修复 Table 组件指定 `childrenColumnName` 时,`selectedRows` 参数为空的问题。[#16614](https://github.com/ant-design/ant-design/issues/16614)
- TypeScript
- ⚡️ 完善 Breadcrumb 中 `children` 属性的定义。[#16550](https://github.com/ant-design/ant-design/pull/16550) [@Gin-X](https://github.com/Gin-X)
- ⚡️ 完善 Form 中 `onFieldsChange` 函数的参数定义。[#16577](https://github.com/ant-design/ant-design/pull/16577) [@SylvanasGone](https://github.com/SylvanasGone)
- ⚡️ 完善 List 中 `dataSource``renderItem` 属性的定义。[#16587](https://github.com/ant-design/ant-design/issues/16587)
- ⚡️ 完善 Tree 中 `onDragEnter` 函数的参数定义。[#16638](https://github.com/ant-design/ant-design/pull/16638) [@eruca](https://github.com/eruca)
- ⚡️ 完善 Tree 中 event 属性的定义。[#16624](https://github.com/ant-design/ant-design/pull/16624) [@ztplz](https://github.com/ztplz)
## 3.18.1
`2019-05-13`

2
components/breadcrumb/Breadcrumb.tsx

@ -11,7 +11,7 @@ import { Omit } from '../_util/type';
export interface Route {
path: string;
breadcrumbName: string;
children: Omit<Route, 'children'>[];
children?: Omit<Route, 'children'>[];
}
export interface BreadcrumbProps {

2
components/breadcrumb/index.zh-CN.md

@ -31,7 +31,7 @@ title: Breadcrumb
| href | 链接的目的地 | string | - |
| separator | 自定义的分隔符 | string\|ReactNode | '/' |
| overlay | 下来菜单的内容 | [Menu](/components/menu) \| () => Menu | - |
| onClick | 单击事件 | (e:MouseEventHandler)=>void | - |
| onClick | 单击事件 | (e:MouseEvent)=>void | - |
### routes

11
components/button/__tests__/__snapshots__/index.test.js.snap

@ -211,6 +211,17 @@ exports[`Button should has click wave effect 1`] = `
</button>
`;
exports[`Button should merge text if children using variable 1`] = `
<button
class="ant-btn"
type="button"
>
<span>
This is a test 1
</span>
</button>
`;
exports[`Button should not render as link button when href is undefined 1`] = `
<button
class="ant-btn ant-btn-primary"

11
components/button/__tests__/index.test.js

@ -157,4 +157,15 @@ describe('Button', () => {
);
expect(wrapper.render()).toMatchSnapshot();
});
// https://github.com/ant-design/ant-design/issues/15342
it('should merge text if children using variable', () => {
const wrapper = mount(
<Button>
This {'is'} a test {1}
</Button>,
);
expect(wrapper.render()).toMatchSnapshot();
});
});

27
components/button/button.tsx

@ -15,6 +15,29 @@ function isString(str: any) {
return typeof str === 'string';
}
function spaceChildren(children: React.ReactNode, needInserted: boolean) {
let isPrevChildPure: boolean = false;
const childList: React.ReactNode[] = [];
React.Children.forEach(children, child => {
const type = typeof child;
const isCurrentChildPure = type === 'string' || type === 'number';
if (isPrevChildPure && isCurrentChildPure) {
const lastIndex = childList.length - 1;
const lastChild = childList[lastIndex];
childList[lastIndex] = `${lastChild}${child}`;
} else {
childList.push(child);
}
isPrevChildPure = isCurrentChildPure;
});
// Pass to React.Children.map to auto fill key
return React.Children.map(childList, child =>
insertSpace(child as React.ReactChild, needInserted),
);
}
// Insert one space between two chinese characters automatically.
function insertSpace(child: React.ReactChild, needInserted: boolean) {
// Check the child if is undefined or null.
@ -243,9 +266,7 @@ class Button extends React.Component<ButtonProps, ButtonState> {
const iconNode = iconType ? <Icon type={iconType} /> : null;
const kids =
children || children === 0
? React.Children.map(children, child =>
insertSpace(child as React.ReactChild, this.isNeedInserted() && autoInsertSpace),
)
? spaceChildren(children, this.isNeedInserted() && autoInsertSpace)
: null;
const linkButtonRestProps = omit(rest as AnchorButtonProps, ['htmlType']);

9
components/carousel/__tests__/index.test.js

@ -105,4 +105,13 @@ describe('Carousel', () => {
);
warnSpy.mockRestore();
});
it('should active when children change', () => {
const wrapper = mount(<Carousel />);
wrapper.setProps({
children: <div />,
});
wrapper.update();
expect(wrapper.find('.slick-active').length).toBeTruthy();
});
});

7
components/carousel/index.tsx

@ -33,6 +33,7 @@ export interface CarouselProps extends Settings {
prefixCls?: string;
slickGoTo?: number;
dotPosition?: DotPosition;
children?: React.ReactNode;
}
export default class Carousel extends React.Component<CarouselProps, {}> {
@ -70,6 +71,12 @@ export default class Carousel extends React.Component<CarouselProps, {}> {
this.innerSlider = this.slick && this.slick.innerSlider;
}
componentDidUpdate(prevProps: CarouselProps) {
if (React.Children.count(this.props.children) !== React.Children.count(prevProps.children)) {
this.goTo(0, false);
}
}
componentWillUnmount() {
const { autoplay } = this.props;
if (autoplay) {

4
components/cascader/style/index.less

@ -195,8 +195,8 @@
&-active:not(&-disabled) {
&,
&:hover {
font-weight: 600;
background: @background-color-base;
font-weight: @select-item-selected-font-weight;
background-color: @background-color-light;
}
}
&-expand {

2
components/drawer/style/drawer.less

@ -187,6 +187,8 @@
&-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 0;
background-color: @modal-mask-bg;

2
components/form/Form.tsx

@ -20,7 +20,7 @@ interface FormCreateOptionMessages {
}
export interface FormCreateOption<T> {
onFieldsChange?: (props: T, fields: object, allFields: any) => void;
onFieldsChange?: (props: T, fields: any, allFields: any) => void;
onValuesChange?: (props: T, changedValues: any, allValues: any) => void;
mapPropsToFields?: (props: T) => void;
validateMessages?: FormCreateOptionMessages;

11
components/form/index.en-US.md

@ -225,7 +225,7 @@ See more advanced usage at [async-validator](https://github.com/yiminghe/async-v
## Using in TypeScript
```jsx
```tsx
import { Form } from 'antd';
import { FormComponentProps } from 'antd/lib/form';
@ -238,12 +238,9 @@ class UserForm extends React.Component<UserFormProps, any> {
// ...
}
const App =
Form.create <
UserFormProps >
{
// ...
}(UserForm);
const App = Form.create<UserFormProps>({
// ...
})(UserForm);
```
<style>

11
components/form/index.zh-CN.md

@ -227,7 +227,7 @@ validateFields(['field1', 'field2'], options, (errors, values) => {
## 在 TypeScript 中使用
```jsx
```tsx
import { Form } from 'antd';
import { FormComponentProps } from 'antd/lib/form';
@ -240,12 +240,9 @@ class UserForm extends React.Component<UserFormProps, any> {
// ...
}
const App =
Form.create <
UserFormProps >
{
// ...
}(UserForm);
const App = Form.create<UserFormProps>({
// ...
})(UserForm);
```
<style>

2
components/form/style/index.less

@ -113,7 +113,7 @@ input[type='checkbox'] {
}
&-with-help {
margin-bottom: @form-item-margin-bottom - @form-explain-height - @form-help-margin-top;
margin-bottom: max(0, @form-item-margin-bottom - @form-explain-height - @form-help-margin-top);
}
&-label {

5
components/input/__tests__/__snapshots__/demo.test.js.snap

@ -1198,10 +1198,7 @@ exports[`renders ./components/input/demo/textarea-resize.md correctly 1`] = `
type="button"
>
<span>
Auto Resize:
</span>
<span>
false
Auto Resize: false
</span>
</button>
<textarea

8
components/list/index.tsx

@ -36,7 +36,7 @@ export interface ListProps<T> {
className?: string;
style?: React.CSSProperties;
children?: React.ReactNode;
dataSource: T[];
dataSource?: T[];
extra?: React.ReactNode;
grid?: ListGridType;
id?: string;
@ -46,7 +46,7 @@ export interface ListProps<T> {
pagination?: PaginationConfig | false;
prefixCls?: string;
rowKey?: any;
renderItem: (item: T, index: number) => React.ReactNode;
renderItem?: (item: T, index: number) => React.ReactNode;
size?: ListSize;
split?: boolean;
header?: React.ReactNode;
@ -124,6 +124,8 @@ export default class List<T> extends React.Component<ListProps<T>, ListState> {
renderItem = (item: any, index: number) => {
const { renderItem, rowKey } = this.props;
if (!renderItem) return null;
let key;
if (typeof rowKey === 'function') {
@ -170,7 +172,7 @@ export default class List<T> extends React.Component<ListProps<T>, ListState> {
loadMore,
pagination,
grid,
dataSource,
dataSource = [],
size,
rowKey,
renderItem,

12
components/pagination/style/index.less

@ -334,20 +334,20 @@
cursor: not-allowed;
.@{pagination-prefix-cls}-item {
cursor: not-allowed;
border-color: @border-color-base;
background: @disabled-bg;
border-color: @border-color-base;
cursor: not-allowed;
a {
cursor: not-allowed;
color: @disabled-color;
background: transparent;
border: none;
cursor: not-allowed;
}
&-active {
border-color: transparent;
background: darken(@disabled-bg, 10%);
border-color: transparent;
a {
color: #fff;
}
@ -358,10 +358,10 @@
&,
&:hover,
&:focus {
border-color: @border-color-base;
color: @text-color-secondary;
cursor: not-allowed;
background: @disabled-bg;
border-color: @border-color-base;
cursor: not-allowed;
}
}

2
components/select/index.zh-CN.md

@ -55,7 +55,7 @@ title: Select
| menuItemSelectedIcon | 自定义当前选中的条目图标 | ReactNode | - |
| tokenSeparators | 在 tags 和 multiple 模式下自动分词的分隔符 | string\[] | |
| value | 指定当前选中的条目 | string\|string\[]\<br />number\|number\[]\<br />LabeledValue\|LabeledValue[] | - |
| onBlur | 失去焦点时回调 | function | - |
| onBlur | 失去焦点时回调 | function | - |
| onChange | 选中 option,或 input 的 value 变化(combobox 模式下)时,调用此函数 | function(value, option:Option/Array&lt;Option>) | - |
| onDeselect | 取消选中时调用,参数为选中项的 value (或 key) 值,仅在 multiple 或 tags 模式下生效 | function(string\|number\|LabeledValue) | - |
| onFocus | 获得焦点时回调 | function | - |

4
components/spin/style/index.less

@ -124,7 +124,7 @@
display: inline-block;
font-size: @spin-dot-size;
.square(@spin-dot-size);
.square(1em);
&-item {
position: absolute;
@ -172,7 +172,6 @@
&-sm &-dot {
font-size: @spin-dot-size-sm;
.square(@spin-dot-size-sm);
i {
width: 6px;
height: 6px;
@ -183,7 +182,6 @@
&-lg &-dot {
font-size: @spin-dot-size-lg;
.square(@spin-dot-size-lg);
i {
width: 14px;
height: 14px;

2
components/style/color/colorPalette.less

@ -34,7 +34,7 @@
var saturation;
if (isLight) {
saturation = Math.round(hsv.s * 100) - saturationStep * i;
} else if (i == darkColorCount) {
} else if (i === darkColorCount) {
saturation = Math.round(hsv.s * 100) + saturationStep;
} else {
saturation = Math.round(hsv.s * 100) + saturationStep2 * i;

15
components/table/Table.tsx

@ -97,6 +97,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
rowKey: 'key',
showHeader: true,
sortDirections: ['ascend', 'descend'],
childrenColumnName: 'children',
};
CheckboxPropsCache: {
@ -524,7 +525,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
let selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
const key = this.getRecordKey(record, rowIndex);
const { pivot } = this.state;
const rows = this.getFlatCurrentPageData(this.props.childrenColumnName);
const rows = this.getFlatCurrentPageData();
let realIndex = rowIndex;
if (this.props.expandedRowRender) {
realIndex = rows.findIndex(row => this.getRecordKey(row, rowIndex) === key);
@ -604,7 +605,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
};
handleSelectRow = (selectionKey: string, index: number, onSelectFunc: SelectionItemSelectFn) => {
const data = this.getFlatCurrentPageData(this.props.childrenColumnName);
const data = this.getFlatCurrentPageData();
const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection();
const selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
const changeableRowKeys = data
@ -760,10 +761,10 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
};
renderRowSelection(prefixCls: string, locale: TableLocale) {
const { rowSelection, childrenColumnName } = this.props;
const { rowSelection } = this.props;
const columns = this.columns.concat();
if (rowSelection) {
const data = this.getFlatCurrentPageData(childrenColumnName).filter((item, index) => {
const data = this.getFlatCurrentPageData().filter((item, index) => {
if (rowSelection.getCheckboxProps) {
return !this.getCheckboxPropsByItem(item, index).disabled;
}
@ -1066,10 +1067,12 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
}
getFlatData() {
return flatArray(this.getLocalData(null, false));
const { childrenColumnName } = this.props;
return flatArray(this.getLocalData(null, false), childrenColumnName);
}
getFlatCurrentPageData(childrenColumnName: string | undefined) {
getFlatCurrentPageData() {
const { childrenColumnName } = this.props;
return flatArray(this.getCurrentPageData(), childrenColumnName);
}

32
components/table/__tests__/Table.rowSelection.test.js

@ -670,6 +670,38 @@ describe('Table.rowSelection', () => {
expect(checkboxAll.instance().state).toEqual({ indeterminate: false, checked: true });
});
// https://github.com/ant-design/ant-design/issues/16614
it('should get selectedRows correctly when set childrenColumnName', () => {
const onChange = jest.fn();
const newDatas = [
{
key: 1,
name: 'Jack',
list: [
{
key: 11,
name: 'John Brown',
},
],
},
];
const wrapper = mount(
<Table
columns={columns}
dataSource={newDatas}
childrenColumnName="list"
rowSelection={{ onChange }}
expandedRowKeys={[1]}
/>,
);
const checkboxes = wrapper.find('input');
checkboxes.at(2).simulate('change', { target: { checked: true } });
expect(onChange).toHaveBeenLastCalledWith([11], [newDatas[0].list[0]]);
checkboxes.at(1).simulate('change', { target: { checked: true } });
const item0 = { ...newDatas[0], list: undefined };
expect(onChange).toHaveBeenLastCalledWith([11, 1], [item0, newDatas[0].list[0]]);
});
it('clear selection className when remove `rowSelection`', () => {
const dataSource = [{ id: 1, name: 'Hello', age: 10 }, { id: 2, name: 'World', age: 30 }];

80
components/table/__tests__/__snapshots__/demo.test.js.snap

@ -4062,11 +4062,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class=""
>
<div>
<a>
Edit
</a>
</div>
<a>
Edit
</a>
</td>
</tr>
<tr
@ -4095,11 +4093,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class=""
>
<div>
<a>
Edit
</a>
</div>
<a>
Edit
</a>
</td>
</tr>
<tr
@ -4128,11 +4124,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class=""
>
<div>
<a>
Edit
</a>
</div>
<a>
Edit
</a>
</td>
</tr>
<tr
@ -4161,11 +4155,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class=""
>
<div>
<a>
Edit
</a>
</div>
<a>
Edit
</a>
</td>
</tr>
<tr
@ -4194,11 +4186,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class=""
>
<div>
<a>
Edit
</a>
</div>
<a>
Edit
</a>
</td>
</tr>
<tr
@ -4227,11 +4217,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class=""
>
<div>
<a>
Edit
</a>
</div>
<a>
Edit
</a>
</td>
</tr>
<tr
@ -4260,11 +4248,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class=""
>
<div>
<a>
Edit
</a>
</div>
<a>
Edit
</a>
</td>
</tr>
<tr
@ -4293,11 +4279,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class=""
>
<div>
<a>
Edit
</a>
</div>
<a>
Edit
</a>
</td>
</tr>
<tr
@ -4326,11 +4310,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class=""
>
<div>
<a>
Edit
</a>
</div>
<a>
Edit
</a>
</td>
</tr>
<tr
@ -4359,11 +4341,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class=""
>
<div>
<a>
Edit
</a>
</div>
<a>
Edit
</a>
</td>
</tr>
</tbody>

75
components/table/demo/edit-cell.md

@ -16,7 +16,6 @@ Table with editable cells.
```jsx
import { Table, Input, Button, Popconfirm, Form } from 'antd';
const FormItem = Form.Item;
const EditableContext = React.createContext();
const EditableRow = ({ form, index, ...props }) => (
@ -52,46 +51,50 @@ class EditableCell extends React.Component {
});
};
render() {
renderCell = form => {
this.form = form;
const { children, dataIndex, record, title } = this.props;
const { editing } = this.state;
const { editable, dataIndex, title, record, index, handleSave, ...restProps } = this.props;
return editing ? (
<Form.Item style={{ margin: 0 }}>
{form.getFieldDecorator(dataIndex, {
rules: [
{
required: true,
message: `${title} is required.`,
},
],
initialValue: record[dataIndex],
})(<Input ref={node => (this.input = node)} onPressEnter={this.save} onBlur={this.save} />)}
</Form.Item>
) : (
<div
className="editable-cell-value-wrap"
style={{ paddingRight: 24 }}
onClick={this.toggleEdit}
>
{children}
</div>
);
};
render() {
const {
editable,
dataIndex,
title,
record,
index,
handleSave,
children,
...restProps
} = this.props;
return (
<td {...restProps}>
{editable ? (
<EditableContext.Consumer>
{form => {
this.form = form;
return editing ? (
<FormItem style={{ margin: 0 }}>
{form.getFieldDecorator(dataIndex, {
rules: [
{
required: true,
message: `${title} is required.`,
},
],
initialValue: record[dataIndex],
})(
<Input
ref={node => (this.input = node)}
onPressEnter={this.save}
onBlur={this.save}
/>,
)}
</FormItem>
) : (
<div
className="editable-cell-value-wrap"
style={{ paddingRight: 24 }}
onClick={this.toggleEdit}
>
{restProps.children}
</div>
);
}}
</EditableContext.Consumer>
<EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
) : (
restProps.children
children
)}
</td>
);

105
components/table/demo/edit-row.md

@ -25,7 +25,6 @@ for (let i = 0; i < 100; i++) {
address: `London Park no. ${i}`,
});
}
const FormItem = Form.Item;
const EditableContext = React.createContext();
class EditableCell extends React.Component {
@ -36,34 +35,40 @@ class EditableCell extends React.Component {
return <Input />;
};
render() {
const { editing, dataIndex, title, inputType, record, index, ...restProps } = this.props;
renderCell = ({ getFieldDecorator }) => {
const {
editing,
dataIndex,
title,
inputType,
record,
index,
children,
...restProps
} = this.props;
return (
<EditableContext.Consumer>
{form => {
const { getFieldDecorator } = form;
return (
<td {...restProps}>
{editing ? (
<FormItem style={{ margin: 0 }}>
{getFieldDecorator(dataIndex, {
rules: [
{
required: true,
message: `Please Input ${title}!`,
},
],
initialValue: record[dataIndex],
})(this.getInput())}
</FormItem>
) : (
restProps.children
)}
</td>
);
}}
</EditableContext.Consumer>
<td {...restProps}>
{editing ? (
<Form.Item style={{ margin: 0 }}>
{getFieldDecorator(dataIndex, {
rules: [
{
required: true,
message: `Please Input ${title}!`,
},
],
initialValue: record[dataIndex],
})(this.getInput())}
</Form.Item>
) : (
children
)}
</td>
);
};
render() {
return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>;
}
}
@ -96,31 +101,27 @@ class EditableTable extends React.Component {
render: (text, record) => {
const { editingKey } = this.state;
const editable = this.isEditing(record);
return (
<div>
{editable ? (
<span>
<EditableContext.Consumer>
{form => (
<a
href="javascript:;"
onClick={() => this.save(form, record.key)}
style={{ marginRight: 8 }}
>
Save
</a>
)}
</EditableContext.Consumer>
<Popconfirm title="Sure to cancel?" onConfirm={() => this.cancel(record.key)}>
<a>Cancel</a>
</Popconfirm>
</span>
) : (
<a disabled={editingKey !== ''} onClick={() => this.edit(record.key)}>
Edit
</a>
)}
</div>
return editable ? (
<span>
<EditableContext.Consumer>
{form => (
<a
href="javascript:;"
onClick={() => this.save(form, record.key)}
style={{ marginRight: 8 }}
>
Save
</a>
)}
</EditableContext.Consumer>
<Popconfirm title="Sure to cancel?" onConfirm={() => this.cancel(record.key)}>
<a>Cancel</a>
</Popconfirm>
</span>
) : (
<a disabled={editingKey !== ''} onClick={() => this.edit(record.key)}>
Edit
</a>
);
},
},

11
components/tree/Tree.tsx

@ -25,6 +25,7 @@ export interface AntdTreeNodeAttribute {
disabled: boolean;
disableCheckbox: boolean;
}
export interface AntTreeNodeProps {
className?: string;
checkable?: boolean;
@ -69,7 +70,11 @@ export interface AntTreeNodeExpandedEvent extends AntTreeNodeBaseEvent {
export interface AntTreeNodeMouseEvent {
node: AntTreeNode;
event: React.MouseEventHandler<any>;
event: React.MouseEvent<any>;
}
export interface AntTreeNodeDragEnterEvent extends AntTreeNodeMouseEvent {
expandedKeys: string[];
}
export interface AntTreeNodeDropEvent {
@ -78,7 +83,7 @@ export interface AntTreeNodeDropEvent {
dragNodesKeys: string[];
dropPosition: number;
dropToGap?: boolean;
event: React.MouseEventHandler<any>;
event: React.MouseEvent<any>;
}
export interface TreeProps {
@ -135,7 +140,7 @@ export interface TreeProps {
/** 设置节点可拖拽(IE>8)*/
draggable?: boolean;
onDragStart?: (options: AntTreeNodeMouseEvent) => void;
onDragEnter?: (options: AntTreeNodeMouseEvent) => void;
onDragEnter?: (options: AntTreeNodeDragEnterEvent) => void;
onDragOver?: (options: AntTreeNodeMouseEvent) => void;
onDragLeave?: (options: AntTreeNodeMouseEvent) => void;
onDragEnd?: (options: AntTreeNodeMouseEvent) => void;

2
docs/react/use-in-typescript.en-US.md

@ -189,8 +189,6 @@ You can also follow instructions in [Use in create-react-app](/docs/react/use-wi
And you can use [react-scripts-ts-antd](https://www.npmjs.com/package/react-scripts-ts-antd) which includes ts-import-plugin, react-app-rewired, scss, less and etc. You can create a new project that without any configurations by running just one command.
## Alternative ways
- [Create React apps (with Typescript and antd) with no build configuration](https://github.com/SZzzzz/react-scripts-ts-antd)
- [react-app-rewire-typescript][https://github.com/lwd-technology/react-app-rewire-typescript]
- [ts-import-plugin](https://github.com/Brooooooklyn/ts-import-plugin)

6
docs/react/use-in-typescript.zh-CN.md

@ -78,7 +78,7 @@ export default App;
此时我们需要对 create-react-app 的默认配置进行自定义,这里我们使用 [react-app-rewired](https://github.com/timarney/react-app-rewired) (一个对 create-react-app 进行自定义配置的社区解决方案)。
引入 react-app-rewired 并修改 package.json 里的启动配置。由于新的 [react-app-rewired@2.x](https://github.com/timarney/react-app-rewired#alternatives) 版本的关系,你需要还需要安装 [customize-cra](https://github.com/arackaf/customize-cra)。
引入 react-app-rewired 并修改 package.json 里的启动配置。由于新的 [react-app-rewired@2.x](https://github.com/timarney/react-app-rewired#alternatives) 版本的关系,你还需要安装 [customize-cra](https://github.com/arackaf/customize-cra)。
```
$ yarn add react-app-rewired customize-cra
@ -183,6 +183,10 @@ module.exports = override(
## 其他方案
先按照 [在 create-react-app 中使用](/docs/react/use-with-create-react-app.en-US.md) 中的说明操作,再配置 TypeScript 开发环境。
你也可以使用 [react-scripts-ts-antd](https://www.npmjs.com/package/react-scripts-ts-antd),其中包括了 ts-import-plugin,react-app-rewired,scss,less 等插件。你可以通过只运行一个命令来创建一个没有任何配置的新项目。
- [Create React apps (with Typescript and antd) with no build configuration](https://github.com/SZzzzz/react-scripts-ts-antd)
- [react-app-rewire-typescript][https://github.com/lwd-technology/react-app-rewire-typescript]
- [ts-import-plugin](https://github.com/Brooooooklyn/ts-import-plugin)

4
package.json

@ -1,6 +1,6 @@
{
"name": "antd",
"version": "3.18.1",
"version": "3.18.2",
"title": "Ant Design",
"description": "An enterprise-class UI design language and React components implementation",
"homepage": "http://ant.design/",
@ -59,7 +59,7 @@
"prop-types": "^15.6.2",
"raf": "^3.4.0",
"rc-animate": "^2.5.4",
"rc-calendar": "~9.12.1",
"rc-calendar": "~9.13.3",
"rc-cascader": "~0.17.0",
"rc-checkbox": "~2.1.5",
"rc-collapse": "~1.11.1",

10
site/theme/template/Content/Article.jsx

@ -11,6 +11,16 @@ export default class Article extends React.Component {
intl: PropTypes.object.isRequired,
};
shouldComponentUpdate(nextProps) {
const { location } = this.props;
const { location: nextLocation } = nextProps;
if (nextLocation.pathname === location.pathname) {
return false;
}
return true;
}
onResourceClick = e => {
if (!window.gtag) {
return;

10
site/theme/template/Content/ComponentDoc.jsx

@ -29,6 +29,16 @@ export default class ComponentDoc extends React.Component {
});
}
shouldComponentUpdate(nextProps) {
const { location } = this.props;
const { location: nextLocation } = nextProps;
if (nextLocation.pathname === location.pathname) {
return false;
}
return true;
}
componentWillUnmount() {
clearTimeout(this.pingTimer);
}

33
site/theme/template/Content/MainContent.jsx

@ -68,6 +68,7 @@ export default class MainContent extends Component {
componentDidMount() {
this.componentDidUpdate();
window.addEventListener('load', this.handleInitialHashOnLoad);
}
static getDerivedStateFromProps(props, state) {
@ -87,28 +88,18 @@ export default class MainContent extends Component {
this.bindScroller();
}
if (!window.location.hash && prevLocation.pathname !== location.pathname) {
document.documentElement.scrollTop = 0;
window.scrollTo(0, 0);
}
// when subMenu not equal
if (get(this.props, 'route.path') !== get(prevProps, 'route.path')) {
// reset menu OpenKeys
this.handleMenuOpenChange();
}
setTimeout(() => {
if (!window.location.hash) {
return;
}
const element = document.getElementById(
decodeURIComponent(window.location.hash.replace('#', '')),
);
if (element && document.documentElement.scrollTop === 0) {
element.scrollIntoView();
}
}, 0);
}
componentWillUnmount() {
this.scroller.disable();
this.scroller.destroy();
window.removeEventListener('load', this.handleInitialHashOnLoad);
}
getMenuItems(footerNavIcons = {}) {
@ -163,9 +154,23 @@ export default class MainContent extends Component {
this.setState({ openKeys });
};
handleInitialHashOnLoad = () => {
setTimeout(() => {
if (!window.location.hash) {
return;
}
const element = document.getElementById(
decodeURIComponent(window.location.hash.replace('#', '')),
);
if (element && document.documentElement.scrollTop === 0) {
element.scrollIntoView();
}
}, 0);
};
bindScroller() {
if (this.scroller) {
this.scroller.disable();
this.scroller.destroy();
}
require('intersection-observer'); // eslint-disable-line
const scrollama = require('scrollama'); // eslint-disable-line

374
site/theme/template/IconDisplay/fields.ts

@ -1,370 +1,12 @@
import manifest from '@ant-design/icons/lib/manifest';
let allIcons: string[] = [];
Object.keys(manifest).forEach(theme => {
allIcons = [...allIcons, ...(manifest as any)[theme]];
});
export const categories = {
all: [
'underline',
'small-dash',
'caret-down',
'medium',
'search',
'vertical-align-middle',
'like',
'pause-circle',
'pic-left',
'check-square',
'file-search',
'arrow-down',
'switcher',
'rollback',
'money-collect',
'bulb',
'vertical-left',
'file-unknown',
'appstore',
'file-excel',
'sound',
'unordered-list',
'left-circle',
'play-circle',
'file-zip',
'border-outer',
'medium-workmark',
'dropbox',
'hourglass',
'sort-descending',
'swap-left',
'safety',
'menu-unfold',
'user',
'highlight',
'fullscreen',
'reconciliation',
'issues-close',
'android',
'dollar',
'colum-height',
'pull-request',
'home',
'shop',
'copyright',
'alert',
'gitlab',
'disconnect',
'column-width',
'sliders',
'ant-design',
'weibo',
'fullscreen-exit',
'logout',
'strikethrough',
'shopping',
'file-word',
'funnel-plot',
'github',
'vertical-right',
'usb',
'export',
'down',
'shrink',
'usergroup-add',
'tag',
'up-square',
'down-square',
'file-add',
'fall',
'inbox',
'audit',
'plus-square',
'stock',
'drag',
'database',
'file',
'account-book',
'control',
'red-envelope',
'radius-bottomright',
'radius-bottomleft',
'box-plot',
'file-text',
'folder-open',
'build',
'font-size',
'apartment',
'behance-square',
'bar-chart',
'up',
'question-circle',
'question',
'lock',
'cloud-upload',
'fire',
'weibo-circle',
'dislike',
'usergroup-delete',
'instagram',
'euro',
'link',
'idcard',
'key',
'meh',
'arrow-right',
'percentage',
'qrcode',
'number',
'ci',
'diff',
'minus-square',
'border-inner',
'paper-clip',
'caret-up',
'close-circle',
'pic-center',
'mail',
'desktop',
'download',
'import',
'radar-chart',
'area-chart',
'pound',
'file-done',
'user-delete',
'aliyun',
'login',
'book',
'scissor',
'wallet',
'file-image',
'bell',
'coffee',
'dashboard',
'code',
'poweroff',
'heat-map',
'alipay-circle',
'aliwangwang',
'carry-out',
'transaction',
'double-left',
'flag',
'snippets',
'stop',
'right-circle',
'step-forward',
'cluster',
'container',
'slack-square',
'frown',
'tool',
'safety-certificate',
'dribbble-square',
'rise',
'file-sync',
'border',
'caret-right',
'bold',
'trophy',
'share-alt',
'plus',
'check',
'dash',
'warning',
'trademark',
'global',
'pie-chart',
'radius-upright',
'security-scan',
'wifi',
'line-height',
'team',
'info',
'user-add',
'close',
'border-verticle',
'info-circle',
'dingding',
'eye-invisible',
'cloud-sync',
'left-square',
'copy',
'gold',
'ant-cloud',
'zoom-in',
'fund',
'reload',
'play-square',
'border-right',
'file-exclamation',
'codepen-circle',
'fast-backward',
'align-right',
'environment',
'check-circle',
'html5',
'save',
'smile',
'scan',
'fork',
'right',
'file-protect',
'setting',
'solution',
'loading',
'fast-forward',
'message',
'zoom-out',
'crown',
'backward',
'yuque',
'notification',
'picture',
'exception',
'table',
'barcode',
'taobao-circle',
'facebook',
'camera',
'printer',
'amazon',
'file-jpg',
'border-top',
'redo',
'pay-circle',
'wechat',
'swap-right',
'google',
'more',
'line',
'up-circle',
'exclamation-circle',
'branches',
'radius-setting',
'deployment-unit',
'down-circle',
'step-backward',
'rest',
'contacts',
'form',
'star',
'ordered-list',
'experiment',
'edit',
'api',
'windows',
'youtube',
'unlock',
'to-top',
'border-left',
'compass',
'alibaba',
'plus-circle',
'menu-fold',
'woman',
'bank',
'credit-card',
'file-markdown',
'vertical-align-bottom',
'gateway',
'select',
'yahoo',
'loading-3-quarters',
'sketch',
'audio',
'delete',
'reddit',
'alipay',
'pic-right',
'retweet',
'skin',
'phone',
'sync',
'eye',
'mobile',
'insurance',
'codepen',
'dribbble',
'gift',
'line-chart',
'car',
'weibo-square',
'thunderbolt',
'profile',
'tags',
'border-bottom',
'arrow-up',
'google-plus',
'folder-add',
'schedule',
'linkedin',
'qq',
'shake',
'undo',
'robot',
'twitter',
'filter',
'italic',
'calendar',
'video-camera',
'arrow-left',
'align-center',
'ellipsis',
'minus-circle',
'border-horizontal',
'laptop',
'dot-chart',
'caret-left',
'font-colors',
'close-square',
'slack',
'zhihu',
'cloud',
'ie',
'read',
'bars',
'vertical-align-top',
'upload',
'pause',
'double-right',
'property-safety',
'forward',
'code-sandbox',
'interation',
'right-square',
'skype',
'rocket',
'tablet',
'enter',
'cloud-download',
'menu',
'pushpin',
'hdd',
'chrome',
'shopping-cart',
'sort-ascending',
'calculator',
'apple',
'block',
'man',
'medicine-box',
'project',
'history',
'folder',
'arrows-alt',
'taobao',
'file-ppt',
'bg-colors',
'left',
'file-pdf',
'monitor',
'minus',
'exclamation',
'swap',
'behance',
'customer-service',
'radius-upleft',
'cloud-server',
'layout',
'clock-circle',
'align-left',
'heart',
],
all: [...new Set(allIcons)],
direction: [
'step-backward',
'step-forward',

40
site/theme/template/IconDisplay/index.tsx

@ -63,28 +63,32 @@ class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
};
renderCategories(list: Array<{ category: CategoriesKeys; icons: string[] }>) {
const { searchKey } = this.state;
const { searchKey, theme } = this.state;
const otherIcons = categories.all.filter(icon => {
return list.filter(({ category }) => category !== 'all').every(item => !item.icons.includes(icon));
return list
.filter(({ category }) => category !== 'all')
.every(item => !item.icons.includes(icon));
});
return list
.filter(({ category }) => category !== 'all')
.concat({ category: 'other', icons: otherIcons })
.map(({ category, icons }) => ({
category,
icons: icons.filter(name => name.includes(searchKey)),
}))
.filter(({ icons }) => !!icons.length)
.map(({ category, icons }) => (
<Category
key={category}
title={category}
icons={icons}
theme={this.state.theme}
newIcons={IconDisplay.newIconNames}
/>
));
.filter(({ category }) => category !== 'all')
.concat({ category: 'other', icons: otherIcons })
.map(({ category, icons }) => ({
category,
icons: icons
.filter(name => name.includes(searchKey))
.filter(name => manifest[IconDisplay.themeTypeMapper[theme]].includes(name)),
}))
.filter(({ icons }) => !!icons.length)
.map(({ category, icons }) => (
<Category
key={category}
title={category}
icons={icons}
theme={this.state.theme}
newIcons={IconDisplay.newIconNames}
/>
));
}
render() {

Loading…
Cancel
Save