Merge branch 'feature-3.2'

This commit is contained in:
Wei Zhu 2018-02-04 17:24:16 +08:00
commit 49c2a6220b
41 changed files with 4977 additions and 79 deletions

View File

@ -21,5 +21,6 @@ Alert component for feedback.
| description | Additional content of Alert | string\|ReactNode | - |
| message | Content of Alert | string\|ReactNode | - |
| showIcon | Whether to show icon | boolean | false, in `banner` mode default is true |
| iconType | Icon type, effective when `showIcon` is `true` | string | - |
| type | Type of Alert styles, options: `success`, `info`, `warning`, `error` | string | `info`, in `banner` mode default is `warning` |
| onClose | Callback when Alert is closed | Function | - |

View File

@ -23,6 +23,7 @@ export interface AlertProps {
onClose?: React.MouseEventHandler<HTMLAnchorElement>;
/** Whether to show icon */
showIcon?: boolean;
iconType?: string;
style?: React.CSSProperties;
prefixCls?: string;
className?: string;
@ -59,7 +60,7 @@ export default class Alert extends React.Component<AlertProps, any> {
render() {
let {
closable, description, type, prefixCls = 'ant-alert', message, closeText, showIcon, banner,
className = '', style,
className = '', style, iconType,
} = this.props;
// banner模式默认有 Icon
@ -67,27 +68,28 @@ export default class Alert extends React.Component<AlertProps, any> {
// banner模式默认为警告
type = banner && type === undefined ? 'warning' : type || 'info';
let iconType = '';
switch (type) {
case 'success':
iconType = 'check-circle';
break;
case 'info':
iconType = 'info-circle';
break;
case 'error':
iconType = 'cross-circle';
break;
case 'warning':
iconType = 'exclamation-circle';
break;
default:
iconType = 'default';
}
if (!iconType) {
switch (type) {
case 'success':
iconType = 'check-circle';
break;
case 'info':
iconType = 'info-circle';
break;
case 'error':
iconType = 'cross-circle';
break;
case 'warning':
iconType = 'exclamation-circle';
break;
default:
iconType = 'default';
}
// use outline icon in alert with description
if (!!description) {
iconType += '-o';
// use outline icon in alert with description
if (!!description) {
iconType += '-o';
}
}
let alertCls = classNames(prefixCls, {

View File

@ -22,5 +22,6 @@ title: Alert
| description | 警告提示的辅助性文字介绍 | string\|ReactNode | 无 |
| message | 警告提示内容 | string\|ReactNode | 无 |
| showIcon | 是否显示辅助图标 | boolean | false`banner` 模式下默认值为 true |
| iconType | 自定义图标类型,`showIcon` 为 `true` 时有效 | string | - |
| type | 指定警告提示的样式,有四种选择 `success`、`info`、`warning`、`error` | string | `info``banner` 模式下默认值为 `warning` |
| onClose | 关闭时触发的回调函数 | Function | 无 |

View File

@ -0,0 +1,2 @@
import ku_IQ from '../../date-picker/locale/ku_IQ';
export default ku_IQ;

View File

@ -10,6 +10,7 @@ export interface CollapsePanelProps {
style?: React.CSSProperties;
showArrow?: boolean;
prefixCls?: string;
forceRender?: boolean;
}
export default class CollapsePanel extends React.Component<CollapsePanelProps, {}> {

View File

@ -30,3 +30,4 @@ A content area which can be collapsed and expanded.
| header | Title of the panel | string\|ReactNode | - |
| key | Unique key identifying the panel from among its siblings | string | - |
| showArrow | If `false`, panel will not show arrow icon | boolean | `true` |
| forceRender | Forced render of content on panel, instead of lazy rending after clicking on header | boolean | `false` |

View File

@ -30,3 +30,4 @@ cols: 1
| disabled | 禁用后的面板展开与否将无法通过用户交互改变 | boolean | false |
| header | 面板头内容 | string\|ReactNode | 无 |
| key | 对应 activeKey | string | 无 |
| forceRender | 被隐藏时是否渲染 DOM 结构 | boolean | false |

View File

@ -7,7 +7,7 @@ import classNames from 'classnames';
import Icon from '../icon';
import warning from '../_util/warning';
import callMoment from '../_util/callMoment';
import { RangePickerValue } from './interface';
import { RangePickerValue, RangePickerPresetRange } from './interface';
export interface RangePickerState {
value?: RangePickerValue;
@ -156,6 +156,26 @@ export default class RangePicker extends React.Component<any, RangePickerState>
}
}
handleCalendarInputSelect = (value: RangePickerValue) => {
this.setState(({ showDate }) => ({
value,
showDate: getShowDateFromValue(value) || showDate,
}));
}
handleRangeClick = (value: RangePickerPresetRange) => {
if (typeof value === 'function') {
value = value();
}
this.setValue(value, true);
const { onOk } = this.props;
if (onOk) {
onOk(value);
}
}
setValue(value: RangePickerValue, hidePanel?: boolean) {
this.handleChange(value);
if ((hidePanel || !this.props.showTime) && !('open' in this.props)) {
@ -190,7 +210,7 @@ export default class RangePicker extends React.Component<any, RangePickerState>
return (
<a
key={range}
onClick={() => this.setValue(value, true)}
onClick={() => this.handleRangeClick(value)}
onMouseEnter={() => this.setState({ hoverValue: value })}
onMouseLeave={this.handleRangeMouseLeave}
>
@ -269,6 +289,7 @@ export default class RangePicker extends React.Component<any, RangePickerState>
onHoverChange={this.handleHoverChange}
onPanelChange={props.onPanelChange}
showToday={showToday}
onInputSelect={this.handleCalendarInputSelect}
/>
);
@ -317,6 +338,7 @@ export default class RangePicker extends React.Component<any, RangePickerState>
return (
<span
ref={this.savePicker}
id={props.id}
className={classNames(props.className, props.pickerClass)}
style={{ ...style, ...pickerStyle }}
tabIndex={props.disabled ? -1 : 0}

View File

@ -131,7 +131,7 @@ export default class WeekPicker extends React.Component<any, any> {
);
};
return (
<span className={classNames(className, pickerClass)}>
<span className={classNames(className, pickerClass)} id={this.props.id}>
<RcDatePicker
{...this.props}
calendar={calendar}

View File

@ -10,6 +10,14 @@ const { RangePicker } = DatePicker;
describe('RangePicker', () => {
focusTest(RangePicker);
beforeEach(() => {
setMockDate();
});
afterEach(() => {
resetMockDate();
});
it('show month panel according to value', () => {
const birthday = moment('2000-01-01', 'YYYY-MM-DD').locale('zh-cn');
const wrapper = mount(
@ -115,7 +123,6 @@ describe('RangePicker', () => {
});
it('clear hover value after panel close', () => {
setMockDate();
jest.useFakeTimers();
const wrapper = mount(
<div>
@ -131,6 +138,68 @@ describe('RangePicker', () => {
expect(
wrapper.find('.ant-calendar-cell').at(23).hasClass('ant-calendar-in-range-cell')
).toBe(true);
resetMockDate();
});
describe('preset range', () => {
it('static range', () => {
const range = [moment().subtract(2, 'd'), moment()];
const format = 'YYYY-MM-DD HH:mm:ss';
const wrapper = mount(
<RangePicker
ranges={{ 'recent two days': range }}
format={format}
/>
);
wrapper.find('.ant-calendar-picker-input').simulate('click');
wrapper.find('.ant-calendar-range-quick-selector a').simulate('click');
expect(
wrapper.find('.ant-calendar-range-picker-input').first().getDOMNode().value
).toBe(range[0].format(format));
expect(
wrapper.find('.ant-calendar-range-picker-input').last().getDOMNode().value
).toBe(range[1].format(format));
});
it('function range', () => {
const range = [moment().subtract(2, 'd'), moment()];
const format = 'YYYY-MM-DD HH:mm:ss';
const wrapper = mount(
<RangePicker
ranges={{ 'recent two days': () => range }}
format={format}
/>
);
wrapper.find('.ant-calendar-picker-input').simulate('click');
wrapper.find('.ant-calendar-range-quick-selector a').simulate('click');
expect(
wrapper.find('.ant-calendar-range-picker-input').first().getDOMNode().value
).toBe(range[0].format(format));
expect(
wrapper.find('.ant-calendar-range-picker-input').last().getDOMNode().value
).toBe(range[1].format(format));
});
});
// https://github.com/ant-design/ant-design/issues/6999
it('input date manually', () => {
const wrapper = mount(<RangePicker open />);
const dateString = '2008-12-31';
const input = wrapper.find('.ant-calendar-input').first();
input.simulate('change', { target: { value: dateString } });
expect(input.getDOMNode().value).toBe(dateString);
});
it('triggers onOk when click on preset range', () => {
const handleOk = jest.fn();
const range = [moment().subtract(2, 'd'), moment()];
const wrapper = mount(
<RangePicker
ranges={{ 'recent two days': range }}
onOk={handleOk}
/>
);
wrapper.find('.ant-calendar-picker-input').simulate('click');
wrapper.find('.ant-calendar-range-quick-selector a').simulate('click');
expect(handleOk).toBeCalledWith(range);
});
});

View File

@ -173,6 +173,7 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
return (
<span
id={props.id}
className={classNames(props.className, props.pickerClass)}
style={props.style}
onFocus={props.onFocus}

View File

@ -3,6 +3,7 @@ import * as moment from 'moment';
import { TimePickerProps } from '../time-picker';
export interface PickerProps {
id?: number | string;
prefixCls?: string;
inputPrefixCls?: string;
format?: string;
@ -53,7 +54,7 @@ export type RangePickerValue =
[moment.Moment] |
[undefined, moment.Moment] |
[moment.Moment, moment.Moment];
export type RangePickerRange = RangePickerValue | (() => RangePickerValue);
export type RangePickerPresetRange = RangePickerValue | (() => RangePickerValue);
export interface RangePickerProps extends PickerProps {
className?: string;
@ -65,7 +66,7 @@ export interface RangePickerProps extends PickerProps {
onOk?: (selectedTime: moment.Moment) => void;
showTime?: TimePickerProps | boolean;
ranges?: {
[range: string]: RangePickerRange,
[range: string]: RangePickerPresetRange,
};
placeholder?: [string, string];
mode?: string | string[];

View File

@ -0,0 +1,18 @@
import CalendarLocale from 'rc-calendar/lib/locale/ku_IQ';
import TimePickerLocale from '../../time-picker/locale/ku_IQ';
// Merge into a locale object
const locale = {
lang: {
placeholder: 'Dîrok hilbijêre',
rangePlaceholder: ['Dîroka destpêkê', 'Dîroka dawîn'],
...CalendarLocale,
},
timePickerLocale: {
...TimePickerLocale,
},
};
// All settings at:
// https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json
export default locale;

View File

@ -1724,6 +1724,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
>
<span
class="ant-calendar-picker"
id="date-picker"
>
<div>
<input
@ -1762,6 +1763,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
>
<span
class="ant-calendar-picker"
id="date-time-picker"
>
<div>
<input
@ -1800,6 +1802,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
>
<span
class="ant-calendar-picker"
id="month-picker"
>
<div>
<input
@ -1838,6 +1841,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
>
<span
class="ant-calendar-picker"
id="range-picker"
tabindex="0"
>
<span
@ -1892,6 +1896,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
>
<span
class="ant-calendar-picker"
id="range-time-picker"
style="width:350px"
tabindex="0"
>

View File

@ -77,6 +77,7 @@ The wrapper.
| -------- | ----------- | ---- | ------- |
| className | container className | string | - |
| style | to customize the styles | object | - |
| hasSider | whether contain Sider in children, don't have to assign it normally. Useful in ssr avoid style flickering | boolean | - |
> APIs of `Layout.Header` `Layout.Footer` `Layout.Content` are the same as that of `Layout`.

View File

@ -78,6 +78,7 @@ title: Layout
| --- | --- | --- | --- |
| className | 容器 className | string | - |
| style | 指定样式 | object | - |
| hasSider | 表示子元素里有 Sider一般不用指定。可用于服务端渲染时避免样式闪动 | boolean | - |
> `Layout.Header` `Layout.Footer` `Layout.Content` API 与 `Layout` 相同

View File

@ -7,6 +7,7 @@ export interface BasicProps {
style?: React.CSSProperties;
prefixCls?: string;
className?: string;
hasSider?: boolean;
}
function generator(props: BasicProps) {
@ -58,9 +59,9 @@ class BasicLayout extends React.Component<BasicProps, any> {
}
render() {
const { prefixCls, className, children, ...others } = this.props;
const { prefixCls, className, children, hasSider, ...others } = this.props;
const divCls = classNames(className, prefixCls, {
[`${prefixCls}-has-sider`]: this.state.siders.length > 0,
[`${prefixCls}-has-sider`]: hasSider || this.state.siders.length > 0,
});
return (
<div className={divCls} {...others}>{children}</div>

View File

@ -39,8 +39,9 @@ import isIS from '../is_IS';
import arEG from '../ar_EG';
import ukUA from '../uk_UA';
import zhCN from '../zh_CN';
import kuIQ from '../ku_IQ';
const locales = [enUS, ptBR, ptPT, ruRU, esES, svSE, frBE, deDE, nlNL, caES, csCZ, koKR, etEE, skSK, jaJP, trTR, zhTW, fiFI, plPL, bgBG, enGB, frFR, nlBE, itIT, viVN, thTH, faIR, elGR, nbNO, srRS, isIS, arEG, ukUA, zhCN];
const locales = [enUS, ptBR, ptPT, ruRU, esES, svSE, frBE, deDE, nlNL, caES, csCZ, koKR, etEE, skSK, jaJP, trTR, zhTW, fiFI, plPL, bgBG, enGB, frFR, nlBE, itIT, viVN, thTH, faIR, elGR, nbNO, srRS, isIS, arEG, ukUA, zhCN, kuIQ];
const { Option } = Select;
const { RangePicker } = DatePicker;

View File

@ -0,0 +1,44 @@
import Pagination from 'rc-pagination/lib/locale/ku_IQ';
import DatePicker from '../date-picker/locale/ku_IQ';
import TimePicker from '../time-picker/locale/ku_IQ';
import Calendar from '../calendar/locale/ku_IQ';
export default {
locale: 'ku-iq',
Pagination,
DatePicker,
TimePicker,
Calendar,
Table: {
filterTitle: 'Menuê peldanka',
filterConfirm: 'Temam',
filterReset: 'Jê bibe',
emptyText: 'Agahî tune',
selectAll: 'Hemî hilbijêre',
selectInvert: 'Hilbijartinan veguhere',
},
Modal: {
okText: 'Temam',
cancelText: 'Betal ke',
justOkText: 'Temam',
},
Popconfirm: {
okText: 'Temam',
cancelText: 'Betal ke',
},
Transfer: {
notFoundContent: 'Peyda Nebû',
searchPlaceholder: 'Lêgerîn',
itemUnit: 'tişt',
itemsUnit: 'tişt',
},
Select: {
notFoundContent: 'Peyda Nebû',
},
Upload: {
uploading: 'Bardike...',
removeFile: 'Pelê rabike',
uploadError: 'Xeta barkirine',
previewFile: 'Pelê pêşbibîne',
},
};

View File

@ -720,3 +720,33 @@ exports[`renders ./components/progress/demo/line-mini.md correctly 1`] = `
</div>
</div>
`;
exports[`renders ./components/progress/demo/segment.md correctly 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:60%;height:8px"
/>
<div
class="ant-progress-success-bg"
style="width:30%;height:8px"
/>
</div>
</div>
<span
class="ant-progress-text"
>
60%
</span>
</div>
</div>
`;

View File

@ -0,0 +1,24 @@
---
order: 9
title:
zh-CN: 分段进度条
en-US: Progress bar with success segment
---
## zh-CN
标准的进度条。
## en-US
A standard progress bar.
````jsx
import { Tooltip, Progress } from 'antd';
ReactDOM.render(
<Tooltip title="3 done / 3 in progress / 4 to do">
<Progress percent={60} successPercent={30} />
</Tooltip>
, mountNode);
````

View File

@ -27,3 +27,4 @@ If it will take a long time to complete an operation, you can use `Progress` to
| strokeWidth `(type=circle)` | to set the width of the circular progress bar, unit: percentage of the canvas width | number | 6 |
| type | to set the type, options: `line` `circle` `dashboard` | string | `line` |
| width `(type=circle)` | to set the canvas width of the circular progress bar, unit: `px` | number | 132 |
| successPercent | segmented success percent, works when `type="line"` | number | 0 |

View File

@ -28,3 +28,4 @@ title: Progress
| strokeWidth `(type=circle)` | 圆形进度条线的宽度,单位是进度条画布宽度的百分比 | number | 6 |
| type | 类型,可选 `line` `circle` `dashboard` | string | line |
| width `(type=circle)` | 圆形进度条画布宽度,单位 px | number | 132 |
| successPercent | 已完成的分段百分比,`type="line"` 时有效 | number | 0 |

View File

@ -15,6 +15,7 @@ export interface ProgressProps {
className?: string;
type?: 'line' | 'circle' | 'dashboard';
percent?: number;
successPercent?: number;
format?: (percent: number) => string;
status?: 'success' | 'active' | 'exception';
showInfo?: boolean;
@ -56,7 +57,7 @@ export default class Progress extends React.Component<ProgressProps, {}> {
render() {
const props = this.props;
const {
prefixCls, className, percent = 0, status, format, trailColor, size,
prefixCls, className, percent = 0, status, format, trailColor, size, successPercent,
type, strokeWidth, width, showInfo, gapDegree = 0, gapPosition, ...restProps,
} = props;
const progressStatus = parseInt(percent.toString(), 10) >= 100 && !('status' in props) ?
@ -83,11 +84,19 @@ export default class Progress extends React.Component<ProgressProps, {}> {
width: `${percent}%`,
height: strokeWidth || (size === 'small' ? 6 : 8),
};
const successPercentStyle = {
width: `${successPercent}%`,
height: strokeWidth || (size === 'small' ? 6 : 8),
};
const successSegment = successPercent !== undefined
? <div className={`${prefixCls}-success-bg`} style={successPercentStyle} />
: null;
progress = (
<div>
<div className={`${prefixCls}-outer`}>
<div className={`${prefixCls}-inner`}>
<div className={`${prefixCls}-bg`} style={percentStyle} />
{successSegment}
</div>
</div>
{progressInfo}

View File

@ -35,6 +35,7 @@
background-color: @progress-remaining-color;
border-radius: 100px;
vertical-align: middle;
position: relative;
}
&-circle-trail {
@ -46,6 +47,7 @@
animation: ~"@{ant-prefix}-progress-appear" .3s;
}
&-success-bg,
&-bg {
border-radius: 100px;
background-color: @progress-default-color;
@ -53,6 +55,13 @@
position: relative;
}
&-success-bg {
background-color: @success-color;
position: absolute;
top: 0;
left: 0;
}
&-text {
word-break: normal;
width: 2em;

View File

@ -47,15 +47,15 @@ Select component to select value from options.
| tokenSeparators | Separator used to tokenize on tag/multiple mode | string\[] | |
| value | Current selected option. | string\|number\|string\[]\|number\[] | - |
| onBlur | Called when blur | function | - |
| onChange | Called when select an option or input value change, or value of input is changed in combobox mode | function(value, label) | - |
| onDeselect | Called when a option is deselected, the params are option's value (or key) . only called for multiple or tags, effective in multiple or tags mode only. | function(value) | - |
| onChange | Called when select an option or input value change, or value of input is changed in combobox mode | function(value, option:Option/Array<Option\>) | - |
| onDeselect | Called when a option is deselected, the params are option's value (or key) . only called for multiple or tags, effective in multiple or tags mode only. | function(value, option:Option) | - |
| onFocus | Called when focus | function | - |
| onInputKeyDown | Called when key pressed | function | - |
| onMouseEnter | Called when mouse enter | function | - |
| onMouseLeave | Called when mouse leave | function | - |
| onPopupScroll | Called when dropdown scrolls | function | - |
| onSearch | Callback function that is fired when input changed. | function(value: string) | |
| onSelect | Called when a option is selected, the params are option's value (or key) and option instance. | function(value, option) | - |
| onSelect | Called when a option is selected, the params are option's value (or key) and option instance. | function(value, option:Option) | - |
### Select Methods

View File

@ -51,14 +51,14 @@ title: Select
| tokenSeparators | 在 tags 和 multiple 模式下自动分词的分隔符 | string\[] | |
| value | 指定当前选中的条目 | string\|string\[]\|number\|number\[] | - |
| onBlur | 失去焦点的时回调 | function | - |
| onChange | 选中 option或 input 的 value 变化combobox 模式下)时,调用此函数 | function(value) | - |
| onDeselect | 取消选中时调用,参数为选中项的 value (或 key) 值,仅在 multiple 或 tags 模式下生效 | function(value) | - |
| onChange | 选中 option或 input 的 value 变化combobox 模式下)时,调用此函数 | function(value, option:Option/Array<Option\>) | - |
| onDeselect | 取消选中时调用,参数为选中项的 value (或 key) 值,仅在 multiple 或 tags 模式下生效 | function(valueoption:Option) | - |
| onFocus | 获得焦点时回调 | function | - |
| onMouseEnter | 鼠标移入时回调 | function | - |
| onMouseLeave | 鼠标移出时回调 | function | - |
| onPopupScroll | 下拉列表滚动时的回调 | function | - |
| onSearch | 文本框值变化时回调 | function(value: string) | |
| onSelect | 被选中时调用,参数为选中项的 value (或 key) 值 | function(value, option) | - |
| onSelect | 被选中时调用,参数为选中项的 value (或 key) 值 | function(value, option:Option) | - |
> 注意,如果发现下拉菜单跟随页面滚动,或者需要在其他弹层中触发 Select请尝试使用 `getPopupContainer={triggerNode => triggerNode.parentNode}` 将下拉弹层渲染节点固定在触发器的父元素中。

View File

@ -45,26 +45,24 @@ export default class SelectionBox extends React.Component<SelectionBoxProps, Sel
}
render() {
const { type, rowIndex, disabled, onChange } = this.props;
const { type, rowIndex, ...rest } = this.props;
const { checked } = this.state;
if (type === 'radio') {
return (
<Radio
disabled={disabled}
onChange={onChange}
value={rowIndex}
checked={checked}
value={rowIndex}
{...rest}
/>
);
} else {
return (
<Checkbox
checked={checked}
{...rest}
/>
);
}
return (
<Checkbox
checked={checked}
disabled={disabled}
onChange={onChange}
/>
);
}
}

View File

@ -597,9 +597,9 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
type={type}
store={this.store}
rowIndex={rowIndex}
disabled={props.disabled}
onChange={handleChange}
defaultSelection={this.getDefaultSelection()}
{...props}
/>
</span>
);

View File

@ -3,16 +3,18 @@ import { mount } from 'enzyme';
import createStore from '../createStore';
import SelectionBox from '../SelectionBox';
const getDefaultStore = (selectedRowKeys) => {
return createStore({
selectedRowKeys: selectedRowKeys || [],
selectionDirty: false,
});
};
describe('SelectionBox', () => {
it('unchecked by selectedRowKeys ', () => {
const store = createStore({
selectedRowKeys: [],
selectionDirty: false,
});
const wrapper = mount(
<SelectionBox
store={store}
store={getDefaultStore()}
rowIndex="1"
disabled={false}
onChange={() => {}}
@ -24,14 +26,9 @@ describe('SelectionBox', () => {
});
it('checked by selectedRowKeys ', () => {
const store = createStore({
selectedRowKeys: ['1'],
selectionDirty: false,
});
const wrapper = mount(
<SelectionBox
store={store}
store={getDefaultStore(['1'])}
rowIndex="1"
disabled={false}
onChange={() => {}}
@ -43,14 +40,9 @@ describe('SelectionBox', () => {
});
it('checked by defaultSelection', () => {
const store = createStore({
selectedRowKeys: [],
selectionDirty: false,
});
const wrapper = mount(
<SelectionBox
store={store}
store={getDefaultStore()}
rowIndex="1"
disabled={false}
onChange={() => {}}
@ -62,11 +54,7 @@ describe('SelectionBox', () => {
});
it('checked when store change', () => {
const store = createStore({
selectedRowKeys: [],
selectionDirty: false,
});
const store = getDefaultStore();
const wrapper = mount(
<SelectionBox
store={store}
@ -84,4 +72,49 @@ describe('SelectionBox', () => {
expect(wrapper.state()).toEqual({ checked: true });
});
it('passes props to Checkbox', () => {
const checkboxProps = {
name: 'testName',
id: 'testId',
};
const wrapper = mount(
<SelectionBox
store={getDefaultStore()}
rowIndex="1"
disabled={false}
onChange={() => {
}}
defaultSelection={['1']}
{...checkboxProps}
/>
);
wrapper.find('Checkbox').forEach((box) => {
expect(box.props().name).toEqual(checkboxProps.name);
expect(box.props().id).toEqual(checkboxProps.id);
});
});
it('passes props to Radios', () => {
const radioProps = {
name: 'testName',
id: 'testId',
};
const wrapper = mount(
<SelectionBox
store={getDefaultStore()}
rowIndex="1"
disabled={false}
onChange={() => {
}}
defaultSelection={['1']}
type="radio"
{...radioProps}
/>
);
wrapper.find('Radio').forEach((radio) => {
expect(radio.props().name).toEqual(radioProps.name);
expect(radio.props().id).toEqual(radioProps.id);
});
});
});

View File

@ -77,6 +77,7 @@ describe('Table.rowSelection', () => {
const rowSelection = {
getCheckboxProps: record => ({
disabled: record.name === 'Lucy',
name: record.name,
}),
};
@ -84,7 +85,9 @@ describe('Table.rowSelection', () => {
const checkboxes = wrapper.find('input');
expect(checkboxes.at(1).props().disabled).toBe(false);
expect(checkboxes.at(1).props().name).toEqual(data[0].name);
expect(checkboxes.at(2).props().disabled).toBe(true);
expect(checkboxes.at(2).props().name).toEqual(data[1].name);
});
it('works with pagination', () => {

View File

@ -9302,6 +9302,7 @@ exports[`renders ./components/table/demo/row-selection.md correctly 1`] = `
>
<input
class="ant-checkbox-input"
name="John Brown"
type="checkbox"
/>
<span
@ -9350,6 +9351,7 @@ exports[`renders ./components/table/demo/row-selection.md correctly 1`] = `
>
<input
class="ant-checkbox-input"
name="Jim Green"
type="checkbox"
/>
<span
@ -9398,6 +9400,7 @@ exports[`renders ./components/table/demo/row-selection.md correctly 1`] = `
>
<input
class="ant-checkbox-input"
name="Joe Black"
type="checkbox"
/>
<span
@ -9447,6 +9450,7 @@ exports[`renders ./components/table/demo/row-selection.md correctly 1`] = `
<input
class="ant-checkbox-input"
disabled=""
name="Disabled User"
type="checkbox"
/>
<span

View File

@ -60,6 +60,7 @@ const rowSelection = {
},
getCheckboxProps: record => ({
disabled: record.name === 'Disabled User', // Column configuration not to be checked
name: record.name,
}),
};

View File

@ -153,6 +153,7 @@ export interface SelectionBoxProps {
type?: RowSelectionType;
defaultSelection: string[];
rowIndex: string;
name?: string;
disabled?: boolean;
onChange: React.ChangeEventHandler<HTMLInputElement>;
}

View File

@ -101,6 +101,11 @@ exports[`Tabs tabPosition remove card 1`] = `
key="1"
onClick={[Function]}
role="tab"
style={
Object {
"marginRight": undefined,
}
}
>
foo
</div>

View File

@ -35,6 +35,7 @@ Ant Design has 3 types of Tabs for different situations.
| onNextClick | Callback executed when next button is clicked | Function | - |
| onPrevClick | Callback executed when prev button is clicked | Function | - |
| onTabClick | Callback executed when tab is clicked | Function | - |
| tabBarGutter | The gap between tabs | number | - |
### Tabs.TabPane

View File

@ -29,6 +29,7 @@ export interface TabsProps {
prefixCls?: string;
className?: string;
animated?: boolean | { inkBar: boolean; tabPane: boolean; };
tabBarGutter?: number;
}
// Tabs
@ -99,6 +100,7 @@ export default class Tabs extends React.Component<TabsProps, any> {
onPrevClick,
onNextClick,
animated = true,
tabBarGutter,
} = this.props;
let { inkBarAnimated, tabPaneAnimated } = typeof animated === 'object' ? {
@ -171,6 +173,7 @@ export default class Tabs extends React.Component<TabsProps, any> {
onPrevClick={onPrevClick}
onNextClick={onNextClick}
style={tabBarStyle}
tabBarGutter={tabBarGutter}
/>
);

View File

@ -38,6 +38,7 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。
| onNextClick | next 按钮被点击的回调 | Function | 无 |
| onPrevClick | prev 按钮被点击的回调 | Function | 无 |
| onTabClick | tab 被点击的回调 | Function | 无 |
| tabBarGutter | tabs 之间的间隙 | number | 无 |
### Tabs.TabPane

View File

@ -0,0 +1,5 @@
const locale = {
placeholder: 'Demê hilbijêre',
};
export default locale;

10
package.json Normal file → Executable file
View File

@ -51,10 +51,10 @@
"omit.js": "^1.0.0",
"prop-types": "^15.5.7",
"rc-animate": "^2.4.1",
"rc-calendar": "~9.4.0",
"rc-calendar": "~9.5.0",
"rc-cascader": "~0.12.0",
"rc-checkbox": "~2.1.1",
"rc-collapse": "~1.7.5",
"rc-collapse": "~1.8.0",
"rc-dialog": "~7.1.0",
"rc-dropdown": "~2.1.0",
"rc-editor-mention": "^1.0.2",
@ -62,15 +62,15 @@
"rc-input-number": "~4.0.0",
"rc-menu": "~6.2.0",
"rc-notification": "~3.0.0",
"rc-pagination": "~1.14.0",
"rc-pagination": "~1.15.0",
"rc-progress": "~2.2.2",
"rc-rate": "~2.4.0",
"rc-select": "~7.5.0",
"rc-select": "~7.7.0",
"rc-slider": "~8.5.0",
"rc-steps": "~3.0.0",
"rc-switch": "~1.6.0",
"rc-table": "~6.1.0",
"rc-tabs": "~9.1.2",
"rc-tabs": "~9.2.0",
"rc-time-picker": "~3.2.1",
"rc-tooltip": "~3.7.0",
"rc-tree": "~1.7.0",