Merge pull request #5558 from ant-design/feature-2.9

Feature 2.9
This commit is contained in:
偏右 2017-03-31 11:23:39 +08:00 committed by GitHub
commit cb2460c412
73 changed files with 1465 additions and 109 deletions

View File

@ -422,14 +422,6 @@ exports[`renders ./components/button/demo/loading.md correctly 1`] = `
Click me!
</span>
</button>
<button
class="ant-btn ant-btn-primary"
type="button"
>
<span>
Won't show loading
</span>
</button>
<br />
<button
class="ant-btn ant-btn-circle ant-btn-loading"

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { Component } from 'react';
import { render, mount } from 'enzyme';
import { renderToJson } from 'enzyme-to-json';
import Button from '..';
@ -25,4 +25,43 @@ describe('Button', () => {
// eslint-disable-next-line
expect(wrapper.type().__ANT_BUTTON).toBe(true);
});
it('should change loading state instantly by default', () => {
class DefaultButton extends Component {
state = {
loading: false,
};
enterLoading = () => {
this.setState({ loading: true });
}
render() {
return <Button loading={this.state.loading} onClick={this.enterLoading}>Button</Button>;
}
}
const wrapper = mount(
<DefaultButton />
);
wrapper.simulate('click');
expect(wrapper.hasClass('ant-btn-loading')).toBe(true);
});
it('should change loading state with delay', () => {
// eslint-disable-next-line
class DefaultButton extends Component {
state = {
loading: false,
};
enterLoading = () => {
this.setState({ loading: { delay: 1000 } });
}
render() {
return <Button loading={this.state.loading} onClick={this.enterLoading}>Button</Button>;
}
}
const wrapper = mount(
<DefaultButton />
);
wrapper.simulate('click');
expect(wrapper.hasClass('ant-btn-loading')).toBe(false);
});
});

View File

@ -41,7 +41,7 @@ export interface ButtonProps {
size?: ButtonSize;
onClick?: React.FormEventHandler<any>;
onMouseUp?: React.FormEventHandler<any>;
loading?: boolean;
loading?: boolean | { delay?: number };
disabled?: boolean;
style?: React.CSSProperties;
prefixCls?: string;
@ -66,7 +66,7 @@ export default class Button extends React.Component<ButtonProps, any> {
size: React.PropTypes.oneOf(['large', 'default', 'small']),
htmlType: React.PropTypes.oneOf(['submit', 'button', 'reset']),
onClick: React.PropTypes.func,
loading: React.PropTypes.bool,
loading: React.PropTypes.oneOfType([React.PropTypes.bool, React.PropTypes.object]),
className: React.PropTypes.string,
icon: React.PropTypes.string,
};
@ -89,8 +89,8 @@ export default class Button extends React.Component<ButtonProps, any> {
clearTimeout(this.delayTimeout);
}
if (loading) {
this.delayTimeout = setTimeout(() => this.setState({ loading }), 200);
if (loading && loading.delay) {
this.delayTimeout = setTimeout(() => this.setState({ loading }), loading.delay);
} else {
this.setState({ loading });
}

View File

@ -20,7 +20,6 @@ class App extends React.Component {
state = {
loading: false,
iconLoading: false,
delayLoading: false,
}
enterLoading = () => {
@ -30,15 +29,6 @@ class App extends React.Component {
enterIconLoading = () => {
this.setState({ iconLoading: true });
}
delayLoading = () => {
this.setState({
delayLoading: true,
});
setTimeout(() => this.setState({
delayLoading: false,
}), 150);
}
render() {
return (
@ -56,9 +46,6 @@ class App extends React.Component {
<Button type="primary" icon="poweroff" loading={this.state.iconLoading} onClick={this.enterIconLoading}>
Click me!
</Button>
<Button type="primary" loading={this.state.delayLoading} onClick={this.delayLoading}>
Won&apos;t show loading
</Button>
<br />
<Button shape="circle" loading />
<Button type="primary" shape="circle" loading />

View File

@ -21,7 +21,7 @@ htmlType | to set the original `type` of `button`, see: [MDN](https://developer.
icon | set the icon of button, see: Icon component | string | -
shape | can be set to `circle` or omitted | string | -
size | can be set to `small` `large` or omitted | string | `default`
loading | to set the loading status of button | boolean | `false`
loading | to set the loading status of button | boolean \| { delay: number } | `false`
onClick | set the handler to handle `click` event | function | -
ghost | make background transparent and invert text and border color, added in 2.7 | boolean | false

View File

@ -24,7 +24,7 @@ htmlType | 设置 `button` 原生的 `type` 值,可选值请参考 [HTML 标
icon | 设置按钮的图标类型 | string | -
shape | 设置按钮形状,可选值为 `circle` 或者不设 | string | -
size | 设置按钮大小,可选值为 `small` `large` 或者不设 | string | `default`
loading | 设置按钮载入状态 | boolean | `false`
loading | 设置按钮载入状态 | boolean \| { delay: number } | `false`
onClick | `click` 事件的 handler | function | -
ghost | 幽灵属性,使按钮背景透明,版本 2.7 中增加 | boolean | false

View File

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

View File

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

View File

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

View File

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

View File

@ -20,8 +20,9 @@
}
&-head {
height: 48px;
line-height: 48px;
height: @card-head-height;
line-height: @card-head-height;
background: @card-head-background;
border-bottom: @border-width-base @border-style-base @border-color-split;
padding: 0 24px;
@ -32,7 +33,7 @@
width: 100%;
overflow: hidden;
white-space: nowrap;
color: @heading-color;
color: @card-head-color;
font-weight: 500;
}
}

View File

@ -61,7 +61,7 @@ export interface CascaderProps {
onPopupVisibleChange?: (popupVisible: boolean) => void;
prefixCls?: string;
inputPrefixCls?: string;
getPopupContainer?: (triggerNode: Element) => HTMLElement;
getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement;
}
function highlightKeyword(str: string, keyword: string, prefixCls: string) {

View File

@ -0,0 +1,17 @@
import CalendarLocale from 'rc-calendar/lib/locale/et_EE';
import TimePickerLocale from '../../time-picker/locale/et_EE';
import assign from 'object-assign';
// 统一合并为完整的 Locale
const locale = {
lang: assign({
placeholder: 'Vali kuupäev',
rangePlaceholder: ['Algus kuupäev', 'Lõpu kuupäev'],
}, CalendarLocale),
timePickerLocale: assign({}, TimePickerLocale),
};
// All settings at:
// https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json
export default locale;

View File

@ -0,0 +1,16 @@
import CalendarLocale from 'rc-calendar/lib/locale/ja_JP';
import TimePickerLocale from '../../time-picker/locale/ja_JP';
import assign from 'object-assign';
const locale = {
lang: assign({
placeholder: '日付を選択',
rangePlaceholder: ['開始日付', '終了日付'],
}, CalendarLocale),
timePickerLocale: assign({}, TimePickerLocale),
};
// All settings at:
// https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json
export default locale;

View File

@ -0,0 +1,17 @@
import CalendarLocale from 'rc-calendar/lib/locale/sk_SK';
import TimePickerLocale from '../../time-picker/locale/sk_SK';
import assign from 'object-assign';
// 统一合并为完整的 Locale
const locale = {
lang: assign({
placeholder: 'Vybrať dátum',
rangePlaceholder: ['Od', 'Do'],
}, CalendarLocale),
timePickerLocale: assign({}, TimePickerLocale),
};
// All settings at:
// https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json
export default locale;

View File

@ -0,0 +1,17 @@
import CalendarLocale from 'rc-calendar/lib/locale/en_US';
import TimePickerLocale from '../../time-picker/locale/tr_TR';
import assign from 'object-assign';
// Merge into a locale object
const locale = {
lang: assign({
placeholder: 'Tarih Seç',
rangePlaceholder: ['Başlangıç Tarihi', 'Bitiş Tarihi'],
}, CalendarLocale),
timePickerLocale: assign({}, TimePickerLocale),
};
// All settings at:
// https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json
export default locale;

View File

@ -23,3 +23,4 @@ When a numeric value needs to be provided.
| disabled | disable the input | boolean | false |
| size | width of input box | string | - |
| formatter | Specifies the format of the value presented | function(value: number \| string): string | - |
| parser | Specifies the value extracted from formatter | function( string): number | - |

View File

@ -26,3 +26,4 @@ title: InputNumber
| disabled | 禁用 | boolean | false |
| size | 输入框大小 | string | 无 |
| formatter | 指定输入框展示值的格式 | function(value: number \| string): string | - |
| parser | 指定从 formatter 里转换回数字的方式,和 formatter 搭配使用 | function( string): number | - |

View File

@ -14,6 +14,10 @@ import nlNL from '../nl_NL';
import caES from '../ca_ES';
import csCZ from '../cs_CZ';
import koKR from '../ko_KR';
import etEE from '../et_EE';
import skSK from '../sk_SK';
import jaJP from '../ja_JP';
import trTR from '../tr_TR';
const Option = Select.Option;
const RangePicker = DatePicker.RangePicker;
@ -59,7 +63,7 @@ const App = () => (
describe('Locale Provider', () => {
it('should display the text as locale changed', () => {
[enUS, ptBR, ruRU, esES, svSE, frBE, deDE, nlNL, caES, csCZ, koKR].forEach((locale) => {
[enUS, ptBR, ruRU, esES, svSE, frBE, deDE, nlNL, caES, csCZ, koKR, etEE, skSK, jaJP, trTR].forEach((locale) => {
const wrapper = mount(
<LocaleProvider locale={locale}>
<App />
@ -81,7 +85,7 @@ describe('Locale Provider', () => {
return null;
}
}
[enUS, ptBR, ruRU, esES, svSE, frBE, deDE, nlNL, caES, csCZ, koKR].forEach((locale) => {
[enUS, ptBR, ruRU, esES, svSE, frBE, deDE, nlNL, caES, csCZ, koKR, trTR].forEach((locale) => {
mount(
<LocaleProvider locale={locale}>
<ModalDemo />

View File

@ -0,0 +1,45 @@
import moment from 'moment';
moment.locale('et');
import DatePicker from '../date-picker/locale/et_EE';
import TimePicker from '../time-picker/locale/et_EE';
import Calendar from '../calendar/locale/et_EE';
export default {
locale: 'et',
DatePicker,
TimePicker,
Calendar,
Table: {
filterTitle: 'Filtri menüü',
filterConfirm: 'OK',
filterReset: 'Nulli',
emptyText: 'Andmed puuduvad',
selectAll: 'Vali kõik',
selectInvert: 'Inverteeri valik',
},
Modal: {
okText: 'OK',
cancelText: 'Tühista',
justOkText: 'OK',
},
Popconfirm: {
okText: 'OK',
cancelText: 'Tühista',
},
Transfer: {
notFoundContent: 'Ei leitud',
searchPlaceholder: 'Otsi siit',
itemUnit: 'kogus',
itemsUnit: 'kogus',
},
Select: {
notFoundContent: 'Ei leitud',
},
Upload: {
uploading: 'Üleslaadimine...',
removeFile: 'Eemalda fail',
uploadError: 'Üleslaadimise tõrge',
previewFile: 'Faili eelvaade',
},
};

View File

@ -0,0 +1,47 @@
import moment from 'moment';
moment.locale('ja');
import Pagination from 'rc-pagination/lib/locale/ja_JP';
import DatePicker from '../date-picker/locale/ja_JP';
import TimePicker from '../time-picker/locale/ja_JP';
import Calendar from '../calendar/locale/ja_JP';
export default {
locale: 'ja',
Pagination,
DatePicker,
TimePicker,
Calendar,
Table: {
filterTitle: 'メニューをフィルター',
filterConfirm: 'OK',
filterReset: 'リセット',
emptyText: 'データがありません',
selectAll: 'すべてを選択',
selectInvert: '選択を反転',
},
Modal: {
okText: 'OK',
cancelText: 'キャンセル',
justOkText: 'OK',
},
Popconfirm: {
okText: 'OK',
cancelText: 'キャンセル',
},
Transfer: {
notFoundContent: '結果はありません',
searchPlaceholder: 'ここを検索',
itemUnit: 'アイテム',
itemsUnit: 'アイテム',
},
Select: {
notFoundContent: '結果はありません',
},
Upload: {
uploading: 'アップロード中...',
removeFile: 'ファイルを削除',
uploadError: 'アップロードエラー',
previewFile: 'ファイルをプレビュー',
},
};

View File

@ -0,0 +1,47 @@
import moment from 'moment';
moment.locale('sk');
import Pagination from 'rc-pagination/lib/locale/sk_SK';
import DatePicker from '../date-picker/locale/sk_SK';
import TimePicker from '../time-picker/locale/sk_SK';
import Calendar from '../calendar/locale/sk_SK';
export default {
locale: 'sk',
Pagination,
DatePicker,
TimePicker,
Calendar,
Table: {
filterTitle: 'Filter',
filterConfirm: 'OK',
filterReset: 'Obnoviť',
emptyText: 'Žiadne dáta',
selectAll: 'Vybrať všetko',
selectInvert: 'Vybrať opačné',
},
Modal: {
okText: 'OK',
cancelText: 'Zrušiť',
justOkText: 'OK',
},
Popconfirm: {
okText: 'OK',
cancelText: 'Zrušiť',
},
Transfer: {
notFoundContent: 'Nenájdené',
searchPlaceholder: 'Vyhľadávanie',
itemUnit: 'položka',
itemsUnit: 'položiek',
},
Select: {
notFoundContent: 'Nenájdené',
},
Upload: {
uploading: 'Nahrávanie...',
removeFile: 'Odstrániť súbor',
uploadError: 'Chyba pri nahrávaní',
previewFile: 'Zobraziť súbor',
},
};

View File

@ -0,0 +1,47 @@
import moment from 'moment';
moment.locale('tr');
import Pagination from 'rc-pagination/lib/locale/en_US';
import DatePicker from '../date-picker/locale/tr_TR';
import TimePicker from '../time-picker/locale/tr_TR';
import Calendar from '../calendar/locale/en_US';
export default {
locale: 'tr',
Pagination,
DatePicker,
TimePicker,
Calendar,
Table: {
filterTitle: 'Menü Filtrele',
filterConfirm: 'Tamam',
filterReset: 'Sıfırla',
emptyText: 'Veri Yok',
selectAll: 'Hepsini Seç',
selectInvert: 'Select Invert',
},
Modal: {
okText: 'Tamam',
cancelText: 'İptal',
justOkText: 'Tamam',
},
Popconfirm: {
okText: 'Tamam',
cancelText: 'İptal',
},
Transfer: {
notFoundContent: 'Bulunamadı',
searchPlaceholder: 'Arama',
itemUnit: 'Öğe',
itemsUnit: 'Öğeler',
},
Select: {
notFoundContent: 'Bulunamadı',
},
Upload: {
uploading: 'Yükleniyor...',
removeFile: `Dosya'ı kaldır`,
uploadError: 'Yükleme Hatası',
previewFile: `Dosya'ı Önizle`,
},
};

