mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 09:26:06 +08:00
Merge branch 'feature-3.3.0'
This commit is contained in:
commit
ed70ba694e
@ -366,6 +366,34 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/smooth-closed.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-alert ant-alert-success ant-alert-no-icon"
|
||||
data-show="true"
|
||||
>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Alert Message Text
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
<a
|
||||
class="ant-alert-close-icon"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-cross"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<p>
|
||||
placeholder text here
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/style.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
|
48
components/alert/demo/smooth-closed.md
Normal file
48
components/alert/demo/smooth-closed.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 平滑地卸载
|
||||
en-US: Smoothly Unmount
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
平滑、自然的卸载提示
|
||||
|
||||
## en-US
|
||||
|
||||
Smoothly and unaffectedly unmount Alert.
|
||||
|
||||
````jsx
|
||||
import { Alert } from 'antd';
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
visiable: true,
|
||||
}
|
||||
handleClose = () => {
|
||||
this.setState({ visiable: false });
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
this.state.visiable ? (
|
||||
<Alert
|
||||
message="Alert Message Text"
|
||||
type="success"
|
||||
closable
|
||||
afterClose={this.handleClose}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
<p>placeholder text here</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<App />
|
||||
, mountNode);
|
||||
````
|
@ -21,6 +21,8 @@ export interface AlertProps {
|
||||
description?: React.ReactNode;
|
||||
/** Callback when close Alert */
|
||||
onClose?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
/** Trigger when animation ending of Alert */
|
||||
afterClose?: Function;
|
||||
/** Whether to show icon */
|
||||
showIcon?: boolean;
|
||||
iconType?: string;
|
||||
@ -56,6 +58,7 @@ export default class Alert extends React.Component<AlertProps, any> {
|
||||
closed: true,
|
||||
closing: true,
|
||||
});
|
||||
(this.props.afterClose || noop)();
|
||||
}
|
||||
render() {
|
||||
let {
|
||||
|
@ -15,6 +15,7 @@ export interface HeaderProps {
|
||||
onValueChange?: (value: moment.Moment) => void;
|
||||
onTypeChange?: (type: string) => void;
|
||||
value: any;
|
||||
validRange ?: [moment.Moment, moment.Moment];
|
||||
}
|
||||
|
||||
export default class Header extends React.Component<HeaderProps, any> {
|
||||
@ -27,11 +28,21 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
private calenderHeaderNode: HTMLDivElement;
|
||||
|
||||
getYearSelectElement(year: number) {
|
||||
const { yearSelectOffset, yearSelectTotal, locale, prefixCls, fullscreen } = this.props;
|
||||
const start = year - (yearSelectOffset as number);
|
||||
const end = start + (yearSelectTotal as number);
|
||||
const {
|
||||
yearSelectOffset,
|
||||
yearSelectTotal,
|
||||
locale,
|
||||
prefixCls,
|
||||
fullscreen,
|
||||
validRange,
|
||||
} = this.props;
|
||||
let start = year - (yearSelectOffset as number);
|
||||
let end = start + (yearSelectTotal as number);
|
||||
if (validRange) {
|
||||
start = validRange[0].get('year');
|
||||
end = validRange[1].get('year') + 1;
|
||||
}
|
||||
const suffix = locale.year === '年' ? '年' : '';
|
||||
|
||||
const options: React.ReactElement<any>[] = [];
|
||||
for (let index = start; index < end; index++) {
|
||||
options.push(<Option key={`${index}`}>{index + suffix}</Option>);
|
||||
@ -63,13 +74,22 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
|
||||
getMonthSelectElement(month: number, months: number[]) {
|
||||
const props = this.props;
|
||||
const { prefixCls, fullscreen } = props;
|
||||
const { prefixCls, fullscreen, validRange, value } = props;
|
||||
const options: React.ReactElement<any>[] = [];
|
||||
|
||||
for (let index = 0; index < 12; index++) {
|
||||
let start = 0;
|
||||
let end = 12;
|
||||
if (validRange) {
|
||||
const [rangeStart, rangeEnd] = validRange;
|
||||
const currentYear = value.get('year');
|
||||
if (rangeEnd.get('year') === currentYear) {
|
||||
end = rangeEnd.get('month') + 1;
|
||||
} else {
|
||||
start = rangeStart.get('month');
|
||||
}
|
||||
}
|
||||
for (let index = start; index < end; index++) {
|
||||
options.push(<Option key={`${index}`}>{months[index]}</Option>);
|
||||
}
|
||||
|
||||
return (
|
||||
<Select
|
||||
size={fullscreen ? 'default' : 'small'}
|
||||
@ -85,8 +105,21 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
}
|
||||
|
||||
onYearChange = (year: string) => {
|
||||
const newValue = this.props.value.clone();
|
||||
const { value, validRange } = this.props;
|
||||
const newValue = value.clone();
|
||||
newValue.year(parseInt(year, 10));
|
||||
// switch the month so that it remains within range when year changes
|
||||
if (validRange) {
|
||||
const [ start, end ] = validRange;
|
||||
const newYear = newValue.get('year');
|
||||
const newMonth = newValue.get('month');
|
||||
if (newYear === end.get('year') && newMonth > end.get('month')) {
|
||||
newValue.month(end.get('month'));
|
||||
}
|
||||
if (newYear === start.get('year') && newMonth < start.get('month')) {
|
||||
newValue.month(start.get('month'));
|
||||
}
|
||||
}
|
||||
|
||||
const onValueChange = this.props.onValueChange;
|
||||
if (onValueChange) {
|
||||
|
@ -15,6 +15,66 @@ describe('Calendar', () => {
|
||||
expect(Moment.isMoment(value)).toBe(true);
|
||||
});
|
||||
|
||||
it('only Valid range should be selectable', () => {
|
||||
const onSelect = jest.fn();
|
||||
const validRange = [Moment('2018-02-02'), Moment('2018-02-18')];
|
||||
const wrapper = mount(
|
||||
<Calendar onSelect={onSelect} validRange={validRange} defaultValue={Moment('2018-02-02')} />
|
||||
);
|
||||
wrapper.find('[title="February 1, 2018"]').at(0).simulate('click');
|
||||
wrapper.find('[title="February 2, 2018"]').at(0).simulate('click');
|
||||
expect(onSelect.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it('dates other than in valid range should be disabled', () => {
|
||||
const onSelect = jest.fn();
|
||||
const validRange = [Moment('2018-02-02'), Moment('2018-02-18')];
|
||||
const wrapper = mount(
|
||||
<Calendar onSelect={onSelect} validRange={validRange} defaultValue={Moment('2018-02-02')} />
|
||||
);
|
||||
wrapper.find('[title="February 20, 2018"]').at(0).simulate('click');
|
||||
const elem = wrapper.find('[title="February 20, 2018"]').hasClass('ant-fullcalendar-disabled-cell');
|
||||
expect(elem).toEqual(true);
|
||||
expect(onSelect.mock.calls.length).toBe(0);
|
||||
});
|
||||
|
||||
it('months other than in valid range should be disabled', () => {
|
||||
const onSelect = jest.fn();
|
||||
const validRange = [Moment('2018-02-02'), Moment('2018-05-18')];
|
||||
const wrapper = mount(
|
||||
<Calendar onSelect={onSelect} validRange={validRange} defaultValue={Moment('2018-02-02')} mode="year" />
|
||||
);
|
||||
expect(wrapper.find('[title="Jan"]').at(0).hasClass('ant-fullcalendar-month-panel-cell-disabled')).toBe(true);
|
||||
expect(wrapper.find('[title="Feb"]').at(0).hasClass('ant-fullcalendar-month-panel-cell-disabled')).toBe(false);
|
||||
expect(wrapper.find('[title="Jun"]').at(0).hasClass('ant-fullcalendar-month-panel-cell-disabled')).toBe(true);
|
||||
wrapper.find('[title="Jan"]').at(0).simulate('click');
|
||||
wrapper.find('[title="Mar"]').at(0).simulate('click');
|
||||
expect(onSelect.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it('months other than in valid range should not be shown in header', () => {
|
||||
const validRange = [Moment('2017-02-02'), Moment('2018-05-18')];
|
||||
const wrapper = mount(
|
||||
<Calendar validRange={validRange} />
|
||||
);
|
||||
wrapper.find('.ant-fullcalendar-year-select').hostNodes().simulate('click');
|
||||
wrapper.find('.ant-select-dropdown-menu-item').first().simulate('click');
|
||||
wrapper.find('.ant-fullcalendar-month-select').hostNodes().simulate('click');
|
||||
// 2 years and 11 months
|
||||
expect(wrapper.find('.ant-select-dropdown-menu-item').length).toBe(13);
|
||||
});
|
||||
|
||||
it('getDateRange should returns a disabledDate function', () => {
|
||||
const validRange = [Moment('2018-02-02'), Moment('2018-05-18')];
|
||||
const wrapper = mount(
|
||||
<Calendar validRange={validRange} defaultValue={Moment('2018-02-02')} />
|
||||
);
|
||||
const instance = wrapper.instance();
|
||||
const disabledDate = instance.getDateRange(validRange);
|
||||
expect(disabledDate(Moment('2018-06-02'))).toBe(true);
|
||||
expect(disabledDate(Moment('2018-04-02'))).toBe(false);
|
||||
});
|
||||
|
||||
it('Calendar should change mode by prop', () => {
|
||||
const monthMode = 'month';
|
||||
const yearMode = 'year';
|
||||
|
@ -40,6 +40,7 @@ When data is in the form of dates, such as schedules, timetables, prices calenda
|
||||
| mode | The display mode of the calendar | `month` \| `year` | `month` |
|
||||
| monthCellRender | Customize the display of the month cell, the returned content will be appended to the cell | function(date: moment): ReactNode | - |
|
||||
| monthFullCellRender | Customize the display of the month cell, the returned content will override the cell | function(date: moment): ReactNode | - |
|
||||
| validRange | to set valid range | \[[moment](http://momentjs.com/), [moment](http://momentjs.com/)] | - |
|
||||
| value | The current selected date | [moment](http://momentjs.com/) | current date |
|
||||
| onPanelChange | Callback for when panel changes | function(date: moment, mode: string) | - |
|
||||
| onSelect | Callback for when a date is selected | function(date: moment) | - |
|
||||
|
@ -37,6 +37,7 @@ export interface CalendarProps {
|
||||
onPanelChange?: (date?: moment.Moment, mode?: CalendarMode) => void;
|
||||
onSelect?: (date?: moment.Moment) => void;
|
||||
disabledDate?: (current: moment.Moment) => boolean;
|
||||
validRange ?: [moment.Moment, moment.Moment];
|
||||
}
|
||||
|
||||
export interface CalendarState {
|
||||
@ -166,6 +167,21 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
this.setValue(value, 'select');
|
||||
}
|
||||
|
||||
getDateRange = (
|
||||
validRange: [moment.Moment, moment.Moment],
|
||||
disabledDate?: (current: moment.Moment) => boolean,
|
||||
) => (current: moment.Moment) => {
|
||||
if (!current) {
|
||||
return false;
|
||||
}
|
||||
const [ startDate, endDate ] = validRange;
|
||||
const inRange = !current.isBetween(startDate, endDate, 'days', '[]');
|
||||
if (disabledDate) {
|
||||
return (disabledDate(current) || inRange);
|
||||
}
|
||||
return inRange;
|
||||
}
|
||||
|
||||
renderCalendar = (locale: any, localeCode: string) => {
|
||||
const { state, props } = this;
|
||||
const { value, mode } = state;
|
||||
@ -183,6 +199,12 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
const monthCellRender = monthFullCellRender || this.monthCellRender;
|
||||
const dateCellRender = dateFullCellRender || this.dateCellRender;
|
||||
|
||||
let disabledDate = props.disabledDate;
|
||||
|
||||
if (props.validRange) {
|
||||
disabledDate = this.getDateRange(props.validRange, disabledDate);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cls} style={style}>
|
||||
<Header
|
||||
@ -193,9 +215,11 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
prefixCls={prefixCls}
|
||||
onTypeChange={this.onHeaderTypeChange}
|
||||
onValueChange={this.onHeaderValueChange}
|
||||
validRange={props.validRange}
|
||||
/>
|
||||
<FullCalendar
|
||||
{...props}
|
||||
disabledDate={disabledDate}
|
||||
Select={noop}
|
||||
locale={locale.lang}
|
||||
type={type}
|
||||
|
@ -41,6 +41,7 @@ title: Calendar
|
||||
| mode | 初始模式,`month/year` | string | month |
|
||||
| monthCellRender | 自定义渲染月单元格,返回内容会被追加到单元格 | function(date: moment): ReactNode | 无 |
|
||||
| monthFullCellRender | 自定义渲染月单元格,返回内容覆盖单元格 | function(date: moment): ReactNode | 无 |
|
||||
| validRange | 设置可以显示的日期 | \[[moment](http://momentjs.com/), [moment](http://momentjs.com/)] | 无 |
|
||||
| value | 展示日期 | [moment](http://momentjs.com/) | 当前日期 |
|
||||
| onPanelChange | 日期面板变化回调 | function(date: moment, mode: string) | 无 |
|
||||
| onSelect | 点击选择日期回调 | function(date: moment) | 无 |
|
||||
|
@ -52,12 +52,16 @@ function onChange(value, selectedOptions) {
|
||||
console.log(value, selectedOptions);
|
||||
}
|
||||
|
||||
function filter(inputValue, path) {
|
||||
return (path.some(option => (option.label).toLowerCase().indexOf(inputValue.toLowerCase()) > -1));
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<Cascader
|
||||
options={options}
|
||||
onChange={onChange}
|
||||
placeholder="Please select"
|
||||
showSearch
|
||||
showSearch={{ filter }}
|
||||
/>,
|
||||
mountNode
|
||||
);
|
||||
|
@ -47,6 +47,7 @@ The following APIs are shared by DatePicker, MonthPicker, RangePicker, WeekPicke
|
||||
| open | open state of picker | boolean | - |
|
||||
| placeholder | placeholder of date input | string\|RangePicker\[] | - |
|
||||
| popupStyle | to customize the style of the popup calendar | object | {} |
|
||||
| dropdownClassName | to customize the className of the popup calendar | string | - |
|
||||
| size | determine the size of the input box, the height of `large` and `small`, are 40px and 24px respectively, while default size is 32px | string | - |
|
||||
| style | to customize the style of the input box | object | {} |
|
||||
| onOpenChange | a callback function, can be executed whether the popup calendar is popped up or closed | function(status) | - |
|
||||
|
@ -47,7 +47,8 @@ subtitle: 日期选择框
|
||||
| locale | 国际化配置 | object | [默认配置](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) |
|
||||
| open | 控制弹层是否展开 | boolean | - |
|
||||
| placeholder | 输入框提示文字 | string\|RangePicker\[] | - |
|
||||
| popupStyle | 格外的弹出日历样式 | object | {} |
|
||||
| popupStyle | 额外的弹出日历样式 | object | {} |
|
||||
| dropdownClassName | 额外的弹出日历 className | string | - |
|
||||
| size | 输入框大小,`large` 高度为 40px,`small` 为 24px,默认是 32px | string | 无 |
|
||||
| style | 自定义输入框样式 | object | {} |
|
||||
| onOpenChange | 弹出日历和关闭日历的回调 | function(status) | 无 |
|
||||
|
@ -12,6 +12,7 @@ export interface PickerProps {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
popupStyle?: React.CSSProperties;
|
||||
dropdownClassName?: string;
|
||||
locale?: any;
|
||||
size?: 'large' | 'small' | 'default';
|
||||
getCalendarContainer?: (triggerNode: Element) => HTMLElement;
|
||||
|
@ -29,6 +29,30 @@ exports[`renders ./components/divider/demo/horizontal.md correctly 1`] = `
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-with-text-left"
|
||||
>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
With Text
|
||||
</span>
|
||||
</div>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-with-text-right"
|
||||
>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
With Text
|
||||
</span>
|
||||
</div>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -25,6 +25,10 @@ ReactDOM.render(
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.</p>
|
||||
<Divider dashed />
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.</p>
|
||||
<Divider orientation="left">With Text</Divider>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.</p>
|
||||
<Divider orientation="right">With Text</Divider>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.</p>
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
||||
|
@ -20,3 +20,4 @@ A divider line separates different content.
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| dashed | whether line is dashed | Boolean | false |
|
||||
| type | direction type of divider | enum: `horizontal` `vertical` | `horizontal` |
|
||||
| orientation | this is optional, if not set it will have the text in the center | enum: `left` `right` | `center` |
|
||||
|
@ -4,6 +4,7 @@ import classNames from 'classnames';
|
||||
export interface DividerProps {
|
||||
prefixCls?: string;
|
||||
type?: 'horizontal' | 'vertical';
|
||||
orientation?: 'left' | 'right';
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
dashed?: boolean;
|
||||
@ -13,14 +14,16 @@ export interface DividerProps {
|
||||
export default function Divider({
|
||||
prefixCls = 'ant',
|
||||
type = 'horizontal',
|
||||
orientation = '',
|
||||
className,
|
||||
children,
|
||||
dashed,
|
||||
...restProps,
|
||||
}: DividerProps) {
|
||||
const orientationPrefix = (orientation.length > 0) ? '-' + orientation : orientation;
|
||||
const classString = classNames(
|
||||
className, `${prefixCls}-divider`, `${prefixCls}-divider-${type}`, {
|
||||
[`${prefixCls}-divider-with-text`]: children,
|
||||
[`${prefixCls}-divider-with-text${orientationPrefix}`]: children,
|
||||
[`${prefixCls}-divider-dashed`]: !!dashed,
|
||||
});
|
||||
return (
|
||||
|
@ -44,17 +44,81 @@
|
||||
transform: translateY(50%);
|
||||
}
|
||||
}
|
||||
|
||||
&-inner-text {
|
||||
display: inline-block;
|
||||
padding: 0 24px;
|
||||
}
|
||||
&-horizontal&-with-text-left {
|
||||
display: table;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
background: transparent;
|
||||
font-weight: 500;
|
||||
color: @heading-color;
|
||||
font-size: @font-size-base;
|
||||
margin: 16px 0;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: table-cell;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
width: 5%;
|
||||
border-top: 1px solid @border-color-split;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
display: table-cell;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
width: 95%;
|
||||
border-top: 1px solid @border-color-split;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
&-inner-text {
|
||||
display: inline-block;
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&-horizontal&-with-text-right {
|
||||
display: table;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
background: transparent;
|
||||
font-weight: 500;
|
||||
color: @heading-color;
|
||||
font-size: @font-size-base;
|
||||
margin: 16px 0;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: table-cell;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
width: 95%;
|
||||
border-top: 1px solid @border-color-split;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
display: table-cell;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
width: 5%;
|
||||
border-top: 1px solid @border-color-split;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
&-inner-text {
|
||||
display: inline-block;
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
&-dashed {
|
||||
background: none;
|
||||
border-top: 1px dashed @border-color-split;
|
||||
}
|
||||
|
||||
&-horizontal&-with-text&-dashed {
|
||||
border-top: 0;
|
||||
&:before,
|
||||
|
@ -47,6 +47,7 @@ export interface ModalProps {
|
||||
bodyStyle?: React.CSSProperties;
|
||||
maskStyle?: React.CSSProperties;
|
||||
mask?: boolean;
|
||||
keyboard?: boolean;
|
||||
}
|
||||
|
||||
export interface ModalFuncProps {
|
||||
@ -68,6 +69,7 @@ export interface ModalFuncProps {
|
||||
okCancel?: boolean;
|
||||
style?: React.CSSProperties;
|
||||
type?: string;
|
||||
keyboard?: boolean;
|
||||
}
|
||||
|
||||
export type ModalFunc = (props: ModalFuncProps) => {
|
||||
|
@ -14,7 +14,7 @@ interface ConfirmDialogProps extends ModalFuncProps {
|
||||
const IS_REACT_16 = !!ReactDOM.createPortal;
|
||||
|
||||
const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
const { onCancel, onOk, close, zIndex, afterClose, visible } = props;
|
||||
const { onCancel, onOk, close, zIndex, afterClose, visible, keyboard } = props;
|
||||
const iconType = props.iconType || 'question-circle';
|
||||
const okType = props.okType || 'primary';
|
||||
const prefixCls = props.prefixCls || 'ant-confirm';
|
||||
@ -55,6 +55,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
width={width}
|
||||
zIndex={zIndex}
|
||||
afterClose={afterClose}
|
||||
keyboard={keyboard}
|
||||
>
|
||||
<div className={`${prefixCls}-body-wrapper`}>
|
||||
<div className={`${prefixCls}-body`}>
|
||||
|
@ -3,7 +3,7 @@ import * as ReactDOM from 'react-dom';
|
||||
import RcTable from 'rc-table';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import Pagination, { PaginationProps } from '../pagination';
|
||||
import Pagination from '../pagination';
|
||||
import Icon from '../icon';
|
||||
import Spin from '../spin';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
@ -28,6 +28,7 @@ import {
|
||||
CompareFn,
|
||||
TableStateFilters,
|
||||
SelectionItemSelectFn,
|
||||
TablePaginationConfig,
|
||||
} from './interface';
|
||||
import { RadioChangeEvent } from '../radio';
|
||||
import { CheckboxChangeEvent } from '../checkbox';
|
||||
@ -149,7 +150,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
}
|
||||
|
||||
getDefaultPagination(props: TableProps<T>) {
|
||||
const pagination: PaginationProps = props.pagination || {};
|
||||
const pagination: TablePaginationConfig = props.pagination || {};
|
||||
return this.hasPagination(props) ?
|
||||
{
|
||||
...defaultPagination,
|
||||
@ -227,7 +228,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
};
|
||||
}
|
||||
|
||||
setSelectedRowKeys(selectedRowKeys: string[], { selectWay, record, checked, changeRowKeys }: any) {
|
||||
setSelectedRowKeys(selectedRowKeys: string[], { selectWay, record, checked, changeRowKeys, nativeEvent }: any) {
|
||||
const { rowSelection = {} as any } = this.props;
|
||||
if (rowSelection && !('selectedRowKeys' in rowSelection)) {
|
||||
this.store.setState({ selectedRowKeys });
|
||||
@ -243,7 +244,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
rowSelection.onChange(selectedRowKeys, selectedRows);
|
||||
}
|
||||
if (selectWay === 'onSelect' && rowSelection.onSelect) {
|
||||
rowSelection.onSelect(record, checked, selectedRows);
|
||||
rowSelection.onSelect(record, checked, selectedRows, nativeEvent);
|
||||
} else if (selectWay === 'onSelectAll' && rowSelection.onSelectAll) {
|
||||
const changeRows = data.filter(
|
||||
(row, i) => changeRowKeys.indexOf(this.getRecordKey(row, i)) >= 0,
|
||||
@ -446,6 +447,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
|
||||
handleSelect = (record: T, rowIndex: number, e: CheckboxChangeEvent) => {
|
||||
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);
|
||||
let key = this.getRecordKey(record, rowIndex);
|
||||
@ -461,11 +463,14 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
selectWay: 'onSelect',
|
||||
record,
|
||||
checked,
|
||||
changeRowKeys: void(0),
|
||||
nativeEvent,
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
let key = this.getRecordKey(record, rowIndex);
|
||||
@ -477,6 +482,8 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
selectWay: 'onSelect',
|
||||
record,
|
||||
checked,
|
||||
changeRowKeys: void(0),
|
||||
nativeEvent,
|
||||
});
|
||||
}
|
||||
|
||||
@ -642,6 +649,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
render: this.renderSelectionBox(rowSelection.type),
|
||||
className: selectionColumnClass,
|
||||
fixed: rowSelection.fixed,
|
||||
width: rowSelection.columnWidth,
|
||||
};
|
||||
if (rowSelection.type !== 'radio') {
|
||||
const checkboxAllDisabled = data.every((item, index) => this.getCheckboxPropsByItem(item, index).disabled);
|
||||
@ -780,7 +788,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
}
|
||||
}
|
||||
|
||||
renderPagination() {
|
||||
renderPagination(paginationPosition: string) {
|
||||
// 强制不需要分页
|
||||
if (!this.hasPagination()) {
|
||||
return null;
|
||||
@ -792,10 +800,11 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
} else if (this.props.size as string === 'middle' || this.props.size === 'small') {
|
||||
size = 'small';
|
||||
}
|
||||
let position = pagination.position || 'bottom';
|
||||
let total = pagination.total || this.getLocalData().length;
|
||||
return (total > 0) ? (
|
||||
return (total > 0 && (position === paginationPosition || position === 'both')) ? (
|
||||
<Pagination
|
||||
key="pagination"
|
||||
key={`pagination-${paginationPosition}`}
|
||||
{...pagination}
|
||||
className={classNames(pagination.className, `${this.props.prefixCls}-pagination`)}
|
||||
onChange={this.handlePageChange}
|
||||
@ -995,8 +1004,9 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
{...loading}
|
||||
className={loading.spinning ? `${paginationPatchClass} ${prefixCls}-spin-holder` : ''}
|
||||
>
|
||||
{this.renderPagination('top')}
|
||||
{table}
|
||||
{this.renderPagination()}
|
||||
{this.renderPagination('bottom')}
|
||||
</Spin>
|
||||
</div>
|
||||
);
|
||||
|
@ -131,4 +131,17 @@ describe('Table.pagination', () => {
|
||||
wrapper.setProps({ dataSource: [data[0]] });
|
||||
expect(wrapper.find('.ant-pagination-item-1').hasClass('ant-pagination-item-active')).toBe(true);
|
||||
});
|
||||
|
||||
it('specify the position of pagination', () => {
|
||||
const wrapper = mount(createTable({ pagination: { position: 'top' } }));
|
||||
expect(wrapper.find('.ant-spin-container').children()).toHaveLength(2);
|
||||
expect(wrapper.find('.ant-spin-container').childAt(0).find('.ant-pagination')).toHaveLength(1);
|
||||
wrapper.setProps({ pagination: { position: 'bottom' } });
|
||||
expect(wrapper.find('.ant-spin-container').children()).toHaveLength(2);
|
||||
expect(wrapper.find('.ant-spin-container').childAt(1).find('.ant-pagination')).toHaveLength(1);
|
||||
wrapper.setProps({ pagination: { position: 'both' } });
|
||||
expect(wrapper.find('.ant-spin-container').children()).toHaveLength(3);
|
||||
expect(wrapper.find('.ant-spin-container').childAt(0).find('.ant-pagination')).toHaveLength(1);
|
||||
expect(wrapper.find('.ant-spin-container').childAt(2).find('.ant-pagination')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
@ -154,11 +154,11 @@ describe('Table.rowSelection', () => {
|
||||
wrapper.find('input').last().simulate('change', { target: { checked: true } });
|
||||
|
||||
expect(handleChange).toBeCalledWith([3], [{ key: 3, name: 'Jerry' }]);
|
||||
expect(handleSelect).toBeCalledWith(
|
||||
{ key: 3, name: 'Jerry' },
|
||||
true,
|
||||
[{ key: 3, name: 'Jerry' }]
|
||||
);
|
||||
expect(handleSelect.mock.calls.length).toBe(1);
|
||||
expect(handleSelect.mock.calls[0][0]).toEqual({ key: 3, name: 'Jerry' });
|
||||
expect(handleSelect.mock.calls[0][1]).toEqual(true);
|
||||
expect(handleSelect.mock.calls[0][2]).toEqual([{ key: 3, name: 'Jerry' }]);
|
||||
expect(handleSelect.mock.calls[0][3].type).toBe('change');
|
||||
});
|
||||
|
||||
it('fires selectAll event', () => {
|
||||
|
@ -1359,8 +1359,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
class="ant-form-item-children"
|
||||
>
|
||||
<span
|
||||
checked=""
|
||||
class="ant-switch ant-switch-checked"
|
||||
class="ant-switch"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
@ -1644,14 +1643,43 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-spin-container"
|
||||
>
|
||||
<ul
|
||||
class="ant-pagination ant-table-pagination"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<li
|
||||
aria-disabled="true"
|
||||
class="ant-pagination-disabled ant-pagination-prev"
|
||||
tabindex="0"
|
||||
title="Previous Page"
|
||||
>
|
||||
<a
|
||||
class="ant-pagination-item-link"
|
||||
/>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"
|
||||
tabindex="0"
|
||||
title="1"
|
||||
>
|
||||
<a>
|
||||
1
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
aria-disabled="true"
|
||||
class="ant-pagination-disabled ant-pagination-next"
|
||||
tabindex="0"
|
||||
title="Next Page"
|
||||
>
|
||||
<a
|
||||
class="ant-pagination-item-link"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
<div
|
||||
class="ant-table ant-table-default ant-table-scroll-position-left"
|
||||
>
|
||||
<div
|
||||
class="ant-table-title"
|
||||
>
|
||||
Here is title
|
||||
</div>
|
||||
<div
|
||||
class="ant-table-content"
|
||||
>
|
||||
|
@ -65,15 +65,16 @@ const title = () => 'Here is title';
|
||||
const showHeader = true;
|
||||
const footer = () => 'Here is footer';
|
||||
const scroll = { y: 240 };
|
||||
const pagination = { position: 'both' };
|
||||
|
||||
class Demo extends React.Component {
|
||||
state = {
|
||||
bordered: false,
|
||||
loading: false,
|
||||
pagination: true,
|
||||
pagination,
|
||||
size: 'default',
|
||||
expandedRowRender,
|
||||
title,
|
||||
title: false,
|
||||
showHeader,
|
||||
footer,
|
||||
rowSelection: {},
|
||||
@ -114,6 +115,10 @@ class Demo extends React.Component {
|
||||
this.setState({ scroll: enable ? scroll : undefined });
|
||||
}
|
||||
|
||||
handlePaginationChange = (enable) => {
|
||||
this.setState({ pagination: enable ? pagination : false });
|
||||
}
|
||||
|
||||
render() {
|
||||
const state = this.state;
|
||||
return (
|
||||
@ -127,7 +132,7 @@ class Demo extends React.Component {
|
||||
<Switch checked={state.loading} onChange={this.handleToggle('loading')} />
|
||||
</FormItem>
|
||||
<FormItem label="Pagination">
|
||||
<Switch checked={state.pagination} onChange={this.handleToggle('pagination')} />
|
||||
<Switch checked={state.pagination} onChange={this.handlePaginationChange} />
|
||||
</FormItem>
|
||||
<FormItem label="Title">
|
||||
<Switch checked={!!state.title} onChange={this.handleTitleChange} />
|
||||
|
@ -65,7 +65,7 @@ const columns = [{
|
||||
| indentSize | Indent size in pixels of tree data | number | 15 |
|
||||
| loading | Loading status of table | boolean\|[object](https://ant.design/components/spin-cn/#API) ([more](https://github.com/ant-design/ant-design/issues/4544#issuecomment-271533135)) | `false` |
|
||||
| locale | i18n text including filter, sort, empty text, etc | object | filterConfirm: 'Ok' <br> filterReset: 'Reset' <br> emptyText: 'No Data' <br> [Default](https://github.com/ant-design/ant-design/issues/575#issuecomment-159169511) |
|
||||
| pagination | Pagination [config](/components/pagination/), hide it by setting it to `false` | object | |
|
||||
| pagination | Pagination [config](#pagination) or [`Pagination`] (/components/pagination/), hide it by setting it to `false` | object | |
|
||||
| rowClassName | Row's className | Function(record, index):string | - |
|
||||
| rowKey | Row's unique key, could be a string or function that returns a string | string\|Function(record):string | `key` |
|
||||
| rowSelection | Row selection [config](#rowSelection) | object | null |
|
||||
@ -135,6 +135,16 @@ One of the Table `columns` prop for describing the table's columns, Column has t
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| title | Title of the column group | string\|ReactNode | - |
|
||||
|
||||
### pagination
|
||||
|
||||
Properties for pagination.
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| position | specify the position of `Pagination` | 'top' \| 'bottom' \| 'both' | 'bottom' |
|
||||
|
||||
More about pagination, please check [`Pagination`](/components/pagination/).
|
||||
|
||||
### rowSelection
|
||||
|
||||
Properties for row selection.
|
||||
@ -145,10 +155,11 @@ Properties for row selection.
|
||||
| getCheckboxProps | Get Checkbox or Radio props | Function(record) | - |
|
||||
| hideDefaultSelections | Remove the default `Select All` and `Select Invert` selections | boolean | `false` |
|
||||
| selectedRowKeys | Controlled selected row keys | string\[] | \[] |
|
||||
| columnWidth | Set the width of the selection column | string\|number | - |
|
||||
| selections | Custom selection [config](#rowSelection), only displays default selections when set to `true` | object\[]\|boolean | - |
|
||||
| type | `checkbox` or `radio` | `checkbox` \| `radio` | `checkbox` |
|
||||
| onChange | Callback executed when selected rows change | Function(selectedRowKeys, selectedRows) | - |
|
||||
| onSelect | Callback executed when select/deselect one row | Function(record, selected, selectedRows) | - |
|
||||
| onSelect | Callback executed when select/deselect one row | Function(record, selected, selectedRows, nativeEvent) | - |
|
||||
| onSelectAll | Callback executed when select/deselect all rows | Function(selected, selectedRows, changeRows) | - |
|
||||
| onSelectInvert | Callback executed when row selection is inverted | Function(selectedRows) | - |
|
||||
|
||||
|
@ -66,7 +66,7 @@ const columns = [{
|
||||
| indentSize | 展示树形数据时,每层缩进的宽度,以 px 为单位 | number | 15 |
|
||||
| loading | 页面是否加载中 | boolean\|[object](https://ant.design/components/spin-cn/#API) ([更多](https://github.com/ant-design/ant-design/issues/4544#issuecomment-271533135)) | false |
|
||||
| locale | 默认文案设置,目前包括排序、过滤、空数据文案 | object | filterConfirm: '确定' <br> filterReset: '重置' <br> emptyText: '暂无数据' <br> [默认值](https://github.com/ant-design/ant-design/issues/575#issuecomment-159169511) |
|
||||
| pagination | 分页器,配置项参考 [pagination](/components/pagination/),设为 false 时不展示和进行分页 | object | |
|
||||
| pagination | 分页器,参考[配置项](#pagination)或 [pagination](/components/pagination/),设为 false 时不展示和进行分页 | object | |
|
||||
| rowClassName | 表格行的类名 | Function(record, index):string | - |
|
||||
| rowKey | 表格行 key 的取值,可以是字符串或一个函数 | string\|Function(record):string | 'key' |
|
||||
| rowSelection | 列表项是否可选择,[配置项](#rowSelection) | object | null |
|
||||
@ -136,6 +136,16 @@ const columns = [{
|
||||
| --- | --- | --- | --- |
|
||||
| title | 列头显示文字 | string\|ReactNode | - |
|
||||
|
||||
### pagination
|
||||
|
||||
分页的配置项。
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| position | 指定分页显示的位置 | 'top' \| 'bottom' \| 'both' | 'bottom' |
|
||||
|
||||
更多配置项,请查看 [`Pagination`](/components/pagination/)。
|
||||
|
||||
### rowSelection
|
||||
|
||||
选择功能的配置。
|
||||
@ -146,10 +156,11 @@ const columns = [{
|
||||
| getCheckboxProps | 选择框的默认属性配置 | Function(record) | - |
|
||||
| hideDefaultSelections | 去掉『全选』『反选』两个默认选项 | boolean | false |
|
||||
| selectedRowKeys | 指定选中项的 key 数组,需要和 onChange 进行配合 | string\[] | \[] |
|
||||
| columnWidth | 自定义列表选择框宽度 | string\|number | - |
|
||||
| selections | 自定义选择项 [配置项](#selection), 设为 `true` 时使用默认选择项 | object\[]\|boolean | true |
|
||||
| type | 多选/单选,`checkbox` or `radio` | string | `checkbox` |
|
||||
| onChange | 选中项发生变化的时的回调 | Function(selectedRowKeys, selectedRows) | - |
|
||||
| onSelect | 用户手动选择/取消选择某列的回调 | Function(record, selected, selectedRows) | - |
|
||||
| onSelect | 用户手动选择/取消选择某列的回调 | Function(record, selected, selectedRows, nativeEvent) | - |
|
||||
| onSelectAll | 用户手动选择/取消选择所有列的回调 | Function(selected, selectedRows, changeRows) | - |
|
||||
| onSelectInvert | 用户手动选择反选的回调 | Function(selectedRows) | - |
|
||||
|
||||
|
@ -60,6 +60,10 @@ export interface TableLocale {
|
||||
export type RowSelectionType = 'checkbox' | 'radio';
|
||||
export type SelectionSelectFn<T> = (record: T, selected: boolean, selectedRows: Object[]) => any;
|
||||
|
||||
export interface TablePaginationConfig extends PaginationProps {
|
||||
position?: 'top' | 'bottom' | 'both';
|
||||
}
|
||||
|
||||
export interface TableRowSelection<T> {
|
||||
type?: RowSelectionType;
|
||||
selectedRowKeys?: string[] | number[];
|
||||
@ -71,13 +75,14 @@ export interface TableRowSelection<T> {
|
||||
selections?: SelectionItem[] | boolean;
|
||||
hideDefaultSelections?: boolean;
|
||||
fixed?: boolean;
|
||||
columnWidth?: string | number;
|
||||
}
|
||||
|
||||
export interface TableProps<T> {
|
||||
prefixCls?: string;
|
||||
dropdownPrefixCls?: string;
|
||||
rowSelection?: TableRowSelection<T>;
|
||||
pagination?: PaginationProps | false;
|
||||
pagination?: TablePaginationConfig | false;
|
||||
size?: 'default' | 'middle' | 'small';
|
||||
dataSource?: T[];
|
||||
components?: TableComponents;
|
||||
@ -93,7 +98,7 @@ export interface TableProps<T> {
|
||||
expandRowByClick?: boolean;
|
||||
onExpandedRowsChange?: (expandedRowKeys: string[] | number[]) => void;
|
||||
onExpand?: (expanded: boolean, record: T) => void;
|
||||
onChange?: (pagination: PaginationProps | boolean, filters: string[], sorter: Object) => any;
|
||||
onChange?: (pagination: TablePaginationConfig | boolean, filters: string[], sorter: Object) => any;
|
||||
loading?: boolean | SpinProps;
|
||||
locale?: Object;
|
||||
indentSize?: number;
|
||||
@ -117,7 +122,7 @@ export interface TableStateFilters {
|
||||
}
|
||||
|
||||
export interface TableState<T> {
|
||||
pagination: PaginationProps;
|
||||
pagination: TablePaginationConfig;
|
||||
filters: TableStateFilters;
|
||||
sortColumn: ColumnProps<T> | null;
|
||||
sortOrder: string;
|
||||
|
@ -12,6 +12,7 @@
|
||||
.reset-component;
|
||||
position: relative;
|
||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||
clear: both;
|
||||
|
||||
&-body {
|
||||
transition: opacity .3s;
|
||||
|
@ -38,6 +38,7 @@ import moment from 'moment';
|
||||
| getPopupContainer | to set the container of the floating layer, while the default is to create a div element in body | function(trigger) | - |
|
||||
| hideDisabledOptions | hide the options that can not be selected | boolean | false |
|
||||
| hourStep | interval between hours in picker | number | 1 |
|
||||
| inputReadOnly | Set the `readonly` attribute of the input tag (avoids virtual keyboard on touch devices) | boolean | false |
|
||||
| minuteStep | interval between minutes in picker | number | 1 |
|
||||
| open | whether to popup panel | boolean | false |
|
||||
| placeholder | display when there's no value | string | "Select a time" |
|
||||
|
@ -43,6 +43,7 @@ export interface TimePickerProps {
|
||||
minuteStep?: number;
|
||||
secondStep?: number;
|
||||
allowEmpty?: boolean;
|
||||
inputReadOnly?: boolean;
|
||||
clearText?: string;
|
||||
defaultOpenValue?: moment.Moment;
|
||||
popupClassName?: string;
|
||||
|
@ -39,6 +39,7 @@ import moment from 'moment';
|
||||
| getPopupContainer | 定义浮层的容器,默认为 body 上新建 div | function(trigger) | 无 |
|
||||
| hideDisabledOptions | 隐藏禁止选择的选项 | boolean | false |
|
||||
| hourStep | 小时选项间隔 | number | 1 |
|
||||
| inputReadOnly | 设置输入框为只读(避免在移动设备上打开虚拟键盘)| boolean | false |
|
||||
| minuteStep | 分钟选项间隔 | number | 1 |
|
||||
| open | 面板是否打开 | boolean | false |
|
||||
| placeholder | 没有值的时候显示的内容 | string | "请选择时间" |
|
||||
|
@ -8,6 +8,7 @@ export interface TimelineProps {
|
||||
className?: string;
|
||||
/** 指定最后一个幽灵节点是否存在或内容 */
|
||||
pending?: React.ReactNode;
|
||||
pendingDot?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
@ -18,7 +19,7 @@ export default class Timeline extends React.Component<TimelineProps, any> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { prefixCls, children, pending, className, ...restProps } = this.props;
|
||||
const { prefixCls, children, pending, pendingDot, className, ...restProps } = this.props;
|
||||
const pendingNode = typeof pending === 'boolean' ? null : pending;
|
||||
const classString = classNames(prefixCls, {
|
||||
[`${prefixCls}-pending`]: !!pending,
|
||||
@ -33,7 +34,7 @@ export default class Timeline extends React.Component<TimelineProps, any> {
|
||||
const pendingItem = (!!pending) ? (
|
||||
<TimelineItem
|
||||
pending={!!pending}
|
||||
dot={<Icon type="loading" />}
|
||||
dot={pendingDot || <Icon type="loading" />}
|
||||
>
|
||||
{pendingNode}
|
||||
</TimelineItem>
|
||||
|
@ -7,11 +7,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
当任务状态正在发生,还在记录过程中,可用幽灵节点来表示当前的时间节点。(用于时间正序排列)
|
||||
当任务状态正在发生,还在记录过程中,可用幽灵节点来表示当前的时间节点(用于时间正序排列)。当 pending 值为 false ,可用定制元件替换默认时间图点。
|
||||
|
||||
## en-US
|
||||
|
||||
When the timeline is incomplete and ongoing, put a ghost node at last. set `pending={true}` or `pending={a React Element}`. Used in ascend chronological order.
|
||||
When the timeline is incomplete and ongoing, put a ghost node at last. set `pending={true}` or `pending={a React Element}`. Used in ascend chronological order. When `pending` is not false, set `pendingDot={a React Element}` to replace the default pending dot.
|
||||
|
||||
````jsx
|
||||
import { Timeline } from 'antd';
|
||||
|
@ -29,6 +29,7 @@ Timeline
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| pending | Set the last ghost node's existence or its content | boolean\|string\|ReactNode | `false` |
|
||||
| pendingDot | Set the dot of the last ghost node when pending is true | \|string\|ReactNode | `<Icon type="loading" />` |
|
||||
|
||||
### Timeline.Item
|
||||
|
||||
|
@ -30,6 +30,7 @@ title: Timeline
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| pending | 指定最后一个幽灵节点是否存在或内容 | boolean\|string\|ReactNode | false |
|
||||
| pendingDot | 当最后一个幽灵节点存在時,指定其时间图点 | \|string\|ReactNode | `<Icon type="loading" />` |
|
||||
|
||||
### Timeline.Item
|
||||
|
||||
|
@ -51,9 +51,9 @@
|
||||
"omit.js": "^1.0.0",
|
||||
"prop-types": "^15.5.7",
|
||||
"rc-animate": "^2.4.1",
|
||||
"rc-calendar": "~9.5.0",
|
||||
"rc-calendar": "~9.6.0",
|
||||
"rc-cascader": "~0.12.0",
|
||||
"rc-checkbox": "~2.1.1",
|
||||
"rc-checkbox": "~2.1.5",
|
||||
"rc-collapse": "~1.8.0",
|
||||
"rc-dialog": "~7.1.0",
|
||||
"rc-dropdown": "~2.1.0",
|
||||
@ -71,7 +71,7 @@
|
||||
"rc-switch": "~1.6.0",
|
||||
"rc-table": "~6.1.0",
|
||||
"rc-tabs": "~9.2.0",
|
||||
"rc-time-picker": "~3.2.1",
|
||||
"rc-time-picker": "~3.3.0",
|
||||
"rc-tooltip": "~3.7.0",
|
||||
"rc-tree": "~1.7.11",
|
||||
"rc-tree-select": "~1.12.0",
|
||||
|
Loading…
Reference in New Issue
Block a user