Merge branch "master" into "feature"

This commit is contained in:
afc163 2018-12-20 17:43:00 +08:00
commit 879784c665
No known key found for this signature in database
GPG Key ID: 738F973FCE5C6B48
33 changed files with 359 additions and 83 deletions

View File

@ -219,6 +219,8 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
// Wait for parent component ref has its value
this.timeout = setTimeout(() => {
this.setTargetEventListeners(target);
// Mock Event object.
this.updatePosition({} as Event);
});
}

View File

@ -208,7 +208,7 @@ export default class Button extends React.Component<ButtonProps, any> {
[`${prefixCls}-${type}`]: type,
[`${prefixCls}-${shape}`]: shape,
[`${prefixCls}-${sizeCls}`]: sizeCls,
[`${prefixCls}-icon-only`]: !children && icon,
[`${prefixCls}-icon-only`]: !children && children !== 0 && icon,
[`${prefixCls}-loading`]: loading,
[`${prefixCls}-background-ghost`]: ghost,
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar,

View File

@ -234,6 +234,21 @@
}
}
&-loading {
overflow: hidden;
position: relative;
&:after {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: @card-padding-base;
background: @component-background;
content: '';
}
}
&-loading &-body {
user-select: none;
}

View File

@ -262,11 +262,11 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
handlePopupVisibleChange = (popupVisible: boolean) => {
if (!('popupVisible' in this.props)) {
this.setState({
this.setState(state => ({
popupVisible,
inputFocused: popupVisible,
inputValue: popupVisible ? this.state.inputValue : '',
});
inputValue: popupVisible ? state.inputValue : '',
}));
}
const onPopupVisibleChange = this.props.onPopupVisibleChange;

View File

@ -69,7 +69,7 @@
&-actions {
margin-top: 12px;
padding-left: 0;
> li {
display: inline-block;
color: @comment-action-color;

View File

@ -143,17 +143,14 @@ export default class Drawer extends React.Component<DrawerProps, IDrawerState> {
};
getRcDrawerStyle = () => {
const { zIndex, placement, maskStyle } = this.props;
return this.state.push
? {
...maskStyle,
zIndex,
transform: this.getPushTransform(placement),
}
: {
...maskStyle,
zIndex,
};
const { zIndex, placement, maskStyle, style } = this.props;
const { push } = this.state;
return {
...maskStyle,
zIndex,
transform: push ? this.getPushTransform(placement) : undefined,
style,
};
};
// render drawer body dom
@ -210,14 +207,12 @@ export default class Drawer extends React.Component<DrawerProps, IDrawerState> {
>
{header}
{closer}
<div className={`${prefixCls}-body`} style={this.props.style}>
{this.props.children}
</div>
<div className={`${prefixCls}-body`}>{this.props.children}</div>
</div>
);
};
// render Provider for Multi-level drawer
// render Provider for Multi-level drawe
renderProvider = (value: Drawer) => {
const {
prefixCls: customizePrefixCls,

View File

@ -15,7 +15,7 @@
position: absolute;
top: -7px;
left: -7px;
right: -7px;
right: 0;
bottom: -7px;
content: ' ';
opacity: 0.0001;
@ -55,6 +55,7 @@
border-radius: @border-radius-base;
box-shadow: @box-shadow-base;
background-clip: padding-box;
-webkit-transform: translate3d(0, 0, 0);
&-item-group-title {
color: @text-color-secondary;

View File

@ -104,7 +104,7 @@ export default class Row extends React.Component<RowProps, RowState> {
getGutter(): number | undefined {
const { gutter } = this.props;
if (typeof gutter === 'object') {
for (let i = 0; i <= responsiveArray.length; i++) {
for (let i = 0; i < responsiveArray.length; i++) {
const breakpoint: Breakpoint = responsiveArray[i];
if (this.state.screens[breakpoint] && gutter[breakpoint] !== undefined) {
return gutter[breakpoint];

View File

@ -138,7 +138,7 @@ const Icon: IconComponent<IconProps> = props => {
);
}
computedType = withThemeSuffix(
removeTypeTheme(alias(type)),
removeTypeTheme(alias(computedType)),
dangerousTheme || theme || defaultTheme,
);
innerNode = (

View File

@ -46,7 +46,11 @@ class Basic extends React.Component<BasicProps, any> {
}
}
class BasicLayout extends React.Component<BasicProps, any> {
interface BasicLayoutState {
siders: string[];
}
class BasicLayout extends React.Component<BasicProps, BasicLayoutState> {
static childContextTypes = {
siderHook: PropTypes.object,
};
@ -56,14 +60,14 @@ class BasicLayout extends React.Component<BasicProps, any> {
return {
siderHook: {
addSider: (id: string) => {
this.setState({
siders: [...this.state.siders, id],
});
this.setState(state => ({
siders: [...state.siders, id],
}));
},
removeSider: (id: string) => {
this.setState({
siders: this.state.siders.filter(currentId => currentId !== id),
});
this.setState(state => ({
siders: state.siders.filter(currentId => currentId !== id),
}));
},
},
};

View File

@ -94,6 +94,7 @@ class Mention extends React.Component<MentionProps, MentionState> {
this.props.onFocus(ev);
}
};
onBlur = (ev: React.FocusEvent<HTMLElement>) => {
this.setState({
focus: false,
@ -102,9 +103,11 @@ class Mention extends React.Component<MentionProps, MentionState> {
this.props.onBlur(ev);
}
};
focus = () => {
this.mentionEle._editor.focusEditor();
};
mentionRef = (ele: any) => {
this.mentionEle = ele;
};
@ -122,7 +125,6 @@ class Mention extends React.Component<MentionProps, MentionState> {
[`${prefixCls}-active`]: focus,
[`${prefixCls}-placement-top`]: placement === 'top',
});
const notFoundContent = loading ? <Icon type="loading" /> : this.props.notFoundContent;
return (

View File

@ -214,26 +214,19 @@ export default class Menu extends React.Component<MenuProps, MenuState> {
const { openAnimation, openTransitionName } = this.props;
let menuOpenAnimation = openAnimation || openTransitionName;
if (openAnimation === undefined && openTransitionName === undefined) {
switch (menuMode) {
case 'horizontal':
menuOpenAnimation = 'slide-up';
break;
case 'vertical':
case 'vertical-left':
case 'vertical-right':
// When mode switch from inline
// submenu should hide without animation
if (this.switchingModeFromInline) {
menuOpenAnimation = '';
this.switchingModeFromInline = false;
} else {
menuOpenAnimation = 'zoom-big';
}
break;
case 'inline':
menuOpenAnimation = animation;
break;
default:
if (menuMode === 'horizontal') {
menuOpenAnimation = 'slide-up';
} else if (menuMode === 'inline') {
menuOpenAnimation = animation;
} else {
// When mode switch from inline
// submenu should hide without animation
if (this.switchingModeFromInline) {
menuOpenAnimation = '';
this.switchingModeFromInline = false;
} else {
menuOpenAnimation = 'zoom-big';
}
}
}
return menuOpenAnimation;

View File

@ -136,7 +136,7 @@ export default function confirm(config: ModalFuncProps) {
if (unmountResult && div.parentNode) {
div.parentNode.removeChild(div);
}
const triggerCancel = args && args.length && args.some(param => param && param.triggerCancel);
const triggerCancel = args.some(param => param && param.triggerCancel);
if (config.onCancel && triggerCancel) {
config.onCancel(...args);
}

View File

@ -101,6 +101,7 @@
&-arrow {
background: @popover-bg;
background-color: inherit;
width: sqrt(@popover-arrow-width * @popover-arrow-width * 2);
height: sqrt(@popover-arrow-width * @popover-arrow-width * 2);
transform: rotate(45deg);

View File

@ -89,6 +89,33 @@ exports[`Progress render negetive successPercent 1`] = `
</div>
`;
exports[`Progress render normal progress 1`] = `
<div
class="ant-progress ant-progress-line ant-progress-status-normal ant-progress-show-info ant-progress-default"
>
<div>
<div
class="ant-progress-outer"
>
<div
class="ant-progress-inner"
>
<div
class="ant-progress-bg"
style="width: 0%; height: 8px; border-radius: 100px;"
/>
</div>
</div>
<span
class="ant-progress-text"
title="0%"
>
0%
</span>
</div>
</div>
`;
exports[`Progress render out-of-range progress 1`] = `
<div
class="ant-progress ant-progress-line ant-progress-status-success ant-progress-show-info ant-progress-default"

View File

@ -46,4 +46,9 @@ describe('Progress', () => {
const wrapper = mount(<Progress type="circle" percent={50} strokeColor="red" />);
expect(wrapper.render()).toMatchSnapshot();
});
it('render normal progress', () => {
const wrapper = mount(<Progress status="normal" />);
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -22,7 +22,7 @@ If it will take a long time to complete an operation, you can use `Progress` to
| gapPosition `(type=circle)` | the gap position, options: `top` `bottom` `left` `right` | string | `top` |
| percent | to set the completion percentage | number | 0 |
| showInfo | whether to display the progress value and the status icon | boolean | true |
| status | to set the status of the Progress, options: `success` `exception` `active` | string | - |
| status | to set the status of the Progress, options: `success` `exception` `active` `normal` | string | - |
| strokeWidth `(type=line)` | to set the width of the progress bar, unit: `px` | number | 10 |
| strokeWidth `(type=circle)` | to set the width of the circular progress bar, unit: percentage of the canvas width | number | 6 |
| strokeLinecap | to set the style of the progress linecap | Enum{ 'round', 'square' } | `round` |

View File

@ -23,7 +23,7 @@ title: Progress
| gapPosition `(type=circle)` | 圆形进度条缺口位置 | Enum{ 'top', 'bottom', 'left', 'right' } | `top` |
| percent | 百分比 | number | 0 |
| showInfo | 是否显示进度数值或状态图标 | boolean | true |
| status | 状态,可选:`success` `exception` `active` | string | - |
| status | 状态,可选:`success` `exception` `active` `normal` | string | - |
| strokeWidth `(type=line)` | 进度条线的宽度,单位 px | number | 10 |
| strokeWidth `(type=circle)` | 圆形进度条线的宽度,单位是进度条画布宽度的百分比 | number | 6 |
| strokeLinecap | | Enum{ 'round', 'square' } | `round` |

View File

@ -21,7 +21,7 @@ export interface ProgressProps {
percent?: number;
successPercent?: number;
format?: (percent?: number, successPercent?: number) => React.ReactNode;
status?: 'success' | 'active' | 'exception';
status?: 'success' | 'active' | 'exception' | 'normal';
showInfo?: boolean;
strokeWidth?: number;
strokeLinecap?: string;

View File

@ -37,7 +37,7 @@ export interface AbstractSelectProps {
open?: boolean;
onDropdownVisibleChange?: (open: boolean) => void;
autoClearSearchValue?: boolean;
dropdownRender?: (menu: React.ReactNode) => React.ReactNode;
dropdownRender?: (menu?: React.ReactNode, props?: SelectProps) => React.ReactNode;
loading?: boolean;
}

View File

@ -14,10 +14,10 @@ title:
When `tooltipVisible` is `true`, ToolTip will show always, or ToolTip will not show anyway, even if dragging or hovering.
````jsx
````jsx
import Slider from '..';
import { Slider } from 'antd';
ReactDOM.render(<Slider defaultValue={30} tooltipVisible />, mountNode);
ReactDOM.render(<Slider defaultValue={30} tooltipVisible />, mountNode);
````
````

View File

@ -85,12 +85,7 @@ export default class Slider extends React.Component<SliderProps, SliderState> {
const { tipFormatter, tooltipVisible } = this.props;
const { visibles } = this.state;
const isTipFormatter = tipFormatter ? visibles[index] || dragging : false;
let visible;
if (tooltipVisible) {
visible = tooltipVisible || isTipFormatter;
} else if (tooltipVisible === undefined) {
visible = isTipFormatter;
}
const visible = tooltipVisible || (tooltipVisible === undefined && isTipFormatter);
return (
<Tooltip
prefixCls={tooltipPrefixCls}

View File

@ -432,6 +432,8 @@
@tabs-bar-margin: 0 0 16px 0;
@tabs-horizontal-margin: 0 32px 0 0;
@tabs-horizontal-padding: 12px 16px;
@tabs-horizontal-padding-lg: 16px;
@tabs-horizontal-padding-sm: 8px 16px;
@tabs-vertical-padding: 8px 24px;
@tabs-vertical-margin: 0 0 16px 0;
@tabs-scrolling-size: 32px;

View File

@ -494,7 +494,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();
const rows = this.getFlatCurrentPageData(this.props.childrenColumnName);
let realIndex = rowIndex;
if (this.props.expandedRowRender) {
realIndex = rows.findIndex(row => this.getRecordKey(row, rowIndex) === key);
@ -559,10 +559,8 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
handleRadioSelect = (record: T, rowIndex: number, e: RadioChangeEvent) => {
const checked = e.target.checked;
const nativeEvent = e.nativeEvent;
const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection();
let selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
const key = this.getRecordKey(record, rowIndex);
selectedRowKeys = [key];
const selectedRowKeys = [key];
this.store.setState({
selectionDirty: true,
});
@ -576,7 +574,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
};
handleSelectRow = (selectionKey: string, index: number, onSelectFunc: SelectionItemSelectFn) => {
const data = this.getFlatCurrentPageData();
const data = this.getFlatCurrentPageData(this.props.childrenColumnName);
const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection();
const selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
const changeableRowKeys = data
@ -728,10 +726,10 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
};
renderRowSelection(prefixCls: string, locale: TableLocale) {
const { rowSelection } = this.props;
const { rowSelection, childrenColumnName } = this.props;
const columns = this.columns.concat();
if (rowSelection) {
const data = this.getFlatCurrentPageData().filter((item, index) => {
const data = this.getFlatCurrentPageData(childrenColumnName).filter((item, index) => {
if (rowSelection.getCheckboxProps) {
return !this.getCheckboxPropsByItem(item, index).disabled;
}
@ -783,7 +781,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
}
getColumnKey(column: ColumnProps<T>, index?: number) {
return column.key || column.dataIndex || index;
return column.key || (column.dataIndex as string) || index;
}
getMaxCurrent(total: number) {
@ -1034,8 +1032,8 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
return flatArray(this.getLocalData(null, false));
}
getFlatCurrentPageData() {
return flatArray(this.getCurrentPageData());
getFlatCurrentPageData(childrenColumnName: string | undefined) {
return flatArray(this.getCurrentPageData(), childrenColumnName);
}
recursiveSort(data: T[], sorterFn: (a: any, b: any) => number): T[] {

View File

@ -615,4 +615,40 @@ describe('Table.rowSelection', () => {
expect(onChange.mock.calls[1][0].length).toBe(2);
expect(onChange.mock.calls[1][1].length).toBe(2);
});
it('render correctly when set childrenColumnName', () => {
const newDatas = [
{
key: 1,
name: 'Jack',
children: [
{
key: 11,
name: 'John Brown',
},
],
},
{
key: 2,
name: 'Lucy',
children: [
{
key: 21,
name: 'Lucy Brown',
},
],
},
];
const wrapper = mount(
<Table columns={columns} dataSource={newDatas} childrenColumnName="test" rowSelection={{}} />,
);
const checkboxes = wrapper.find('input');
const checkboxAll = wrapper.find('SelectionCheckboxAll');
checkboxes.at(1).simulate('change', { target: { checked: true } });
expect(checkboxAll.instance().state).toEqual({ indeterminate: true, checked: false });
checkboxes.at(2).simulate('change', { target: { checked: true } });
expect(checkboxAll.instance().state).toEqual({ indeterminate: false, checked: true });
});
});

View File

@ -19,7 +19,7 @@ export interface ColumnProps<T> {
},
) => React.ReactNode);
key?: React.Key;
dataIndex?: string;
dataIndex?: keyof T;
render?: (text: any, record: T, index: number) => React.ReactNode;
align?: 'left' | 'right' | 'center';
filters?: ColumnFilterItem[];

View File

@ -204,7 +204,7 @@
font-size: @tabs-title-font-size-lg;
}
.@{tab-prefix-cls}-tab {
padding: 16px;
padding: @tabs-horizontal-padding-lg;
}
}
@ -213,7 +213,7 @@
font-size: @tabs-title-font-size-sm;
}
.@{tab-prefix-cls}-tab {
padding: 8px 16px;
padding: @tabs-horizontal-padding-sm;
}
}

View File

@ -132,7 +132,7 @@ export default class DirectoryTree extends React.Component<DirectoryTreeProps, D
onSelect = (keys: string[], event: AntTreeNodeSelectedEvent) => {
const { onSelect, multiple, children } = this.props;
const { expandedKeys = [], selectedKeys = [] } = this.state;
const { expandedKeys = [] } = this.state;
const { node, nativeEvent } = event;
const { eventKey = '' } = node.props;
@ -143,7 +143,7 @@ export default class DirectoryTree extends React.Component<DirectoryTreeProps, D
const shiftPick: boolean = nativeEvent.shiftKey;
// Generate new selected keys
let newSelectedKeys = selectedKeys.slice();
let newSelectedKeys: string[];
if (multiple && ctrlPick) {
// Control click
newSelectedKeys = keys;

View File

@ -21,3 +21,4 @@
@import './theme';
@import './docsearch';
@import './nprogress';
@import './santa';

View File

@ -0,0 +1,171 @@
.santa {
display: inline-block;
vertical-align: middle;
margin-left: 8px;
margin-right: 8px;
}
.santa-body {
font-size: 24px;
color: #f91047;
display: flex;
justify-content: center;
align-items: center;
width: 1em;
height: 1em;
background-color: currentColor;
box-shadow: inset 0 -0.25em rgba(0, 0, 0, 0.1);
border-radius: 50%;
transform-origin: center bottom;
animation: balance alternate infinite 2s ease-in-out;
}
.santa-head {
font-size: 0.4em;
width: 1em;
height: 1.9em;
background-color: white;
border-radius: 0.5em;
transform: translateY(-1em);
position: relative;
}
.santa-head::before {
content: '';
width: 1em;
height: 0.375em;
display: block;
background-color: #ff9876;
position: absolute;
left: 0;
top: 0.65em;
}
.santa-ear {
background-color: #fc8363;
width: 0.1em;
height: 0.3em;
position: absolute;
top: 0.75em;
}
.santa-ear:nth-of-type(1) {
border-radius: 0.05em 0 0 0.05em;
left: -0.1em;
}
.santa-ear:nth-of-type(2) {
border-radius: 0 0.05em 0.05em 0;
right: -0.1em;
}
.santa-hat {
content: '';
width: 1em;
height: 0.15em;
position: absolute;
transform: scale(1.1);
top: 0.5em;
left: 0;
background-color: white;
}
.santa-hat::before {
content: '';
display: block;
width: 1em;
height: 0.5em;
background: #f91047;
border-radius: 0.5em 0.5em 0 0;
z-index: 2;
position: absolute;
top: -0.5em;
}
.santa-hat::after {
/* pompom */
content: '';
width: 0.25em;
height: 0.25em;
display: block;
background-color: white;
border-radius: 50%;
position: absolute;
z-index: 0;
top: -0.72em;
right: 0;
box-shadow: -0.2em 0.2em 0 0.12em rgba(0, 0, 0, 0.2), -0.2em 0.2em 0 0.12em #f91047;
}
.santa-eye {
width: 0.12em;
height: 0.12em;
background-color: black;
border-radius: 50%;
position: absolute;
top: 0.76em;
left: 0.2em;
}
.santa-eye + .santa-eye {
left: auto;
right: 0.2em;
}
.santa-nose {
width: 0.12em;
height: 0.22em;
background-color: #f24c4c;
border-radius: 0 0 0.12em 0.12em;
position: absolute;
top: 0.84em;
left: 50%;
transform: translateX(-50%);
}
.santa-mouth {
width: 0.18em;
height: 0.1em;
border-bottom-right-radius: 5vw;
border-bottom-left-radius: 5vw;
margin-top: 0.3em;
background-color: black;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
animation: hohoho 4s linear forwards infinite;
}
@keyframes hohoho {
0%,
10%,
20%,
40%,
100% {
/* smiling */
width: 0.18em;
height: 0.1em;
border-bottom-right-radius: 1vw;
border-bottom-left-radius: 1vw;
}
5%,
15%,
25%,
35% {
/* hohoho */
width: 0.15em;
height: 0.2em;
border-radius: 50%;
}
}
@keyframes balance {
from {
transform: rotate(-4deg);
}
to {
transform: rotate(4deg);
}
}

View File

@ -169,12 +169,12 @@ export default class Demo extends React.Component {
const dependencies = sourceCode.split('\n').reduce(
(acc, line) => {
const matches = line.match(/import .+? from '(.+)';$/);
if (matches && matches[1]) {
if (matches && matches[1] && !line.includes('antd')) {
acc[matches[1]] = 'latest';
}
return acc;
},
{ react: 'latest', 'react-dom': 'latest' },
{ react: 'latest', 'react-dom': 'latest', antd: 'latest' },
);
const codesanboxPrefillConfig = {
files: {

View File

@ -4,6 +4,7 @@ import { Link } from 'bisheng/router';
import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import { Select, Menu, Row, Col, Icon, Popover, Input, Badge, Button } from 'antd';
import Santa from './Santa';
import * as utils from '../utils';
import { version as antdVersion } from '../../../../package.json';
@ -238,6 +239,7 @@ export default class Header extends React.Component {
alt="Ant Design"
src="https://gw.alipayobjects.com/zos/rmsportal/DkKNubTaaVsKURhcVGkh.svg"
/>
<Santa />
</Link>
</Col>
<Col xxl={20} xl={19} lg={19} md={19} sm={0} xs={0}>

View File

@ -0,0 +1,26 @@
import React from 'react';
import { Tooltip } from 'antd';
export default () => {
const now = new Date();
const isChristmas = now.getMonth() === 11 && now.getDate() === 25;
return (
isChristmas && (
<Tooltip title="🎅🏻 Merry Chrismas!">
<div className="santa">
<div className="santa-body">
<div className="santa-head">
<div className="santa-ear" />
<div className="santa-ear" />
<div className="santa-hat" />
<div className="santa-eye" />
<div className="santa-eye" />
<div className="santa-nose" />
<div className="santa-mouth" />
</div>
</div>
</div>
</Tooltip>
)
);
};