View File

@ -21,6 +21,7 @@ exports[`renders ./components/progress/demo/circle.md correctly 1`] = `
fill-opacity="0"
stroke="#f3f3f3"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
<path
class="ant-progress-circle-path"
@ -31,7 +32,7 @@ exports[`renders ./components/progress/demo/circle.md correctly 1`] = `
stroke="#108ee9"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:73.82742735936014px;transition:stroke-dashoffset 0.3s ease 0s, stroke 0.3s ease;"
style="stroke-dasharray:221.48228207808043px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
</svg>
<span
@ -60,6 +61,7 @@ exports[`renders ./components/progress/demo/circle.md correctly 1`] = `
fill-opacity="0"
stroke="#f3f3f3"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
<path
class="ant-progress-circle-path"
@ -70,7 +72,7 @@ exports[`renders ./components/progress/demo/circle.md correctly 1`] = `
stroke="#ff5500"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:88.59291283123217px;transition:stroke-dashoffset 0.3s ease 0s, stroke 0.3s ease;"
style="stroke-dasharray:206.7167966062084px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
</svg>
<span
@ -101,6 +103,7 @@ exports[`renders ./components/progress/demo/circle.md correctly 1`] = `
fill-opacity="0"
stroke="#f3f3f3"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
<path
class="ant-progress-circle-path"
@ -111,7 +114,7 @@ exports[`renders ./components/progress/demo/circle.md correctly 1`] = `
stroke="#87d068"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:0px;transition:stroke-dashoffset 0.3s ease 0s, stroke 0.3s ease;"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
</svg>
<span
@ -147,6 +150,7 @@ exports[`renders ./components/progress/demo/circle-dynamic.md correctly 1`] = `
fill-opacity="0"
stroke="#f3f3f3"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
<path
class="ant-progress-circle-path"
@ -157,7 +161,7 @@ exports[`renders ./components/progress/demo/circle-dynamic.md correctly 1`] = `
stroke="#108ee9"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:295.3097094374406px;transition:stroke-dashoffset 0.3s ease 0s, stroke 0.3s ease;"
style="stroke-dasharray:0px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
</svg>
<span
@ -211,6 +215,7 @@ exports[`renders ./components/progress/demo/circle-mini.md correctly 1`] = `
fill-opacity="0"
stroke="#f3f3f3"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
<path
class="ant-progress-circle-path"
@ -221,7 +226,7 @@ exports[`renders ./components/progress/demo/circle-mini.md correctly 1`] = `
stroke="#108ee9"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:206.7167966062084px;transition:stroke-dashoffset 0.3s ease 0s, stroke 0.3s ease;"
style="stroke-dasharray:88.59291283123217px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
</svg>
<span
@ -250,6 +255,7 @@ exports[`renders ./components/progress/demo/circle-mini.md correctly 1`] = `
fill-opacity="0"
stroke="#f3f3f3"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
<path
class="ant-progress-circle-path"
@ -260,7 +266,7 @@ exports[`renders ./components/progress/demo/circle-mini.md correctly 1`] = `
stroke="#ff5500"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:88.59291283123217px;transition:stroke-dashoffset 0.3s ease 0s, stroke 0.3s ease;"
style="stroke-dasharray:206.7167966062084px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
</svg>
<span
@ -291,6 +297,7 @@ exports[`renders ./components/progress/demo/circle-mini.md correctly 1`] = `
fill-opacity="0"
stroke="#f3f3f3"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
<path
class="ant-progress-circle-path"
@ -301,7 +308,7 @@ exports[`renders ./components/progress/demo/circle-mini.md correctly 1`] = `
stroke="#87d068"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:0px;transition:stroke-dashoffset 0.3s ease 0s, stroke 0.3s ease;"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
</svg>
<span
@ -316,6 +323,51 @@ exports[`renders ./components/progress/demo/circle-mini.md correctly 1`] = `
</div>
`;
exports[`renders ./components/progress/demo/dashboard.md correctly 1`] = `
<div>
<div
class="ant-progress ant-progress-circle ant-progress-status-normal ant-progress-show-info"
>
<div
class="ant-progress-inner"
style="width:132px;height:132px;font-size:27.12px;"
>
<svg
class="ant-progress-circle "
viewbox="0 0 100 100"
>
<path
class="ant-progress-circle-trail"
d="M 50,50 m 0,47
a 47,47 0 1 1 0,-94
a 47,47 0 1 1 0,94"
fill-opacity="0"
stroke="#f3f3f3"
stroke-width="6"
style="stroke-dasharray:220.30970943744057px 295.3097094374406px;stroke-dashoffset:-37.5px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
<path
class="ant-progress-circle-path"
d="M 50,50 m 0,47
a 47,47 0 1 1 0,-94
a 47,47 0 1 1 0,94"
fill-opacity="0"
stroke="#108ee9"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray:165.23228207808043px 295.3097094374406px;stroke-dashoffset:-37.5px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
</svg>
<span
class="ant-progress-text"
>
75%
</span>
</div>
</div>
</div>
`;
exports[`renders ./components/progress/demo/dynamic.md correctly 1`] = `
<div>
<div
@ -385,6 +437,7 @@ exports[`renders ./components/progress/demo/format.md correctly 1`] = `
fill-opacity="0"
stroke="#f3f3f3"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
<path
class="ant-progress-circle-path"
@ -395,7 +448,7 @@ exports[`renders ./components/progress/demo/format.md correctly 1`] = `
stroke="#108ee9"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:73.82742735936014px;transition:stroke-dashoffset 0.3s ease 0s, stroke 0.3s ease;"
style="stroke-dasharray:221.48228207808043px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
</svg>
<span
@ -424,6 +477,7 @@ exports[`renders ./components/progress/demo/format.md correctly 1`] = `
fill-opacity="0"
stroke="#f3f3f3"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
<path
class="ant-progress-circle-path"
@ -434,7 +488,7 @@ exports[`renders ./components/progress/demo/format.md correctly 1`] = `
stroke="#87d068"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:0px;transition:stroke-dashoffset 0.3s ease 0s, stroke 0.3s ease;"
style="stroke-dasharray:295.3097094374406px 295.3097094374406px;stroke-dashoffset:-0px;transition:stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s;"
/>
</svg>
<span

View File

@ -0,0 +1,24 @@
---
order: 8
title:
zh-CN: 仪表盘
en-US: Dashboard
---
## zh-CN
仪表盘。
## en-US
A dashboard.
````jsx
import { Progress } from 'antd';
ReactDOM.render(
<div>
<Progress type="dashboard" percent={75} />
</div>
, mountNode);
````

View File

@ -17,7 +17,7 @@ If it will take a long time to complete the operation, you can use `Progress` to
Property | Description | Type | Default
-----|-----|-----|------
type | to set the type, options: `line` `circle` | string | line
type | to set the type, options: `line` `circle` `dashboard`| string | line
percent | to set the completion percentage | number | 0
format | template function of the content | function(percent) | `percent => percent + '%'`
status | to set the status of the progress, options: `success` `exception` `active` | string | -

View File

@ -19,7 +19,7 @@ title: Progress
| 属性 | 说明 | 类型 | 默认值 |
|----------|---------------|----------|---------------|
| type | 类型,可选 `line` `circle` | string | line |
| type | 类型,可选 `line` `circle` `dashboard` | string | line |
| percent | 百分比 | number | 0 |
| format | 内容的模板函数 | function(percent) | `percent => percent + '%'` |
| status | 状态,可选:`success` `exception` `active` | string | - |

View File

@ -12,7 +12,7 @@ const statusColorMap = {
export interface ProgressProps {
prefixCls?: string;
className?: string;
type?: 'line' | 'circle';
type?: 'line' | 'circle' | 'dashboard';
percent?: number;
format?: (percent: number) => string;
status?: 'success' | 'active' | 'exception';
@ -21,6 +21,8 @@ export interface ProgressProps {
trailColor?: string;
width?: number;
style?: React.CSSProperties;
gapDegree?: number;
gapPosition?: 'top' | 'bottom' | 'left' | 'right';
}
export default class Progress extends React.Component<ProgressProps, any> {
@ -37,20 +39,21 @@ export default class Progress extends React.Component<ProgressProps, any> {
static propTypes = {
status: PropTypes.oneOf(['normal', 'exception', 'active', 'success']),
type: PropTypes.oneOf(['line', 'circle']),
type: PropTypes.oneOf(['line', 'circle', 'dashboard']),
showInfo: PropTypes.bool,
percent: PropTypes.number,
width: PropTypes.number,
strokeWidth: PropTypes.number,
trailColor: PropTypes.string,
format: PropTypes.func,
gapDegree: PropTypes.number,
};
render() {
const props = this.props;
const {
prefixCls, className, percent = 0, status, format, trailColor,
type, strokeWidth, width, showInfo, ...restProps,
type, strokeWidth, width, showInfo, gapDegree = 0, gapPosition, ...restProps,
} = props;
const progressStatus = parseInt(percent.toString(), 10) >= 100 && !('status' in props) ?
'success' : (status || 'normal');
@ -60,7 +63,7 @@ export default class Progress extends React.Component<ProgressProps, any> {
if (showInfo) {
let text;
const iconType = type === 'circle' ? '' : '-circle';
const iconType = (type === 'circle' || type === 'dashboard') ? '' : '-circle';
if (progressStatus === 'exception') {
text = format ? textFormatter(percent) : <Icon type={`cross${iconType}`} />;
} else if (progressStatus === 'success') {
@ -86,7 +89,7 @@ export default class Progress extends React.Component<ProgressProps, any> {
{progressInfo}
</div>
);
} else if (type === 'circle') {
} else if (type === 'circle' || type === 'dashboard') {
const circleSize = width || 132;
const circleStyle = {
width: circleSize,
@ -94,6 +97,8 @@ export default class Progress extends React.Component<ProgressProps, any> {
fontSize: circleSize * 0.16 + 6,
};
const circleWidth = strokeWidth || 6;
const gapPos = gapPosition || type === 'dashboard' && 'bottom' || 'top';
const gapDeg = gapDegree || type === 'dashboard' && 75;
progress = (
<div className={`${prefixCls}-inner`} style={circleStyle}>
<Circle
@ -103,6 +108,8 @@ export default class Progress extends React.Component<ProgressProps, any> {
strokeColor={statusColorMap[progressStatus]}
trailColor={trailColor}
prefixCls={prefixCls}
gapDegree={gapDeg}
gapPosition={gapPos}
/>
{progressInfo}
</div>
@ -110,7 +117,7 @@ export default class Progress extends React.Component<ProgressProps, any> {
}
const classString = classNames(prefixCls, {
[`${prefixCls}-${type}`]: true,
[`${prefixCls}-${type === 'dashboard' && 'circle' || type}`]: true,
[`${prefixCls}-status-${progressStatus}`]: true,
[`${prefixCls}-show-info`]: showInfo,
}, className);

View File

@ -493,6 +493,188 @@ exports[`renders ./components/radio/demo/radiogroup-more.md correctly 1`] = `
</div>
`;
exports[`renders ./components/radio/demo/radiogroup-optional.md correctly 1`] = `
<div>
<div
class="ant-radio-group"
>
<label
class="ant-radio-wrapper ant-radio-wrapper-checked"
>
<span
class="ant-radio ant-radio-checked"
>
<input
checked=""
class="ant-radio-input"
type="radio"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Apple
</span>
</label>
<label
class="ant-radio-wrapper"
>
<span
class="ant-radio"
>
<input
class="ant-radio-input"
type="radio"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Pear
</span>
</label>
<label
class="ant-radio-wrapper"
>
<span
class="ant-radio"
>
<input
class="ant-radio-input"
type="radio"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Orange
</span>
</label>
</div>
<div
class="ant-radio-group"
>
<label
class="ant-radio-wrapper ant-radio-wrapper-checked"
>
<span
class="ant-radio ant-radio-checked"
>
<input
checked=""
class="ant-radio-input"
type="radio"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Apple
</span>
</label>
<label
class="ant-radio-wrapper"
>
<span
class="ant-radio"
>
<input
class="ant-radio-input"
type="radio"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Pear
</span>
</label>
<label
class="ant-radio-wrapper"
>
<span
class="ant-radio"
>
<input
class="ant-radio-input"
type="radio"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Orange
</span>
</label>
</div>
<div
class="ant-radio-group"
>
<label
class="ant-radio-wrapper ant-radio-wrapper-checked"
>
<span
class="ant-radio ant-radio-checked"
>
<input
checked=""
class="ant-radio-input"
type="radio"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Apple
</span>
</label>
<label
class="ant-radio-wrapper"
>
<span
class="ant-radio"
>
<input
class="ant-radio-input"
type="radio"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Pear
</span>
</label>
<label
class="ant-radio-wrapper"
>
<span
class="ant-radio"
>
<input
class="ant-radio-input"
type="radio"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Orange
</span>
</label>
</div>
</div>
`;
exports[`renders ./components/radio/demo/size.md correctly 1`] = `
<div>
<div>

View File

@ -16,6 +16,21 @@ describe('Radio', () => {
);
}
function createRadioGroupByOption(props) {
const options = [
{ label: 'A', value: 'A' },
{ label: 'B', value: 'B' },
{ label: 'C', value: 'C' },
];
return (
<RadioGroup
{...props}
options={options}
/>
);
}
it('responses hover events', () => {
const onMouseEnter = jest.fn();
const onMouseLeave = jest.fn();
@ -77,4 +92,13 @@ describe('Radio', () => {
radios.at(0).simulate('change');
expect(onChange.mock.calls.length).toBe(0);
});
it('optional should correct render', () => {
const wrapper = mount(
createRadioGroupByOption()
);
const radios = wrapper.find('input');
expect(radios.length).toBe(3);
});
});

View File

@ -0,0 +1,68 @@
---
order: 2
title:
zh-CN: RadioGroup 组合 - 配置方式
en-US: RadioGroup group - optional
---
## zh-CN
通过配置参数来控制渲染单选框。
## en-US
Render radios by configuring parameters.
```jsx
import { Radio } from 'antd';
const RadioGroup = Radio.Group;
const plainOptions = ['Apple', 'Pear', 'Orange'];
const options = [
{ label: 'Apple', value: 'Apple' },
{ label: 'Pear', value: 'Pear' },
{ label: 'Orange', value: 'Orange' },
];
const optionsWithDisabled = [
{ label: 'Apple', value: 'Apple' },
{ label: 'Pear', value: 'Pear' },
{ label: 'Orange', value: 'Orange', disabled: false },
];
class App extends React.Component {
state = {
value1: 'Apple',
value2: 'Apple',
value3: 'Apple',
}
onChange1 = (e) => {
console.log('radio1 checked', e.target.value);
this.setState({
value1: e.target.value,
});
}
onChange2 = (e) => {
console.log('radio2 checked', e.target.value);
this.setState({
value2: e.target.value,
});
}
onChange3 = (e) => {
console.log('radio3 checked', e.target.value);
this.setState({
value3: e.target.value,
});
}
render() {
return (
<div>
<RadioGroup options={plainOptions} onChange={this.onChange1} value={this.state.value1} />
<RadioGroup options={options} onChange={this.onChange2} value={this.state.value2} />
<RadioGroup options={optionsWithDisabled} onChange={this.onChange3} value={this.state.value3} />
</div>
);
}
}
ReactDOM.render(<App />, mountNode);
```

View File

@ -1,6 +1,7 @@
import React, { PropTypes } from 'react';
import classNames from 'classnames';
import shallowEqual from 'shallowequal';
import Radio from './radio';
function getCheckedValue(children) {
let value = null;
@ -29,6 +30,12 @@ export interface RadioGroupProps {
disabled?: boolean;
onMouseEnter?: React.FormEventHandler<any>;
onMouseLeave?: React.FormEventHandler<any>;
/** 以配置的方式设置 Radio 子元素,设置了此参数,会忽略 children */
options?: Array<string | {
label: string;
value: string;
disabled?: boolean;
}>;
}
export default class RadioGroup extends React.Component<RadioGroupProps, any> {
@ -83,8 +90,8 @@ export default class RadioGroup extends React.Component<RadioGroupProps, any> {
shouldComponentUpdate(nextProps, nextState, nextContext) {
return !shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState) ||
!shallowEqual(this.context.group, nextContext.group);
!shallowEqual(this.state, nextState) ||
!shallowEqual(this.context.group, nextContext.group);
}
onRadioChange = (ev) => {
@ -103,10 +110,44 @@ export default class RadioGroup extends React.Component<RadioGroupProps, any> {
}
render() {
const props = this.props;
const { prefixCls = 'ant-radio-group', className = '', children } = props;
const { prefixCls = 'ant-radio-group', className = '' } = props;
const classString = classNames(prefixCls, {
[`${prefixCls}-${props.size}`]: props.size,
}, className);
let children: React.ReactChildren[] | React.ReactElement<any>[] | React.ReactNode = props.children;
// 如果存在 options, 优先使用
if (props.options && props.options.length > 0) {
children = props.options.map((option, index) => {
if (typeof option === 'string') { // 此处类型自动推导为 string
return (
<Radio
key={index}
disabled={this.props.disabled}
value={option}
onChange={this.onRadioChange}
checked={this.state.value === option}
>
{option}
</Radio>
);
} else { // 此处类型自动推导为 { label: string value: string }
return (
<Radio
key={index}
disabled={option.disabled || this.props.disabled}
value={option.value}
onChange={this.onRadioChange}
checked={this.state.value === option.value}
>
{option.label}
</Radio>
);
}
});
}
return (
<div
className={classString}

View File

@ -31,3 +31,4 @@ radio groupwrap a group of `Radio`。
| value | Used for setting the currently selected value. | any | none | none |
| defaultValue | Default selected value | any | none | none |
| size | Size, only on radio style | string | `large` `default` `small` | `default` |
| options | set children optional | string[] \| Array<{ label: string value: string disabled?: boolean }> | 无 | 无 |

View File

@ -32,3 +32,4 @@ title: Radio
| value | 用于设置当前选中的值 | any | 无 | 无 |
| defaultValue | 默认选中的值 | any | 无 | 无 |
| size | 大小,只对按钮样式生效 | string | `large` `default` `small` | `default` |
| options | 以配置形式设置子元素 | string[] \| Array<{ label: string value: string disabled?: boolean }> | 无 | 无 |

View File

@ -18,3 +18,4 @@ size | size of spin, available in `small`, `default` and `large` | string | 'def
spinning | whether Spin is spinning | boolean | true
tip | customize description content when spin has children | string | -
delay | specifies a delay millisecond for loading state (prevent flush) | number (millisecond) | -
wrapperClassName | className of wrapper when Spin has children | string | -

View File

@ -13,6 +13,7 @@ export interface SpinProps {
size?: 'small' | 'default' | 'large';
tip?: string;
delay?: number;
wrapperClassName?: string;
}
export default class Spin extends React.Component<SpinProps, any> {
@ -20,6 +21,7 @@ export default class Spin extends React.Component<SpinProps, any> {
prefixCls: 'ant-spin',
spinning: true,
size: 'default',
wrapperClassName: '',
};
static propTypes = {
@ -27,6 +29,7 @@ export default class Spin extends React.Component<SpinProps, any> {
className: PropTypes.string,
spinning: PropTypes.bool,
size: PropTypes.oneOf(['small', 'default', 'large']),
wrapperClassName: PropTypes.string,
};
debounceTimeout: number;
@ -82,7 +85,7 @@ export default class Spin extends React.Component<SpinProps, any> {
}
}
render() {
const { className, size, prefixCls, tip, ...restProps } = this.props;
const { className, size, prefixCls, tip, wrapperClassName, ...restProps } = this.props;
const { spinning } = this.state;
const spinClassName = classNames(prefixCls, {
@ -110,6 +113,10 @@ export default class Spin extends React.Component<SpinProps, any> {
</div>
);
if (this.isNestedPattern()) {
let animateClassName = prefixCls + '-nested-loading';
if (wrapperClassName) {
animateClassName += ' ' + wrapperClassName;
}
const containerClassName = classNames({
[`${prefixCls}-container`]: true,
[`${prefixCls}-blur`]: spinning,
@ -118,7 +125,7 @@ export default class Spin extends React.Component<SpinProps, any> {
<Animate
{...divProps}
component="div"
className={`${prefixCls}-nested-loading`}
className={animateClassName}
style={null}
transitionName="fade"
>

View File

@ -19,3 +19,4 @@ size | 组件大小,可选值为 `small` `default` `large` | string | 'default
spinning | 是否旋转 | boolean | true
tip | 当作为包裹元素时,可以自定义描述文案 | string | -
delay | 延迟显示加载效果的时间(防止闪烁) | number (毫秒) | -
wrapperClassName | 包装器的类属性 | string | -

View File

@ -265,3 +265,9 @@
// ---
@rate-star-color: #f5a623;
@rate-star-bg: #e9e9e9;
// Card
// ---
@card-head-height: 48px;
@card-head-color: @heading-color;
@card-head-background: @component-background;

View File

@ -15,6 +15,7 @@ export interface ColumnProps<T> {
width?: string | number;
className?: string;
fixed?: boolean | ('left' | 'right');
filterIcon?: React.ReactNode;
filteredValue?: any[];
sortOrder?: boolean | ('ascend' | 'descend');
children?: ColumnProps<T>[];

View File

@ -175,7 +175,7 @@ export default class SelectionCheckboxAll extends React.Component<SelectionCheck
customSelections = (
<Dropdown
overlay={menu}
getPopupContainer={trigger => trigger.parentNode as HTMLElement}
getPopupContainer={(trigger: HTMLElement) => trigger.parentNode as HTMLElement}
>
<div className={`${selectionPrefixCls}-down`}>
<Icon type="down" />

View File

@ -862,7 +862,8 @@ exports[`renders ./components/table/demo/custom-filter-panel.md correctly 1`] =
<span>
Name
<i
class="anticon anticon-filter ant-dropdown-trigger"
class="anticon anticon-smile-o ant-table-filter-icon ant-dropdown-trigger"
style="color:#aaa;"
title="筛选"
/>
</span>

View File

@ -14,7 +14,7 @@ title:
Implement a customized column search example via `filterDropdown`, `filterDropdownVisible` and `filterDropdownVisibleChange`.
````jsx
import { Table, Input, Button } from 'antd';
import { Table, Input, Button, Icon } from 'antd';
const data = [{
key: '1',
@ -43,6 +43,7 @@ class App extends React.Component {
filterDropdownVisible: false,
data,
searchText: '',
filtered: false,
};
onInputChange = (e) => {
this.setState({ searchText: e.target.value });
@ -52,6 +53,7 @@ class App extends React.Component {
const reg = new RegExp(searchText, 'gi');
this.setState({
filterDropdownVisible: false,
filtered: !!searchText,
data: data.map((record) => {
const match = record.name.match(reg);
if (!match) {
@ -78,6 +80,7 @@ class App extends React.Component {
filterDropdown: (
<div className="custom-filter-dropdown">
<Input
ref={ele => this.searchInput = ele}
placeholder="Search name"
value={this.state.searchText}
onChange={this.onInputChange}
@ -86,8 +89,9 @@ class App extends React.Component {
<Button type="primary" onClick={this.onSearch}>Search</Button>
</div>
),
filterIcon: <Icon type="smile-o" style={{ color: this.state.filtered ? '#108ee9' : '#aaa' }} />,
filterDropdownVisible: this.state.filterDropdownVisible,
onFilterDropdownVisibleChange: visible => this.setState({ filterDropdownVisible: visible }),
onFilterDropdownVisibleChange: visible => this.setState({ filterDropdownVisible: visible }, () => this.searchInput.focus()),
}, {
title: 'Age',
dataIndex: 'age',

View File

@ -19,6 +19,7 @@ export interface FilterMenuProps {
filterDropdownVisible?: boolean,
onFilterDropdownVisibleChange?: (visible: boolean) => any,
fixed?: boolean | string,
filterIcon?: React.ReactNode;
};
confirmFilter: (column: Object, selectedKeys: string[]) => any;
prefixCls: string;
@ -168,6 +169,18 @@ export default class FilterMenu extends React.Component<FilterMenuProps, any> {
this.setState({ keyPathOfSelectedItem });
}
renderFilterIcon = () => {
const { column, locale, prefixCls } = this.props;
const filterIcon = column.filterIcon as any;
const dropdownSelectedClass = this.props.selectedKeys.length > 0 ? `${prefixCls}-selected` : '';
return filterIcon ? React.cloneElement(filterIcon as any, {
title: locale.filterTitle,
className: classNames(filterIcon.className, {
[`${prefixCls}-icon`]: true,
}),
}) : <Icon title={locale.filterTitle} type="filter" className={dropdownSelectedClass} />;
}
render() {
const { column, locale, prefixCls, dropdownPrefixCls } = this.props;
// default multiple selection in filter dropdown
@ -209,9 +222,6 @@ export default class FilterMenu extends React.Component<FilterMenuProps, any> {
</FilterDropdownMenuWrapper>
);
const dropdownSelectedClass = (this.props.selectedKeys.length > 0)
? `${prefixCls}-selected` : '';
return (
<Dropdown
trigger={['click']}
@ -219,7 +229,7 @@ export default class FilterMenu extends React.Component<FilterMenuProps, any> {
visible={this.neverShown ? false : this.state.visible}
onVisibleChange={this.onVisibleChange}
>
<Icon title={locale.filterTitle} type="filter" className={dropdownSelectedClass} />
{this.renderFilterIcon()}
</Dropdown>
);
}

View File

@ -92,7 +92,9 @@ One of Property `columns` for descriping column, Column has the same API.
| filterDropdown | customized filter overlay | ReactNode | - |
| filterDropdownVisible | whether filterDropdown is visible | boolean | - |
| onFilterDropdownVisibleChange | called when filterDropdownVisible is changed | function(visible) {} | - |
| filteredValue | controlled filtered value | string[] | - |
| filteredValue | controlled filtered value, filter icon will highlight. | string[] | - |
| filtered | whether the dataSource is filterd | boolean | false |
| filterIcon | customized filter icon | ReactNode | false |
| sorter | sort function for local sort, see [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)'s compareFunction. If you need sort buttons only, set it `true` | Function\|boolean | - |
| colSpan | span of this column's title | number | |
| width | width of this column | string\|number | - |

View File

@ -94,6 +94,8 @@ const columns = [{
| filterDropdownVisible | 用于控制自定义筛选菜单是否可见 | boolean | - |
| onFilterDropdownVisibleChange | 自定义筛选菜单可见变化时调用 | function(visible) {} | - |
| filteredValue | 筛选的受控属性,外界可用此控制列的筛选状态,值为已筛选的 value 数组 | string[] | - |
| filtered | 标识数据是否经过过滤,筛选图标会高亮 | boolean | false |
| filterIcon | 自定义 fiter 图标。| ReactNode | false |
| sorter | 排序函数,本地排序使用一个函数(参考 [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 的 compareFunction),需要服务端排序可设为 true | Function\|boolean | - |
| colSpan | 表头列合并,设置为 0 时,不渲染 | number | |
| width | 列宽度 | string\|number | - |

View File

@ -39,7 +39,7 @@
text-align: center;
}
.@{iconfont-css-prefix}-filter {
.@{iconfont-css-prefix}-filter, .@{table-prefix-cls}-filter-icon {
margin-left: 4px;
font-size: @font-size-base;
cursor: pointer;

View File

@ -24,6 +24,8 @@ Ant Design has 3 types Tabs for different situation.
| defaultActiveKey | Default actived tabPanel's key, if activeKey is not setted. | - |
| onChange | Callback when tab is switched | Function | - |
| onTabClick | Callback when tab is clicked | Function | - |
| onPrevClick | Callback when prev button is clicked | Function | 无 |
| onNextClick | Callback when next button is clicked | Function | 无 |
| tabBarExtraContent | Extra element in tab bar | React.ReactNode | - |
| tabBarStyle | tar bar style object | object | - |
| type | Basic style of tabs. Options: line, card & editable-card | string | line |
@ -31,7 +33,7 @@ Ant Design has 3 types Tabs for different situation.
| tabPosition | Position of tabs. Options: top, right, bottom & left | string | top |
| onEdit | Callback when tab is added or removed, which is executing when set type as editable-card | (targetKey, action): void | - |
| hideAdd | Hide plus icon or not, which is effective when set type as editable-card | boolean | false |
| animated | Whether to change tabs with animation, this property only works with `tabPosition=top|bottom` | boolean | true |
| animated | Whether to change tabs with animation, this property only works with `tabPosition=top|bottom` | boolean \| {inkBar:boolean, tabPane:boolean} | true |
### Tabs.TabPane
| Property | Description | Type | Default |

View File

@ -1,5 +1,4 @@
import React from 'react';
import { cloneElement } from 'react';
import React, { cloneElement } from 'react';
import { findDOMNode } from 'react-dom';
import RcTabs, { TabPane } from 'rc-tabs';
import ScrollableInkTabBar from 'rc-tabs/lib/ScrollableInkTabBar';
@ -18,6 +17,8 @@ export interface TabsProps {
hideAdd?: boolean;
onChange?: (activeKey: string) => void;
onTabClick?: Function;
onPrevClick?: (e) => void;
onNextClick?: (e) => void;
tabBarExtraContent?: React.ReactNode | null;
tabBarStyle?: React.CSSProperties;
type?: TabsType;
@ -27,7 +28,7 @@ export interface TabsProps {
style?: React.CSSProperties;
prefixCls?: string;
className?: string;
animated?: boolean;
animated?: boolean | { inkBar: boolean; tabPane: boolean; };
}
// Tabs
@ -95,8 +96,17 @@ export default class Tabs extends React.Component<TabsProps, any> {
tabBarStyle,
hideAdd,
onTabClick,
onPrevClick,
onNextClick,
animated,
} = this.props;
let { inkBarAnimated, tabPaneAnimated } = typeof animated === 'object' ? {
inkBarAnimated: animated.inkBar, tabPaneAnimated: animated.tabPane,
} : {
inkBarAnimated: animated, tabPaneAnimated: animated,
};
warning(
!(type.indexOf('card') >= 0 && size === 'small'),
'Tabs[type=card|editable-card] doesn\'t have small size, it\'s by designed.',
@ -150,8 +160,11 @@ export default class Tabs extends React.Component<TabsProps, any> {
const renderTabBar = () => (
<ScrollableInkTabBar
inkBarAnimated={inkBarAnimated}
extraContent={tabBarExtraContent}
onTabClick={onTabClick}
onPrevClick={onPrevClick}
onNextClick={onNextClick}
style={tabBarStyle}
/>
);
@ -162,7 +175,7 @@ export default class Tabs extends React.Component<TabsProps, any> {
className={cls}
tabBarPosition={tabPosition}
renderTabBar={renderTabBar}
renderTabContent={() => <TabContent animated={animated} animatedWithMargin />}
renderTabContent={() => <TabContent animated={tabPaneAnimated} animatedWithMargin />}
onChange={this.handleChange}
>
{childrenWithClose || children}

View File

@ -27,6 +27,8 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。
| defaultActiveKey | 初始化选中面板的 key如果没有设置 activeKey | string | 第一个面板 |
| onChange | 切换面板的回调 | Function | 无 |
| onTabClick | tab 被点击的回调 | Function | 无 |
| onPrevClick | prev 按钮被点击的回调 | Function | 无 |
| onNextClick | next 按钮被点击的回调 | Function | 无 |
| tabBarExtraContent | tab bar 上额外的元素 | React.ReactNode | 无 |
| tabBarStyle | tar bar 的样式对象 | object | - |
| type | 页签的基本样式,可选 `line`、`card` `editable-card` 类型 | string | 'line' |
@ -34,7 +36,7 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。
| tabPosition | 页签位置,可选值有 `top` `right` `bottom` `left` | string | 'top' |
| onEdit | 新增和删除页签的回调,在 `type="editable-card"` 时有效 | (targetKey, action): void | 无 |
| hideAdd | 是否隐藏加号图标,在 `type="editable-card"` 时有效 | boolean | false |
| animated | 是否使用动画切换 Tabs`tabPosition=top|bottom` 时有效 | boolean | true |
| animated | 是否使用动画切换 Tabs`tabPosition=top|bottom` 时有效 | boolean \| {inkBar:boolean, tabPane:boolean} | true |
### Tabs.TabPane

View File

@ -18,8 +18,10 @@
box-sizing: border-box;
height: 2px;
background-color: @primary-color;
transition: transform 0.3s @ease-in-out;
transform-origin: 0 0;
&-animated {
transition: transform 0.3s @ease-in-out;
}
}
&-bar {

View File

@ -1,5 +1,52 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./components/time-picker/demo/12hours.md correctly 1`] = `
<div>
<span
class="ant-time-picker "
>
<input
class="ant-time-picker-input"
placeholder="请选择时间"
readonly=""
type="text"
value=""
/>
<span
class="ant-time-picker-icon"
/>
</span>
<span
class="ant-time-picker "
>
<input
class="ant-time-picker-input"
placeholder="请选择时间"
readonly=""
type="text"
value=""
/>
<span
class="ant-time-picker-icon"
/>
</span>
<span
class="ant-time-picker "
>
<input
class="ant-time-picker-input"
placeholder="请选择时间"
readonly=""
type="text"
value=""
/>
<span
class="ant-time-picker-icon"
/>
</span>
</div>
`;
exports[`renders ./components/time-picker/demo/addon.md correctly 1`] = `
<span
class="ant-time-picker "

View File

@ -0,0 +1,30 @@
---
order: 7
title:
zh-CN: 12 小时制
en-US: 12 hours
---
## zh-CN
12 小时制的时间选择器,默认的 format 为 `h:mm:ss a`
## en-US
TimePicker of 12 hours format, with default format `h:mm:ss a`.
````jsx
import { TimePicker } from 'antd';
function onChange(time, timeString) {
console.log(time, timeString);
}
ReactDOM.render(
<div>
<TimePicker use12Hours onChange={onChange} />
<TimePicker use12Hours format="h:mm:ss A" onChange={onChange} />
<TimePicker use12Hours format="h:mm a" onChange={onChange} />
</div>
, mountNode);
````

View File

@ -27,13 +27,14 @@ import moment from 'moment';
| value | to set time | [moment](http://momentjs.com/) | - |
| placeholder | display when there's no value | string | "Select a time" |
| onChange | a callback function, can be executed when the selected time is changing | function(time: moment, timeString: string): void | - |
| format | to set the time format | string | "HH:mm:ss"、"HH:mm"、"mm:ss" |
| format | to set the time format | string | "HH:mm:ss" |
| disabled | determine whether the TimePicker is disabled | boolean | false |
| disabledHours | to specify the hours that cannot be selected | function() | - |
| disabledMinutes | to specify the minutes that cannot be selected | function(selectedHour) | - |
| disabledSeconds | to specify the seconds that cannot be selected | function(selectedHour, selectedMinute) | - |
| hideDisabledOptions | hide the options that can not be selected | boolean | false |
| getPopupContainer | to set the container of the floating layer, while the default is to create a div element in body | function(trigger) | - |
| addon | called from timepicker panel to render some addon to its bottom | function | 无 |
| addon | called from timepicker panel to render some addon to its bottom | function | - |
| use12Hours | display as 12 hours format, with default format `h:mm:ss a` | boolean | false |
<style>.code-box-demo .ant-time-picker { margin: 0 8px 12px 0; }</style>

View File

@ -22,6 +22,7 @@ export interface TimePickerProps {
style?: React.CSSProperties;
getPopupContainer?: (triggerNode: Element) => HTMLElement;
addon?: Function;
use12Hours?: boolean;
}
abstract class TimePicker extends React.Component<TimePickerProps, any> {
@ -81,10 +82,21 @@ abstract class TimePicker extends React.Component<TimePickerProps, any> {
this.timePickerRef.focus();
}
getDefaultFormat() {
const { format, use12Hours } = this.props;
if (format) {
return format;
} else if (use12Hours) {
return 'h:mm:ss a';
}
return 'HH:mm:ss';
}
render() {
const props = assign({ format: 'HH:mm:ss' }, this.props);
const props = assign({}, this.props);
delete props.defaultValue;
const format = this.getDefaultFormat();
const className = classNames(props.className, {
[`${props.prefixCls}-${props.size}`]: !!props.size,
});
@ -101,12 +113,13 @@ abstract class TimePicker extends React.Component<TimePickerProps, any> {
<RcTimePicker
{...props}
ref={this.saveTimePicker}
format={format}
className={className}
value={this.state.value}
placeholder={props.placeholder === undefined ? this.getLocale().placeholder : props.placeholder}
showHour={props.format.indexOf('HH') > -1}
showMinute={props.format.indexOf('mm') > -1}
showSecond={props.format.indexOf('ss') > -1}
showHour={format.indexOf('HH') > -1 || format.indexOf('h') > -1}
showMinute={format.indexOf('mm') > -1}
showSecond={format.indexOf('ss') > -1}
onChange={this.handleChange}
addon={addon}
/>

View File

@ -28,7 +28,7 @@ import moment from 'moment';
| value | 当前时间 | [moment](http://momentjs.com/) | 无 |
| placeholder | 没有值的时候显示的内容 | string | "请选择时间" |
| onChange | 时间发生变化的回调 | function(time: moment, timeString: string): void | 无 |
| format | 展示的时间格式 | string | "HH:mm:ss"、"HH:mm"、"mm:ss" |
| format | 展示的时间格式 | string | "HH:mm:ss" |
| disabled | 禁用全部操作 | boolean | false |
| disabledHours | 禁止选择部分小时选项 | function() | 无 |
| disabledMinutes | 禁止选择部分分钟选项 | function(selectedHour) | 无 |
@ -36,5 +36,6 @@ import moment from 'moment';
| hideDisabledOptions | 隐藏禁止选择的选项 | boolean | false |
| getPopupContainer | 定义浮层的容器,默认为 body 上新建 div | function(trigger) | 无 |
| addon | 选择框底部显示自定义的内容 | function | 无 |
| use12Hours | 使用 12 小时制,为 true 时 `format` 默认为 `h:mm:ss a` | boolean | false |
<style>.code-box-demo .ant-time-picker { margin: 0 8px 12px 0; }</style>

View File

@ -0,0 +1,5 @@
const locale = {
placeholder: 'Vali aeg',
};
export default locale;

View File

@ -0,0 +1,5 @@
const locale = {
placeholder: '時刻を選択',
};
export default locale;

View File

@ -0,0 +1,5 @@
const locale = {
placeholder: 'Vybrať čas',
};
export default locale;

View File

@ -0,0 +1,5 @@
const locale = {
placeholder: 'Zaman Seç',
};
export default locale;

View File

@ -5,7 +5,6 @@
@timepicker-prefix-cls: ~"@{ant-prefix}-time-picker";
.@{timepicker-prefix-cls}-panel {
max-width: @time-picker-panel-width;
z-index: @zindex-picker;
position: absolute;

View File

@ -84,10 +84,6 @@
&.@{select-tree-prefix-cls}-bottom_close,
&.@{select-tree-prefix-cls}-noline_close {
.antTreeSwitcherIcon();
.ie-rotate(3);
&:after {
transform: rotate(270deg) scale(0.5);
}
}
}
}

View File

@ -484,6 +484,170 @@ exports[`renders ./components/tree/demo/basic-controlled.md correctly 1`] = `
</ul>
`;
exports[`renders ./components/tree/demo/customized-icon.md correctly 1`] = `
<ul
class="ant-tree-show-line ant-tree"
role="tree-node"
unselectable="true"
>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-roots_open"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"
title="parent 1"
>
<span
class="ant-tree-iconEle ant-tree-icon__open"
/>
<span
class="ant-tree-title"
>
parent 1
</span>
</a>
<ul
class="ant-tree-child-tree ant-tree-child-tree-open"
data-expanded="true"
>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-center_open"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open ant-tree-node-selected"
title="parent 1-0"
>
<span
class="ant-tree-iconEle ant-tree-icon__open"
/>
<span
class="ant-tree-title"
>
parent 1-0
</span>
</a>
<ul
class="ant-tree-child-tree ant-tree-child-tree-open ant-tree-line"
data-expanded="true"
>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-switcher-noop ant-tree-center_docu"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"
title="leaf"
>
<span
class="ant-tree-iconEle ant-tree-icon__docu"
/>
<span
class="ant-tree-title"
>
leaf
</span>
</a>
</li>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-switcher-noop ant-tree-bottom_docu"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"
title="leaf"
>
<span
class="ant-tree-iconEle ant-tree-icon__docu"
/>
<span
class="ant-tree-title"
>
leaf
</span>
</a>
</li>
</ul>
</li>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-center_open"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"
title="parent 1-1"
>
<span
class="ant-tree-iconEle ant-tree-icon__open"
/>
<span
class="ant-tree-title"
>
parent 1-1
</span>
</a>
<ul
class="ant-tree-child-tree ant-tree-child-tree-open ant-tree-line"
data-expanded="true"
>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-switcher-noop ant-tree-bottom_docu"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"
title="leaf"
>
<span
class="ant-tree-iconEle ant-tree-icon__docu"
/>
<span
class="ant-tree-title"
>
leaf
</span>
</a>
</li>
</ul>
</li>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-switcher-noop ant-tree-bottom_docu"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"
title="leaf"
>
<span
class="ant-tree-iconEle ant-tree-icon__docu"
/>
<span
class="ant-tree-title"
>
leaf
</span>
</a>
</li>
</ul>
</li>
</ul>
`;
exports[`renders ./components/tree/demo/draggable.md correctly 1`] = `
<ul
class="draggable-tree ant-tree"
@ -682,6 +846,144 @@ exports[`renders ./components/tree/demo/dynamic.md correctly 1`] = `
/>
`;
exports[`renders ./components/tree/demo/line.md correctly 1`] = `
<ul
class="ant-tree-show-line ant-tree"
role="tree-node"
unselectable="true"
>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-roots_open"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"
title="parent 1"
>
<span
class="ant-tree-title"
>
parent 1
</span>
</a>
<ul
class="ant-tree-child-tree ant-tree-child-tree-open"
data-expanded="true"
>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-center_open"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"
title="parent 1-0"
>
<span
class="ant-tree-title"
>
parent 1-0
</span>
</a>
<ul
class="ant-tree-child-tree ant-tree-child-tree-open ant-tree-line"
data-expanded="true"
>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-switcher-noop ant-tree-center_docu"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"
title="leaf"
>
<span
class="ant-tree-title"
>
leaf
</span>
</a>
</li>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-switcher-noop ant-tree-center_docu"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"
title="leaf"
>
<span
class="ant-tree-title"
>
leaf
</span>
</a>
</li>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-switcher-noop ant-tree-bottom_docu"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"
title="leaf"
>
<span
class="ant-tree-title"
>
leaf
</span>
</a>
</li>
</ul>
</li>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-center_close"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"
title="parent 1-1"
>
<span
class="ant-tree-title"
>
parent 1-1
</span>
</a>
</li>
<li
class=""
>
<span
class="ant-tree-switcher ant-tree-bottom_close"
/>
<a
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"
title="parent 1-2"
>
<span
class="ant-tree-title"
>
parent 1-2
</span>
</a>
</li>
</ul>
</li>
</ul>
`;
exports[`renders ./components/tree/demo/search.md correctly 1`] = `
<div>
<span

View File

@ -0,0 +1,85 @@
---
order: 6
title:
zh-CN: 自定义图标
en-US: Customize Icon
---
## zh-CN
可以针对不同节点采用样式覆盖的方式定制图标。
## en-US
You can customize icons for different nodes by styles override.
````jsx
import { Tree } from 'antd';
const TreeNode = Tree.TreeNode;
class Demo extends React.Component {
onSelect = (selectedKeys, info) => {
console.log('selected', selectedKeys, info);
}
render() {
return (
<Tree
showIcon
showLine
defaultExpandedKeys={['0-0-0', '0-0-1']}
defaultSelectedKeys={['0-0-0', '0-0-1']}
onSelect={this.onSelect}
>
<TreeNode title="parent 1" key="0-0">
<TreeNode title="parent 1-0" key="0-0-0">
<TreeNode title="leaf" key="0-0-0-0" />
<TreeNode title="leaf" key="0-0-0-1" />
</TreeNode>
<TreeNode title="parent 1-1" key="0-0-1">
<TreeNode title="leaf" key="0-0-1-0" />
</TreeNode>
<TreeNode title="leaf" key="0-0-2" />
</TreeNode>
</Tree>
);
}
}
ReactDOM.render(<Demo />, mountNode);
````
```css
#components-tree-demo-customized-icon .ant-tree-iconEle {
position: absolute;
left: 0;
background: #fff;
}
#components-tree-demo-customized-icon .ant-tree-iconEle::after {
font-size: 12px;
zoom: 1;
display: inline-block;
font-family: 'anticon';
text-rendering: optimizeLegibility;
color: #999;
transition: transform .3s ease;
margin-top: 2px;
background: #fff;
}
#components-tree-demo-customized-icon .ant-tree-iconEle.ant-tree-icon__docu::after {
content: "\E664";
}
#components-tree-demo-customized-icon .ant-tree-iconEle.ant-tree-icon__open::after {
content: "\E699";
}
#components-tree-demo-customized-icon .ant-tree-iconEle.ant-tree-icon__close::after {
content: "\E662";
}
#components-tree-demo-customized-icon .ant-tree-switcher {
position: relative;
z-index: 1;
background: transparent;
}
#components-tree-demo-customized-icon .ant-tree-switcher::after {
opacity: 0;
}
```

View File

@ -0,0 +1,51 @@
---
order: 5
title:
zh-CN: 连接线
en-US: Tree With Line
---
## zh-CN
带连接线的树。
## en-US
Tree With Line
````jsx
import { Tree } from 'antd';
const TreeNode = Tree.TreeNode;
class Demo extends React.Component {
onSelect = (selectedKeys, info) => {
console.log('selected', selectedKeys, info);
}
render() {
return (
<Tree
showLine
defaultExpandedKeys={['0-0-0']}
onSelect={this.onSelect}
>
<TreeNode title="parent 1" key="0-0">
<TreeNode title="parent 1-0" key="0-0-0">
<TreeNode title="leaf" key="0-0-0-0" />
<TreeNode title="leaf" key="0-0-0-1" />
<TreeNode title="leaf" key="0-0-0-2" />
</TreeNode>
<TreeNode title="parent 1-1" key="0-0-1">
<TreeNode title="leaf" key="0-0-1-0" />
</TreeNode>
<TreeNode title="parent 1-2" key="0-0-2">
<TreeNode title="leaf" key="0-0-2-0" />
<TreeNode title="leaf" key="0-0-2-1" />
</TreeNode>
</TreeNode>
</Tree>
);
}
}
ReactDOM.render(<Demo />, mountNode);
````

View File

@ -38,6 +38,8 @@ Directory, organization, biological classification, country, and etc. Almost thi
|onDragLeave | Defines a function will be called when the onDragLeave event occurs | function({event, node}) | - |
|onDragEnd | Defines a function will be called when the onDragEnd event occurs | function({event, node}) | - |
|onDrop | Defines a function will be called when the onDrop event occurs | function({event, node, dragNode, dragNodesKeys}) | - |
|showLine | Whether show connecting line | boolean | false |
|showIcon | Whether show the icon before TreeNode title, which has no default style, you must set custom style for it if set to true | boolean | false |
### TreeNode props

View File

@ -1,6 +1,7 @@
import React from 'react';
import RcTree, { TreeNode } from 'rc-tree';
import animation from '../_util/openAnimation';
import classNames from 'classnames';
export interface AntTreeNodeProps {
disabled?: boolean;
@ -96,11 +97,16 @@ export default class Tree extends React.Component<TreeProps, any> {
render() {
const props = this.props;
const { prefixCls, className, showLine } = props;
let checkable = props.checkable;
const classString = classNames({
[`${prefixCls}-show-line`]: !!showLine,
}, className);
return (
<RcTree
{...props}
checkable={checkable ? (<span className={`${props.prefixCls}-checkbox-inner`} />) : checkable}
className={classString}
checkable={checkable ? <span className={`${prefixCls}-checkbox-inner`} /> : checkable}
>
{this.props.children}
</RcTree>

View File

@ -39,6 +39,8 @@ subtitle: 树形控件
|onDragLeave | dragleave 触发时调用 | function({event, node}) | - |
|onDragEnd | dragend 触发时调用 | function({event, node}) | - |
|onDrop | drop 触发时调用 | function({event, node, dragNode, dragNodesKeys}) | - |
|showLine | 是否展示连接线 | boolean | false |
|showIcon | 是否展示 TreeNode title 前的图标,没有默认样式,如设置为 true需要自行定义图标相关样式 | boolean | false |
### TreeNode props

View File

@ -21,7 +21,7 @@
user-select: none;
border-top: 2px transparent solid;
border-bottom: 2px transparent solid;
margin-top: -2px;
/* Required to make elements draggable in old WebKit */
-khtml-user-drag: element;
-webkit-user-drag: element;
@ -72,7 +72,8 @@
}
span {
&.@{tree-prefix-cls}-checkbox {
margin: 0 4px 0 0;
margin: 0 4px 0 2px;
vertical-align: middle;
}
&.@{tree-prefix-cls}-switcher,
&.@{tree-prefix-cls}-iconEle {
@ -96,7 +97,7 @@
}
&.@{tree-prefix-cls}-switcher {
&.@{tree-prefix-cls}-switcher-noop {
cursor: auto;
cursor: default;
}
&.@{tree-prefix-cls}-roots_open,
&.@{tree-prefix-cls}-center_open,
@ -111,11 +112,19 @@
.antTreeSwitcherIcon();
.ie-rotate(3);
&:after {
transform: rotate(270deg) scale(0.6);
transform: rotate(270deg) scale(0.59);
}
}
}
}
&:last-child > span {
&.@{tree-prefix-cls}-switcher,
&.@{tree-prefix-cls}-iconEle {
&:before {
display: none;
}
}
}
}
> li {
&:first-child {
@ -132,9 +141,9 @@
}
}
&-treenode-disabled {
>span,
>a,
>a span {
> span,
> a,
> a span {
color: @disabled-color;
cursor: not-allowed;
}
@ -147,4 +156,39 @@
margin-right: 2px;
vertical-align: top;
}
// Tree with line
&&-show-line {
li {
position: relative;
span {
&.@{tree-prefix-cls}-switcher {
background: @component-background;
&.@{tree-prefix-cls}-switcher-noop {
.antTreeShowLineIcon("tree-doc-icon");
}
&.@{tree-prefix-cls}-roots_open,
&.@{tree-prefix-cls}-center_open,
&.@{tree-prefix-cls}-bottom_open,
&.@{tree-prefix-cls}-noline_open {
.antTreeShowLineIcon("tree-showline-open-icon");
}
&.@{tree-prefix-cls}-roots_close,
&.@{tree-prefix-cls}-center_close,
&.@{tree-prefix-cls}-bottom_close,
&.@{tree-prefix-cls}-noline_close {
.antTreeShowLineIcon("tree-showline-close-icon");
}
}
}
}
li:not(:last-child):before {
content: ' ';
width: 1px;
border-left: 1px solid @border-color-base;
height: 100%;
position: absolute;
left: 6px;
margin: 18px 0;
}
}
}

View File

@ -1,16 +1,30 @@
@import "../../style/mixins/index";
.antTreeSwitcherIcon() {
position: relative;
@tree-default-open-icon: "\e606";
@tree-showline-open-icon: "\e621";
@tree-showline-close-icon: "\e645";
@tree-doc-icon: "\e664";
@tree-showline-icon-color: @text-color-secondary;
.antTreeSwitcherIcon(@type: "tree-default-open-icon") {
&:after {
.iconfont-size-under-12px(7px);
display: inline-block;
.iconfont-font("\e606");
.iconfont-font(@@type);
font-weight: bold;
position: absolute;
top: 0;
right: 4px;
color: @text-color;
transition: transform .3s ease;
}
}
.antTreeShowLineIcon(@type) {
&:after {
.iconfont-size-under-12px(12px);
display: inline-block;
.iconfont-font(@@type);
vertical-align: baseline;
font-weight: normal;
color: @tree-showline-icon-color;
transition: transform .3s ease;
}
}

View File

@ -33,6 +33,7 @@ Supported languages:
- Swedish - sv_SE
- Dutch - nl_NL
- Catalan - ca_ES
- Japanese - ja_JP
See usage and contributing way of a new locale package at [LocaleProvider](/components/locale-provider).

View File

@ -32,6 +32,7 @@ return (
- 瑞典语 - sv_SE
- 荷兰语 - nl_NL
- 加泰罗尼亚 - ca_ES
- 日本语 - ja_JP
具体的使用方法和新语言包贡献方式请参考 [LocaleProvider 文档](/components/locale-provider)。

View File

@ -67,7 +67,7 @@ Add `script` and `link` tags in your browser and use the global variable `antd`.
We provide `antd.js` `antd.css` and `antd.min.js` `antd.min.css` under `antd/dist` in antd's npm package. You can also download these files directly from [![CDNJS](https://img.shields.io/cdnjs/v/antd.svg?style=flat-square)](https://cdnjs.com/libraries/antd) or [unpkg](https://unpkg.com/).
> **We strongly discourage loading these entire files** this will add bloat to your application and make it more difficult to receive bugfixes and updates. Ant is intended to be used in conjunction with a built a tool, such as [webpack](https://webpack.github.io/), which will make it easy to import only the parts of antd that you are using.
> **We strongly discourage loading these entire files** this will add bloat to your application and make it more difficult to receive bugfixes and updates. Ant is intended to be used in conjunction with a built a tool, such as [webpack](https://webpack.github.io/), which will make it easy to import only the parts of antd that you are using.
## Usage
@ -95,7 +95,7 @@ import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
}
```
This allows you to import components from antd without having to manually import the corresponding stylesheet. The antd babel plugin will automatically import stylesheets.
This allows you to import components from antd without having to manually import the corresponding stylesheet. The antd babel plugin will automatically import stylesheets.
```jsx
// import js and css modularly, parsed by babel-plugin-import
@ -164,7 +164,6 @@ If you'd like to help us improve antd, just create a [Pull Request](https://gith
## Need Help?
For questions on how to use antd, please post questions to [stackoverflow](http://stackoverflow.com/questions/tagged/antd) using the `antd` tag. If you're not finding what you need on stackoverflow, you can find us on [gitter](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) as well.
For questions on how to use antd, please post questions to [stackoverflow](http://stackoverflow.com/questions/tagged/antd) using the `antd` tag. If you're not finding what you need on stackoverflow, you can find us on [gitter](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) as well.
As always, we encourage experienced users to help those who are not familiar with `antd`!

View File

@ -43,7 +43,7 @@
"object-assign": "~4.1.0",
"omit.js": "^0.1.0",
"rc-animate": "~2.3.0",
"rc-calendar": "~7.6.2",
"rc-calendar": "~7.7.1",
"rc-cascader": "~0.11.0",
"rc-checkbox": "~1.5.0",
"rc-collapse": "~1.6.4",
@ -51,11 +51,11 @@
"rc-dropdown": "~1.4.8",
"rc-editor-mention": "~0.5.2",
"rc-form": "~1.3.0",
"rc-input-number": "~3.3.0",
"rc-input-number": "~3.4.4",
"rc-menu": "~5.0.9",
"rc-notification": "~1.4.0",
"rc-pagination": "~1.7.0",
"rc-progress": "~2.0.1",
"rc-pagination": "~1.8.0",
"rc-progress": "~2.1.0",
"rc-radio": "~2.0.0",
"rc-rate": "~2.1.0",
"rc-select": "~6.8.0",
@ -63,8 +63,8 @@
"rc-steps": "~2.4.0",
"rc-switch": "~1.4.2",
"rc-table": "~5.2.13",
"rc-tabs": "~7.2.0",
"rc-time-picker": "~2.2.1",
"rc-tabs": "~7.3.0",
"rc-time-picker": "~2.3.3",
"rc-tooltip": "~3.4.2",
"rc-tree": "~1.4.0",
"rc-tree-select": "~1.9.0",