mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 09:26:06 +08:00
Merge branch 'feature-2.8'
This commit is contained in:
commit
67bbae9ea8
@ -20,6 +20,8 @@ For displaying anchor hyperlinks on page and jumping between them.
|
||||
| offsetTop | Pixels to offset from top when calculating position of scroll | number | 0 |
|
||||
| offsetBottom | Pixels to offset from bottom when calculating position of scroll | number | - |
|
||||
| bounds | Bounding distance of anchor area | number | 5(px) |
|
||||
| affix | Fixed mode of Anchor | boolean | false |
|
||||
| showInkInFixed | Whether show ink-balls in Fixed mode | boolean | false |
|
||||
|
||||
### Link Props
|
||||
|
||||
|
@ -14,6 +14,7 @@ export interface AnchorProps {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
affix?: boolean;
|
||||
showInkInFixed?: boolean;
|
||||
}
|
||||
|
||||
export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
@ -22,6 +23,7 @@ export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-anchor',
|
||||
affix: true,
|
||||
showInkInFixed: false,
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
@ -91,6 +93,7 @@ export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
}
|
||||
|
||||
renderAnchorLink = (child) => {
|
||||
|
||||
const { href } = child.props;
|
||||
if (child.type.__ANT_ANCHOR_LINK && href) {
|
||||
this.anchorHelper.addLink(href);
|
||||
@ -98,7 +101,7 @@ export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
onClick: this.clickAnchorLink,
|
||||
prefixCls: this.props.prefixCls,
|
||||
bounds: this.props.bounds,
|
||||
affix: this.props.affix,
|
||||
affix: this.props.affix || this.props.showInkInFixed,
|
||||
offsetTop: this.props.offsetTop,
|
||||
});
|
||||
}
|
||||
@ -106,7 +109,7 @@ export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, offsetTop, style, className = '', affix } = this.props;
|
||||
const { prefixCls, offsetTop, style, className = '', affix, showInkInFixed } = this.props;
|
||||
const { activeAnchor, animated } = this.state;
|
||||
const inkClass = classNames({
|
||||
[`${prefixCls}-ink-ball`]: true,
|
||||
@ -119,7 +122,7 @@ export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
}, className);
|
||||
|
||||
const anchorClass = classNames(prefixCls, {
|
||||
'fixed': !affix,
|
||||
'fixed': !affix && !showInkInFixed,
|
||||
});
|
||||
|
||||
const anchorContent = (
|
||||
|
@ -21,6 +21,8 @@ title: Anchor
|
||||
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | |
|
||||
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | number | |
|
||||
| bounds | 锚点区域边界 | number | 5(px) |
|
||||
| affix | 固定模式 | boolean | false |
|
||||
| showInkInFixed | 固定模式是否显示小圆点 | boolean | false |
|
||||
|
||||
### Link Props
|
||||
|
||||
|
@ -1,139 +1,153 @@
|
||||
exports[`test renders ./components/badge/demo/basic.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-badge"
|
||||
title="5">
|
||||
<a
|
||||
class="head-example"
|
||||
href="#" />
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true">
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-webkit-transform:translateY(-1500%);transform:translateY(-1500%);">
|
||||
<p
|
||||
class="">
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
9
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="current">
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
9
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
9
|
||||
</p>
|
||||
</span>
|
||||
</sup>
|
||||
</span>
|
||||
<div>
|
||||
<span
|
||||
class="ant-badge"
|
||||
title="5">
|
||||
<a
|
||||
class="head-example"
|
||||
href="#" />
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true">
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-webkit-transform:translateY(-1500%);transform:translateY(-1500%);">
|
||||
<p
|
||||
class="">
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
9
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="current">
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
9
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="">
|
||||
9
|
||||
</p>
|
||||
</span>
|
||||
</sup>
|
||||
</span>
|
||||
<span
|
||||
class="ant-badge"
|
||||
title="0">
|
||||
<a
|
||||
class="head-example"
|
||||
href="#" />
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true">
|
||||
0
|
||||
</sup>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`test renders ./components/badge/demo/change.md correctly 1`] = `
|
||||
|
@ -7,19 +7,24 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
简单的徽章展示。
|
||||
简单的徽章展示,当 `count` 为 `0` 时,默认不显示,但是可以使用 `showZero` 修改为显示。
|
||||
|
||||
## en-US
|
||||
|
||||
Simplest Usage.
|
||||
Simplest Usage. Badge will be hidden when `count` is `0`, but we can use `showZero` to show it.
|
||||
|
||||
````jsx
|
||||
import { Badge } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Badge count={5}>
|
||||
<a href="#" className="head-example" />
|
||||
</Badge>
|
||||
<div>
|
||||
<Badge count={5}>
|
||||
<a href="#" className="head-example" />
|
||||
</Badge>
|
||||
<Badge count={0} showZero>
|
||||
<a href="#" className="head-example" />
|
||||
</Badge>
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
||||
|
||||
|
@ -27,6 +27,7 @@ Badge normally appears in proximity to notification or head picture with eye-cat
|
||||
|----------------|-------------------------|------------|---------|
|
||||
| count | Number to show in badge | number | |
|
||||
| overflowCount | Max count to show | number | 99 |
|
||||
| showZero | Whether to show badge when `count` is zero | boolean | false |
|
||||
| dot | Whether to show red dot without number | boolean | false |
|
||||
| status | Set Badge as a status dot | Enum{ 'success', 'processing, 'default', 'error', 'warning' } | '' |
|
||||
| text | If `status` is set, `text` is to set the text of status dot | string | '' |
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { PropTypes } from 'react';
|
||||
import Animate from 'rc-animate';
|
||||
import ScrollNumber from './ScrollNumber';
|
||||
import classNames from 'classnames';
|
||||
@ -7,6 +7,7 @@ import warning from '../_util/warning';
|
||||
export interface BadgeProps {
|
||||
/** Number to show in badge */
|
||||
count: number | string;
|
||||
showZero?: boolean;
|
||||
/** Max count to show */
|
||||
overflowCount?: number;
|
||||
/** whether to show red dot without number */
|
||||
@ -22,21 +23,35 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-badge',
|
||||
count: null,
|
||||
showZero: false,
|
||||
dot: false,
|
||||
overflowCount: 99,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
count: React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.number,
|
||||
count: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.number,
|
||||
]),
|
||||
dot: React.PropTypes.bool,
|
||||
overflowCount: React.PropTypes.number,
|
||||
showZero: PropTypes.bool,
|
||||
dot: PropTypes.bool,
|
||||
overflowCount: PropTypes.number,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { count, prefixCls, overflowCount, className, style, children, dot, status, text, ...restProps } = this.props;
|
||||
const {
|
||||
count,
|
||||
showZero,
|
||||
prefixCls,
|
||||
overflowCount,
|
||||
className,
|
||||
style,
|
||||
children,
|
||||
dot,
|
||||
status,
|
||||
text,
|
||||
...restProps,
|
||||
} = this.props;
|
||||
const isDot = dot || status;
|
||||
let displayCount = count > overflowCount ? `${overflowCount}+` : count;
|
||||
// dot mode don't need count
|
||||
@ -44,8 +59,9 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
displayCount = '';
|
||||
}
|
||||
|
||||
// null undefined "" "0" 0
|
||||
const hidden = (!displayCount || displayCount === '0') && !isDot;
|
||||
const isZero = displayCount === '0' || displayCount === 0;
|
||||
const isEmpty = displayCount === null || displayCount === undefined || displayCount === '';
|
||||
const hidden = (isEmpty || (isZero && !showZero)) && !isDot;
|
||||
const scrollNumberCls = classNames({
|
||||
[`${prefixCls}-dot`]: isDot,
|
||||
[`${prefixCls}-count`]: !isDot,
|
||||
|
@ -24,10 +24,11 @@ title: Badge
|
||||
<Badge count={5} />
|
||||
```
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|----------------|----------------------------------|------------|---------|--------|
|
||||
| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | number | | |
|
||||
| overflowCount | 展示封顶的数字值 | number | | 99 |
|
||||
| dot | 不展示数字,只有一个小红点 | boolean | | false |
|
||||
| status | 设置 Badge 为状态点 | Enum | 'success'、'processing'、'default'、'error'、'warning' | '' |
|
||||
| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | string | | '' |
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|----------------|----------------------------------|------------|---------|
|
||||
| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | number | |
|
||||
| overflowCount | 展示封顶的数字值 | number | 99 |
|
||||
| showZero | 当数值为 0 时,是否展示 Badge | boolean | false |
|
||||
| dot | 不展示数字,只有一个小红点 | boolean | false |
|
||||
| status | 设置 Badge 为状态点 | Enum{ 'success', 'processing, 'default', 'error', 'warning' } | '' |
|
||||
| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | string | '' |
|
||||
|
@ -2598,3 +2598,799 @@ exports[`test renders ./components/calendar/demo/notice-calendar.md correctly 1`
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`test renders ./components/calendar/demo/select.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-alert ant-alert-info ant-alert-no-icon"
|
||||
data-show="true">
|
||||
<span
|
||||
class="ant-alert-message">
|
||||
You selected date: 2017-01-25
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description" />
|
||||
</div>
|
||||
<div
|
||||
class=" ant-fullcalendar-fullscreen">
|
||||
<div
|
||||
class="ant-fullcalendar-header">
|
||||
<div
|
||||
class="ant-fullcalendar-year-select ant-select ant-select-enabled">
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-select-selection
|
||||
ant-select-selection--single"
|
||||
role="combobox"
|
||||
tabindex="0">
|
||||
<div
|
||||
class="ant-select-selection__rendered">
|
||||
<div
|
||||
class="ant-select-selection-selected-value"
|
||||
style="display:block;opacity:1;"
|
||||
title="2017年">
|
||||
2017年
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable">
|
||||
<b />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-month-select ant-select ant-select-enabled">
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-select-selection
|
||||
ant-select-selection--single"
|
||||
role="combobox"
|
||||
tabindex="0">
|
||||
<div
|
||||
class="ant-select-selection__rendered">
|
||||
<div
|
||||
class="ant-select-selection-selected-value"
|
||||
style="display:block;opacity:1;"
|
||||
title="1月">
|
||||
1月
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable">
|
||||
<b />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-radio-group ant-radio-group-default">
|
||||
<label
|
||||
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked">
|
||||
<span
|
||||
class="ant-radio-button ant-radio-button-checked">
|
||||
<input
|
||||
checked=""
|
||||
class="ant-radio-button-input"
|
||||
type="radio" />
|
||||
<span
|
||||
class="ant-radio-button-inner" />
|
||||
</span>
|
||||
<span>
|
||||
月
|
||||
</span>
|
||||
</label>
|
||||
<label
|
||||
class="ant-radio-button-wrapper">
|
||||
<span
|
||||
class="ant-radio-button">
|
||||
<input
|
||||
class="ant-radio-button-input"
|
||||
type="radio" />
|
||||
<span
|
||||
class="ant-radio-button-inner" />
|
||||
</span>
|
||||
<span>
|
||||
年
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar ant-fullcalendar-full ant-fullcalendar-fullscreen"
|
||||
tabindex="0">
|
||||
<div
|
||||
class="ant-fullcalendar-calendar-body">
|
||||
<table
|
||||
cellspacing="0"
|
||||
class="ant-fullcalendar-table"
|
||||
role="grid">
|
||||
<thead>
|
||||
<tr
|
||||
role="row">
|
||||
<th
|
||||
class="ant-fullcalendar-column-header"
|
||||
role="columnheader"
|
||||
title="周一">
|
||||
<span
|
||||
class="ant-fullcalendar-column-header-inner">
|
||||
一
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="ant-fullcalendar-column-header"
|
||||
role="columnheader"
|
||||
title="周二">
|
||||
<span
|
||||
class="ant-fullcalendar-column-header-inner">
|
||||
二
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="ant-fullcalendar-column-header"
|
||||
role="columnheader"
|
||||
title="周三">
|
||||
<span
|
||||
class="ant-fullcalendar-column-header-inner">
|
||||
三
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="ant-fullcalendar-column-header"
|
||||
role="columnheader"
|
||||
title="周四">
|
||||
<span
|
||||
class="ant-fullcalendar-column-header-inner">
|
||||
四
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="ant-fullcalendar-column-header"
|
||||
role="columnheader"
|
||||
title="周五">
|
||||
<span
|
||||
class="ant-fullcalendar-column-header-inner">
|
||||
五
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="ant-fullcalendar-column-header"
|
||||
role="columnheader"
|
||||
title="周六">
|
||||
<span
|
||||
class="ant-fullcalendar-column-header-inner">
|
||||
六
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="ant-fullcalendar-column-header"
|
||||
role="columnheader"
|
||||
title="周日">
|
||||
<span
|
||||
class="ant-fullcalendar-column-header-inner">
|
||||
日
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
class="ant-fullcalendar-tbody">
|
||||
<tr
|
||||
role="row">
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell"
|
||||
role="gridcell"
|
||||
title="2016-12-26">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
26
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell"
|
||||
role="gridcell"
|
||||
title="2016-12-27">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
27
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell"
|
||||
role="gridcell"
|
||||
title="2016-12-28">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
28
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell"
|
||||
role="gridcell"
|
||||
title="2016-12-29">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
29
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell"
|
||||
role="gridcell"
|
||||
title="2016-12-30">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
30
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell"
|
||||
role="gridcell"
|
||||
title="2016-12-31">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
31
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-1">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
01
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
role="row">
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-2">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
02
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-3">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
03
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-4">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
04
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-5">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
05
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-6">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
06
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-7">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
07
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-8">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
08
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
role="row">
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-9">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
09
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-10">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
10
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-11">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
11
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-12">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
12
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-13">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
13
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-14">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
14
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-15">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
15
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
role="row">
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-16">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
16
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-17">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
17
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-18">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
18
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-19">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
19
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-20">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
20
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-21">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
21
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-22">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
22
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
role="row">
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-23">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
23
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-24">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
24
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-selected-day"
|
||||
role="gridcell"
|
||||
title="2017-1-25">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
25
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-26">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
26
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-27">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
27
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-28">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
28
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-29">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
29
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
role="row">
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-30">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
30
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
role="gridcell"
|
||||
title="2017-1-31">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
31
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-next-month-btn-day"
|
||||
role="gridcell"
|
||||
title="2017-2-1">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
01
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-next-month-btn-day"
|
||||
role="gridcell"
|
||||
title="2017-2-2">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
02
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-next-month-btn-day"
|
||||
role="gridcell"
|
||||
title="2017-2-3">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
03
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-next-month-btn-day"
|
||||
role="gridcell"
|
||||
title="2017-2-4">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
04
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-next-month-btn-day"
|
||||
role="gridcell"
|
||||
title="2017-2-5">
|
||||
<div
|
||||
class="ant-fullcalendar-date">
|
||||
<div
|
||||
class="ant-fullcalendar-value">
|
||||
05
|
||||
</div>
|
||||
<div
|
||||
class="ant-fullcalendar-content" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
17
components/calendar/__tests__/index.test.js
Normal file
17
components/calendar/__tests__/index.test.js
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import Moment from 'moment';
|
||||
import { mount } from 'enzyme';
|
||||
import Calendar from '..';
|
||||
|
||||
describe('Calendar', () => {
|
||||
it('Calendar should be selectable', () => {
|
||||
const onSelect = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Calendar onSelect={onSelect} />
|
||||
);
|
||||
wrapper.find('.ant-fullcalendar-cell').at(0).simulate('click');
|
||||
expect(onSelect).toBeCalledWith(expect.anything());
|
||||
const value = onSelect.mock.calls[0][0];
|
||||
expect(Moment.isMoment(value)).toBe(true);
|
||||
});
|
||||
});
|
46
components/calendar/demo/select.md
Normal file
46
components/calendar/demo/select.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 选择功能
|
||||
en-US: Selectable Calendar
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
一个通用的日历面板,支持年/月切换。
|
||||
|
||||
## en-US
|
||||
|
||||
A basic calendar component with Year/Month switch.
|
||||
|
||||
````jsx
|
||||
import { Calendar, Alert } from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
value: moment('2017-01-25'),
|
||||
selectedValue: moment('2017-01-25'),
|
||||
}
|
||||
onSelect = (value) => {
|
||||
this.setState({
|
||||
value,
|
||||
selectedValue: value,
|
||||
});
|
||||
}
|
||||
onPanelChange = (value) => {
|
||||
this.setState({ value });
|
||||
}
|
||||
render() {
|
||||
const { value, selectedValue } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Alert message={`You selected date: ${selectedValue && selectedValue.format('YYYY-MM-DD')}`} />
|
||||
<Calendar value={value} onSelect={this.onSelect} onPanelChange={this.onPanelChange} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
````
|
@ -26,6 +26,7 @@ moment.locale('zh-cn');
|
||||
dateCellRender={dateCellRender}
|
||||
monthCellRender={monthCellRender}
|
||||
onPanelChange={onPanelChange}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
```
|
||||
|
||||
@ -35,7 +36,10 @@ moment.locale('zh-cn');
|
||||
| defaultValue | set default date | [moment](http://momentjs.com/) | default date |
|
||||
| mode | can be set to month or year | string | month |
|
||||
| fullscreen | to set whether full-screen display | boolean | true |
|
||||
| dateCellRender | to set the way of renderer the date cell | function(date: moment): ReactNode | - |
|
||||
| monthCellRender | to set the way of renderer the month cell | function(date: moment): ReactNode | - |
|
||||
| dateCellRender | to set the way of renderer the date cell, the returned content will be appended to the cell | function(date: moment): ReactNode | - |
|
||||
| monthCellRender | to set the way of renderer the month cell, the returned content will be appended to the cell | function(date: moment): ReactNode | - |
|
||||
| dateFullCellRender | to set the way of renderer the date cell,the returned content will override the cell | function(date: moment): ReactNode | - |
|
||||
| monthFullCellRender | to set the way of renderer the month cell,the returned content will override the cell | function(date: moment): ReactNode | - |
|
||||
| locale | set locale | object | [default](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) |
|
||||
| onPanelChange| the callback when panel change | function(date: moment, mode: string) | - |
|
||||
| onPanelChange| callback when panel change | function(date: moment, mode: string) | - |
|
||||
| onSelect | callback when select date | function(date: moment) | - |
|
||||
|
@ -33,9 +33,12 @@ export interface CalendarProps {
|
||||
fullscreen?: boolean;
|
||||
dateCellRender?: (date: moment.Moment) => React.ReactNode;
|
||||
monthCellRender?: (date: moment.Moment) => React.ReactNode;
|
||||
dateFullCellRender?: (date: moment.Moment) => React.ReactNode;
|
||||
monthFullCellRender?: (date: moment.Moment) => React.ReactNode;
|
||||
locale?: any;
|
||||
style?: React.CSSProperties;
|
||||
onPanelChange?: (date?: moment.Moment, mode?: CalendarMode) => void;
|
||||
onSelect?: (date?: moment.Moment) => void;
|
||||
}
|
||||
|
||||
export interface CalendarState {
|
||||
@ -49,11 +52,15 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
fullscreen: true,
|
||||
prefixCls: PREFIX_CLS,
|
||||
mode: 'month',
|
||||
onSelect: noop,
|
||||
onPanelChange: noop,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
monthCellRender: PropTypes.func,
|
||||
dateCellRender: PropTypes.func,
|
||||
monthFullCellRender: PropTypes.func,
|
||||
dateFullCellRender: PropTypes.func,
|
||||
fullscreen: PropTypes.bool,
|
||||
locale: PropTypes.object,
|
||||
prefixCls: PropTypes.string,
|
||||
@ -61,6 +68,7 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
style: PropTypes.object,
|
||||
onPanelChange: PropTypes.func,
|
||||
value: PropTypes.object,
|
||||
onSelect: PropTypes.func,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
@ -123,13 +131,16 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
);
|
||||
}
|
||||
|
||||
setValue = (value) => {
|
||||
if (!('value' in this.props) && this.state.value !== value) {
|
||||
setValue = (value, way: 'select' | 'changePanel') => {
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ value });
|
||||
}
|
||||
const onPanelChange = this.props.onPanelChange;
|
||||
if (onPanelChange) {
|
||||
onPanelChange(value, this.state.mode);
|
||||
if (way === 'select') {
|
||||
if (this.props.onSelect) {
|
||||
this.props.onSelect(value);
|
||||
}
|
||||
} else if (way === 'changePanel') {
|
||||
this.onPanelChange(value, this.state.mode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,13 +148,29 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
const mode = (type === 'date') ? 'month' : 'year';
|
||||
if (this.state.mode !== mode) {
|
||||
this.setState({ mode });
|
||||
const onPanelChange = this.props.onPanelChange;
|
||||
if (onPanelChange) {
|
||||
onPanelChange(this.state.value, mode);
|
||||
}
|
||||
this.onPanelChange(this.state.value, mode);
|
||||
}
|
||||
}
|
||||
|
||||
onHeaderValueChange = (value) => {
|
||||
this.setValue(value, 'changePanel');
|
||||
}
|
||||
|
||||
onHeaderTypeChange = (type) => {
|
||||
this.setType(type);
|
||||
}
|
||||
|
||||
onPanelChange(value, mode) {
|
||||
const { onPanelChange } = this.props;
|
||||
if (onPanelChange) {
|
||||
onPanelChange(value, mode);
|
||||
}
|
||||
}
|
||||
|
||||
onSelect = (value) => {
|
||||
this.setValue(value, 'select');
|
||||
}
|
||||
|
||||
render() {
|
||||
const { state, props, context } = this;
|
||||
const { value, mode } = state;
|
||||
@ -151,7 +178,7 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
if (value && localeCode) {
|
||||
value.locale(localeCode);
|
||||
}
|
||||
const { prefixCls, style, className, fullscreen } = props;
|
||||
const { prefixCls, style, className, fullscreen, dateFullCellRender, monthFullCellRender } = props;
|
||||
const type = (mode === 'year') ? 'month' : 'date';
|
||||
const locale = getComponentLocale(props, context, 'Calendar', () => require('./locale/zh_CN'));
|
||||
|
||||
@ -160,6 +187,9 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
cls += (` ${prefixCls}-fullscreen`);
|
||||
}
|
||||
|
||||
const monthCellRender = monthFullCellRender || this.monthCellRender;
|
||||
const dateCellRender = dateFullCellRender || this.dateCellRender;
|
||||
|
||||
return (
|
||||
<div className={cls} style={style}>
|
||||
<Header
|
||||
@ -168,8 +198,8 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
value={value}
|
||||
locale={locale.lang}
|
||||
prefixCls={prefixCls}
|
||||
onTypeChange={this.setType}
|
||||
onValueChange={this.setValue}
|
||||
onTypeChange={this.onHeaderTypeChange}
|
||||
onValueChange={this.onHeaderValueChange}
|
||||
/>
|
||||
<FullCalendar
|
||||
{...props}
|
||||
@ -179,8 +209,9 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
prefixCls={prefixCls}
|
||||
showHeader={false}
|
||||
value={value}
|
||||
monthCellRender={this.monthCellRender}
|
||||
dateCellRender={this.dateCellRender}
|
||||
monthCellRender={monthCellRender}
|
||||
dateCellRender={dateCellRender}
|
||||
onSelect={this.onSelect}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -28,6 +28,7 @@ moment.locale('zh-cn');
|
||||
dateCellRender={dateCellRender}
|
||||
monthCellRender={monthCellRender}
|
||||
onPanelChange={onPanelChange}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
```
|
||||
|
||||
@ -37,7 +38,10 @@ moment.locale('zh-cn');
|
||||
| defaultValue | 默认展示的日期 | [moment](http://momentjs.com/) | 默认日期 |
|
||||
| mode | 初始模式,`month/year` | string | month |
|
||||
| fullscreen | 是否全屏显示 | boolean | true |
|
||||
| dateCellRender | 自定义渲染日期单元格| function(date: moment): ReactNode | 无 |
|
||||
| monthCellRender | 自定义渲染月单元格 | function(date: moment): ReactNode | 无 |
|
||||
| dateCellRender | 自定义渲染日期单元格,返回内容会被追加到单元格| function(date: moment): ReactNode | 无 |
|
||||
| monthCellRender | 自定义渲染月单元格,返回内容会被追加到单元格 | function(date: moment): ReactNode | 无 |
|
||||
| dateFullCellRender | 自定义渲染日期单元格,返回内容覆盖单元格| function(date: moment): ReactNode | 无 |
|
||||
| monthFullCellRender | 自定义渲染月单元格,返回内容覆盖单元格 | function(date: moment): ReactNode | 无 |
|
||||
| locale | 国际化配置 | object | [默认配置](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) |
|
||||
| onPanelChange| 日期面板变化回调 | function(date: moment, mode: string) | 无 |
|
||||
| onSelect | 点击选择日期回调 | function(date: moment) | 无 |
|
||||
|
2
components/calendar/locale/ca_ES.tsx
Normal file
2
components/calendar/locale/ca_ES.tsx
Normal file
@ -0,0 +1,2 @@
|
||||
import ca_ES from '../../date-picker/locale/ca_ES';
|
||||
export default ca_ES;
|
2
components/calendar/locale/cs_CZ.tsx
Normal file
2
components/calendar/locale/cs_CZ.tsx
Normal file
@ -0,0 +1,2 @@
|
||||
import cs_CZ from '../../date-picker/locale/cs_CZ';
|
||||
export default cs_CZ;
|
2
components/calendar/locale/ko_KR.tsx
Normal file
2
components/calendar/locale/ko_KR.tsx
Normal file
@ -0,0 +1,2 @@
|
||||
import ko_KR from '../../date-picker/locale/ko_KR';
|
||||
export default ko_KR;
|
2
components/calendar/locale/nl_NL.tsx
Normal file
2
components/calendar/locale/nl_NL.tsx
Normal file
@ -0,0 +1,2 @@
|
||||
import nl_NL from '../../date-picker/locale/nl_NL';
|
||||
export default nl_NL;
|
@ -84,23 +84,30 @@
|
||||
&-month,
|
||||
&-date {
|
||||
text-align: center;
|
||||
transition: all .3s;
|
||||
}
|
||||
|
||||
&-value {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
color: @text-color;
|
||||
border-radius: 4px;
|
||||
border-radius: @border-radius-base;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
line-height: 22px;
|
||||
transition: all .3s;
|
||||
|
||||
&:hover {
|
||||
background: @primary-1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: @primary-color;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&-month-panel-cell &-value {
|
||||
@ -109,30 +116,35 @@
|
||||
|
||||
&-today &-value,
|
||||
&-month-panel-current-cell &-value {
|
||||
box-shadow: 0 0 0 1px @primary-color;
|
||||
}
|
||||
|
||||
&-selected-day &-value,
|
||||
&-month-panel-selected-cell &-value {
|
||||
background: @primary-color;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&-disabled-cell &-value {
|
||||
cursor: not-allowed;
|
||||
color: #bcbcbc;
|
||||
background: #f3f3f3;
|
||||
color: @disabled-color;
|
||||
background: @background-color-base;
|
||||
border-radius: 0;
|
||||
width: auto;
|
||||
|
||||
&:hover {
|
||||
background: #f3f3f3;
|
||||
background: @background-color-base;
|
||||
}
|
||||
}
|
||||
|
||||
&-disabled-cell-first-of-row &-value {
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-top-left-radius: @border-radius-base;
|
||||
border-bottom-left-radius: @border-radius-base;
|
||||
}
|
||||
|
||||
&-disabled-cell-last-of-row &-value {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-right-radius: @border-radius-base;
|
||||
border-bottom-right-radius: @border-radius-base;
|
||||
}
|
||||
|
||||
&-last-month-cell &-value,
|
||||
@ -166,8 +178,8 @@
|
||||
margin-left: 16px;
|
||||
}
|
||||
label.@{ant-prefix}-radio-button {
|
||||
height: 28px;
|
||||
line-height: 26px;
|
||||
height: @input-height-base;
|
||||
line-height: @input-height-base - 2px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,12 +192,16 @@
|
||||
height: 116px;
|
||||
padding: 4px 8px;
|
||||
border-top: 2px solid @border-color-split;
|
||||
transition: background 0.3s ease;
|
||||
transition: background .3s;
|
||||
|
||||
&:hover {
|
||||
background: @primary-1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: @primary-2;
|
||||
}
|
||||
}
|
||||
|
||||
&-fullscreen &-column-header {
|
||||
@ -207,12 +223,24 @@
|
||||
&-fullscreen &-month-panel-current-cell &-month,
|
||||
&-fullscreen &-today &-date {
|
||||
border-top-color: @primary-color;
|
||||
background-color: @primary-1;
|
||||
color: @primary-color;
|
||||
}
|
||||
&-fullscreen &-month-panel-current-cell &-value {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&-fullscreen &-month-panel-current-cell &-value,
|
||||
&-fullscreen &-today &-value {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&-fullscreen &-month-panel-selected-cell &-month,
|
||||
&-fullscreen &-selected-day &-date {
|
||||
background: @primary-1;
|
||||
}
|
||||
|
||||
&-fullscreen &-month-panel-selected-cell &-value,
|
||||
&-fullscreen &-selected-day &-value {
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
&-fullscreen &-last-month-cell &-date,
|
||||
&-fullscreen &-next-month-btn-day &-date {
|
||||
color: @disabled-color;
|
||||
|
17
components/date-picker/locale/ca_ES.tsx
Normal file
17
components/date-picker/locale/ca_ES.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import CalendarLocale from 'rc-calendar/lib/locale/ca_ES';
|
||||
import TimePickerLocale from '../../time-picker/locale/ca_ES';
|
||||
import assign from 'object-assign';
|
||||
|
||||
// 统一合并为完整的 Locale
|
||||
const locale = {
|
||||
lang: assign({
|
||||
placeholder: 'Seleccionar data',
|
||||
rangePlaceholder: ['Data inicial', 'Data final'],
|
||||
}, 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;
|
17
components/date-picker/locale/cs_CZ.tsx
Normal file
17
components/date-picker/locale/cs_CZ.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import CalendarLocale from 'rc-calendar/lib/locale/cs_CZ';
|
||||
import TimePickerLocale from '../../time-picker/locale/cs_CZ';
|
||||
import assign from 'object-assign';
|
||||
|
||||
// 统一合并为完整的 Locale
|
||||
const locale = {
|
||||
lang: assign({
|
||||
placeholder: 'Vybrat datum',
|
||||
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;
|
17
components/date-picker/locale/ko_KR.tsx
Normal file
17
components/date-picker/locale/ko_KR.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import CalendarLocale from 'rc-calendar/lib/locale/ko_KR';
|
||||
import TimePickerLocale from '../../time-picker/locale/ko_KR';
|
||||
import assign from 'object-assign';
|
||||
|
||||
// 统一合并为完整的 Locale
|
||||
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;
|
17
components/date-picker/locale/nl_NL.tsx
Normal file
17
components/date-picker/locale/nl_NL.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import CalendarLocale from 'rc-calendar/lib/locale/nl_NL';
|
||||
import TimePickerLocale from '../../time-picker/locale/nl_NL';
|
||||
import assign from 'object-assign';
|
||||
|
||||
// 统一合并为完整的 Locale
|
||||
const locale = {
|
||||
lang: assign({
|
||||
placeholder: 'Selecteer datum',
|
||||
rangePlaceholder: ['Begin datum', 'Eind datum'],
|
||||
}, CalendarLocale),
|
||||
timePickerLocale: assign({}, TimePickerLocale),
|
||||
};
|
||||
|
||||
// All settings at:
|
||||
// https://github.com/ant-design/ant-design/issues/424
|
||||
|
||||
export default locale;
|
@ -17,6 +17,7 @@ export interface FormCreateOption {
|
||||
}
|
||||
|
||||
export interface FormProps {
|
||||
layout?: 'horizontal' | 'inline' | 'vertical';
|
||||
horizontal?: boolean;
|
||||
inline?: boolean;
|
||||
vertical?: boolean;
|
||||
@ -87,6 +88,7 @@ export interface ComponentDecorator {
|
||||
export default class Form extends React.Component<FormProps, any> {
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-form',
|
||||
layout: 'horizontal',
|
||||
hideRequiredMark: false,
|
||||
onSubmit(e) {
|
||||
e.preventDefault();
|
||||
@ -94,13 +96,11 @@ export default class Form extends React.Component<FormProps, any> {
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
prefixCls: React.PropTypes.string,
|
||||
vertical: React.PropTypes.bool,
|
||||
horizontal: React.PropTypes.bool,
|
||||
inline: React.PropTypes.bool,
|
||||
children: React.PropTypes.any,
|
||||
onSubmit: React.PropTypes.func,
|
||||
hideRequiredMark: React.PropTypes.bool,
|
||||
prefixCls: PropTypes.string,
|
||||
layout: PropTypes.oneOf(['horizontal', 'inline', 'vertical']),
|
||||
children: PropTypes.any,
|
||||
onSubmit: PropTypes.func,
|
||||
hideRequiredMark: PropTypes.bool,
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
@ -163,23 +163,33 @@ export default class Form extends React.Component<FormProps, any> {
|
||||
}
|
||||
|
||||
getChildContext() {
|
||||
const { layout, vertical } = this.props;
|
||||
return {
|
||||
vertical: this.props.vertical,
|
||||
vertical: layout === 'vertical' || vertical,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, hideRequiredMark, className = '', inline, horizontal, vertical } = this.props;
|
||||
const {
|
||||
prefixCls, hideRequiredMark, className = '', layout,
|
||||
// @deprecated
|
||||
inline, horizontal, vertical,
|
||||
} = this.props;
|
||||
warning(
|
||||
!inline && !horizontal && !vertical,
|
||||
'`Form[inline|horizontal|vertical]` is deprecated, please use `Form[layout]` instead.'
|
||||
);
|
||||
const formClassName = classNames(prefixCls, {
|
||||
[`${prefixCls}-horizontal`]: horizontal,
|
||||
[`${prefixCls}-vertical`]: vertical,
|
||||
[`${prefixCls}-inline`]: inline,
|
||||
[`${prefixCls}-horizontal`]: (!inline && !vertical && layout === 'horizontal') || horizontal,
|
||||
[`${prefixCls}-vertical`]: layout === 'vertical' || vertical,
|
||||
[`${prefixCls}-inline`]: layout === 'inline' || inline,
|
||||
[`${prefixCls}-hide-required-mark`]: hideRequiredMark,
|
||||
}, className);
|
||||
|
||||
const formProps = omit(this.props, [
|
||||
'prefixCls',
|
||||
'className',
|
||||
'layout',
|
||||
'inline',
|
||||
'horizontal',
|
||||
'vertical',
|
||||
|
@ -1,7 +1,7 @@
|
||||
exports[`test renders ./components/form/demo/advanced-search.md correctly 1`] = `
|
||||
<div>
|
||||
<form
|
||||
class="ant-form ant-advanced-search-form">
|
||||
class="ant-form ant-form-horizontal ant-advanced-search-form">
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left:-20px;margin-right:-20px;">
|
||||
@ -218,7 +218,7 @@ exports[`test renders ./components/form/demo/advanced-search.md correctly 1`] =
|
||||
|
||||
exports[`test renders ./components/form/demo/coordinated.md correctly 1`] = `
|
||||
<form
|
||||
class="ant-form">
|
||||
class="ant-form ant-form-horizontal">
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
@ -291,7 +291,7 @@ exports[`test renders ./components/form/demo/coordinated.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
class="ant-col-8 ant-col-offset-4 ant-form-item-control-wrapper">
|
||||
class="ant-form-item-control-wrapper ant-col-xs-8 ant-col-xs-offset-0 ant-col-sm-8 ant-col-sm-offset-4">
|
||||
<div
|
||||
class="ant-form-item-control ">
|
||||
<button
|
||||
@ -384,11 +384,11 @@ exports[`test renders ./components/form/demo/customized-form-controls.md correct
|
||||
|
||||
exports[`test renders ./components/form/demo/dynamic-form-item.md correctly 1`] = `
|
||||
<form
|
||||
class="ant-form">
|
||||
class="ant-form ant-form-horizontal">
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
class="ant-col-20 ant-col-offset-4 ant-form-item-control-wrapper">
|
||||
class="ant-form-item-control-wrapper ant-col-xs-20 ant-col-xs-offset-0 ant-col-sm-20 ant-col-sm-offset-4">
|
||||
<div
|
||||
class="ant-form-item-control ">
|
||||
<button
|
||||
@ -407,7 +407,7 @@ exports[`test renders ./components/form/demo/dynamic-form-item.md correctly 1`]
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
class="ant-col-20 ant-col-offset-4 ant-form-item-control-wrapper">
|
||||
class="ant-form-item-control-wrapper ant-col-xs-20 ant-col-xs-offset-0 ant-col-sm-20 ant-col-sm-offset-4">
|
||||
<div
|
||||
class="ant-form-item-control ">
|
||||
<button
|
||||
@ -657,7 +657,7 @@ exports[`test renders ./components/form/demo/layout.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
class="ant-col-14 ant-col-offset-4 ant-form-item-control-wrapper">
|
||||
class="ant-form-item-control-wrapper ant-col-xs-14 ant-col-xs-offset-0 ant-col-sm-14 ant-col-sm-offset-4">
|
||||
<div
|
||||
class="ant-form-item-control ">
|
||||
<button
|
||||
@ -676,7 +676,7 @@ exports[`test renders ./components/form/demo/layout.md correctly 1`] = `
|
||||
|
||||
exports[`test renders ./components/form/demo/normal-login.md correctly 1`] = `
|
||||
<form
|
||||
class="ant-form login-form">
|
||||
class="ant-form ant-form-horizontal login-form">
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
@ -769,7 +769,7 @@ exports[`test renders ./components/form/demo/normal-login.md correctly 1`] = `
|
||||
|
||||
exports[`test renders ./components/form/demo/register.md correctly 1`] = `
|
||||
<form
|
||||
class="ant-form">
|
||||
class="ant-form ant-form-horizontal">
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
@ -1016,7 +1016,7 @@ exports[`test renders ./components/form/demo/register.md correctly 1`] = `
|
||||
class="ant-row ant-form-item"
|
||||
style="margin-bottom:8px;">
|
||||
<div
|
||||
class="ant-col-14 ant-col-offset-6 ant-form-item-control-wrapper">
|
||||
class="ant-form-item-control-wrapper ant-col-xs-14 ant-col-xs-offset-0 ant-col-sm-14 ant-col-sm-offset-6">
|
||||
<div
|
||||
class="ant-form-item-control ">
|
||||
<label
|
||||
@ -1042,7 +1042,7 @@ exports[`test renders ./components/form/demo/register.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
class="ant-col-14 ant-col-offset-6 ant-form-item-control-wrapper">
|
||||
class="ant-form-item-control-wrapper ant-col-xs-14 ant-col-xs-offset-0 ant-col-sm-14 ant-col-sm-offset-6">
|
||||
<div
|
||||
class="ant-form-item-control ">
|
||||
<button
|
||||
@ -1060,7 +1060,7 @@ exports[`test renders ./components/form/demo/register.md correctly 1`] = `
|
||||
|
||||
exports[`test renders ./components/form/demo/time-related-controls.md correctly 1`] = `
|
||||
<form
|
||||
class="ant-form">
|
||||
class="ant-form ant-form-horizontal">
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
@ -1265,7 +1265,7 @@ exports[`test renders ./components/form/demo/time-related-controls.md correctly
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
class="ant-col-16 ant-col-offset-8 ant-form-item-control-wrapper">
|
||||
class="ant-form-item-control-wrapper ant-col-xs-16 ant-col-xs-offset-0 ant-col-sm-16 ant-col-sm-offset-8">
|
||||
<div
|
||||
class="ant-form-item-control ">
|
||||
<button
|
||||
@ -1283,7 +1283,7 @@ exports[`test renders ./components/form/demo/time-related-controls.md correctly
|
||||
|
||||
exports[`test renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
<form
|
||||
class="ant-form">
|
||||
class="ant-form ant-form-horizontal">
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
@ -1720,7 +1720,7 @@ exports[`test renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-row ant-form-item">
|
||||
<div
|
||||
class="ant-col-12 ant-col-offset-6 ant-form-item-control-wrapper">
|
||||
class="ant-form-item-control-wrapper ant-col-xs-12 ant-col-xs-offset-0 ant-col-sm-12 ant-col-sm-offset-6">
|
||||
<div
|
||||
class="ant-form-item-control ">
|
||||
<button
|
||||
@ -1738,7 +1738,7 @@ exports[`test renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
|
||||
exports[`test renders ./components/form/demo/validate-static.md correctly 1`] = `
|
||||
<form
|
||||
class="ant-form">
|
||||
class="ant-form ant-form-horizontal">
|
||||
<div
|
||||
class="ant-row ant-form-item ant-form-item-with-help">
|
||||
<div
|
||||
@ -1966,7 +1966,7 @@ exports[`test renders ./components/form/demo/validate-static.md correctly 1`] =
|
||||
|
||||
exports[`test renders ./components/form/demo/without-form-create.md correctly 1`] = `
|
||||
<form
|
||||
class="ant-form">
|
||||
class="ant-form ant-form-horizontal">
|
||||
<div
|
||||
class="ant-row ant-form-item ant-form-item-with-help">
|
||||
<div
|
||||
|
@ -27,7 +27,7 @@ describe('Form', () => {
|
||||
|
||||
it('should not remove duplicated user input colon when layout is vertical', () => {
|
||||
const wrapper = mount(
|
||||
<Form vertical>
|
||||
<Form layout="vertical">
|
||||
<Form.Item label="label:">input</Form.Item>
|
||||
<Form.Item label="label:">input</Form.Item>
|
||||
</Form>
|
||||
|
@ -63,7 +63,12 @@ class App extends React.Component {
|
||||
</Select>
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem wrapperCol={{ span: 8, offset: 4 }}>
|
||||
<FormItem
|
||||
wrapperCol={{
|
||||
xs: { span: 8, offset: 0 },
|
||||
sm: { span: 8, offset: 4 },
|
||||
}}
|
||||
>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Submit
|
||||
</Button>
|
||||
|
@ -108,7 +108,7 @@ class Demo extends React.Component {
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<Form inline onSubmit={this.handleSubmit}>
|
||||
<Form layout="inline" onSubmit={this.handleSubmit}>
|
||||
<FormItem label="Price">
|
||||
{getFieldDecorator('price', {
|
||||
initialValue: { number: 0, currency: 'rmb' },
|
||||
|
@ -63,7 +63,10 @@ class DynamicFieldSet extends React.Component {
|
||||
wrapperCol: { span: 20 },
|
||||
};
|
||||
const formItemLayoutWithOutLabel = {
|
||||
wrapperCol: { span: 20, offset: 4 },
|
||||
wrapperCol: {
|
||||
xs: { span: 20, offset: 0 },
|
||||
sm: { span: 20, offset: 4 },
|
||||
},
|
||||
};
|
||||
getFieldDecorator('keys', { initialValue: [] });
|
||||
const keys = getFieldValue('keys');
|
||||
|
@ -29,7 +29,7 @@ const CollectionCreateForm = Form.create()(
|
||||
onCancel={onCancel}
|
||||
onOk={onCreate}
|
||||
>
|
||||
<Form vertical>
|
||||
<Form layout="vertical">
|
||||
<FormItem label="Title">
|
||||
{getFieldDecorator('title', {
|
||||
rules: [{ required: true, message: 'Please input the title of collection!' }],
|
||||
|
@ -35,7 +35,7 @@ const CustomizedForm = Form.create({
|
||||
})((props) => {
|
||||
const { getFieldDecorator } = props.form;
|
||||
return (
|
||||
<Form inline>
|
||||
<Form layout="inline">
|
||||
<FormItem label="Username">
|
||||
{getFieldDecorator('username', {
|
||||
rules: [{ required: true, message: 'Username is required!' }],
|
||||
|
@ -41,7 +41,7 @@ class HorizontalLoginForm extends React.Component {
|
||||
const userNameError = isFieldTouched('userName') && getFieldError('userName');
|
||||
const passwordError = isFieldTouched('password') && getFieldError('password');
|
||||
return (
|
||||
<Form inline onSubmit={this.handleSubmit}>
|
||||
<Form layout="inline" onSubmit={this.handleSubmit}>
|
||||
<FormItem
|
||||
validateStatus={userNameError ? 'error' : ''}
|
||||
help={userNameError || ''}
|
||||
|
@ -34,12 +34,14 @@ class FormLayoutDemo extends React.Component {
|
||||
wrapperCol: { span: 14 },
|
||||
} : null;
|
||||
const buttonItemLayout = formLayout === 'horizontal' ? {
|
||||
wrapperCol: { span: 14, offset: 4 },
|
||||
wrapperCol: {
|
||||
xs: { span: 14, offset: 0 },
|
||||
sm: { span: 14, offset: 4 },
|
||||
},
|
||||
} : null;
|
||||
const layoutProps = { [formLayout]: true };
|
||||
return (
|
||||
<div>
|
||||
<Form {...layoutProps}>
|
||||
<Form layout={formLayout}>
|
||||
<FormItem
|
||||
label="Form Layout"
|
||||
{...formItemLayout}
|
||||
|
@ -81,8 +81,14 @@ class RegistrationForm extends React.Component {
|
||||
};
|
||||
const tailFormItemLayout = {
|
||||
wrapperCol: {
|
||||
span: 14,
|
||||
offset: 6,
|
||||
xs: {
|
||||
span: 14,
|
||||
offset: 0,
|
||||
},
|
||||
sm: {
|
||||
span: 14,
|
||||
offset: 6,
|
||||
},
|
||||
},
|
||||
};
|
||||
const prefixSelector = getFieldDecorator('prefix', {
|
||||
|
@ -108,7 +108,12 @@ class TimeRelatedForm extends React.Component {
|
||||
<TimePicker />
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem wrapperCol={{ span: 16, offset: 8 }}>
|
||||
<FormItem
|
||||
wrapperCol={{
|
||||
xs: { span: 16, offset: 0 },
|
||||
sm: { span: 16, offset: 8 },
|
||||
}}
|
||||
>
|
||||
<Button type="primary" htmlType="submit" size="large">Submit</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
|
@ -157,7 +157,12 @@ class Demo extends React.Component {
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem wrapperCol={{ span: 12, offset: 6 }}>
|
||||
<FormItem
|
||||
wrapperCol={{
|
||||
xs: { span: 12, offset: 0 },
|
||||
sm: { span: 12, offset: 6 },
|
||||
}}
|
||||
>
|
||||
<Button type="primary" htmlType="submit">Submit</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
|
@ -37,8 +37,10 @@ A form field is defined using `<Form.Item />`.
|
||||
| Property | Description | Type | Default Value |
|
||||
|-----------|------------------------------------------|------------|---------|
|
||||
| form | Decorated by `Form.create()` will be automatically set `this.props.form` property, so just pass to form, you don't need to set it by yourself after 1.7.0. | object | n/a
|
||||
| vertical | Use vertical layout. | boolean | false |
|
||||
| inline | Use inline alignment. | boolean | false |
|
||||
| layout | Define form layout(Support after 2.8) | 'horizontal'\|'vertical'\|'inline' | 'horizontal' |
|
||||
| horizontal | Use horizontal layout(Deprecated after 2.8) | boolean | true |
|
||||
| vertical | Use vertical layout(Deprecated after 2.8) | boolean | false |
|
||||
| inline | Use inline alignment(Deprecated after 2.8) | boolean | false |
|
||||
| onSubmit | Defines a function will be called if form data validation is successful. | Function(e:Event) | |
|
||||
| hideRequiredMark | Hide required mark of all form items | Boolean | false |
|
||||
|
||||
|
@ -39,8 +39,10 @@ title: Form
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|-----------|------------------------------------------|------------|-------|
|
||||
| form | 经 `Form.create()` 包装过的组件会自带 `this.props.form` 属性,直接传给 Form 即可。1.7.0 之后无需设置 | object | 无 |
|
||||
| vertical | 垂直排列布局 | boolean | false |
|
||||
| inline | 行内排列布局 | boolean | false |
|
||||
| layout | 表单布局(2.8 之后支持) | 'horizontal'\|'vertical'\|'inline' | 'horizontal' |
|
||||
| horizontal | 水平排列布局(2.8 之后废弃) | boolean | true |
|
||||
| vertical | 垂直排列布局(2.8 之后废弃) | boolean | false |
|
||||
| inline | 行内排列布局(2.8 之后废弃) | boolean | false |
|
||||
| onSubmit | 数据验证成功后回调事件 | Function(e:Event) | |
|
||||
| hideRequiredMark | 隐藏所有表单项的必选标记 | Boolean | false |
|
||||
|
||||
|
@ -86,33 +86,24 @@ input[type="checkbox"] {
|
||||
}
|
||||
|
||||
&-label {
|
||||
text-align: right;
|
||||
display: block;
|
||||
float: none; // To reset `col-*`
|
||||
padding: 0 0 8px;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
line-height: @form-component-height;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
label {
|
||||
color: @label-color;
|
||||
|
||||
&:after {
|
||||
content: ":";
|
||||
margin: 0 8px 0 2px;
|
||||
position: relative;
|
||||
top: -0.5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{ant-prefix}-switch {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
&-no-colon &-label label:after {
|
||||
content: " ";
|
||||
}
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-explain {
|
||||
@ -247,47 +238,59 @@ form {
|
||||
}
|
||||
}
|
||||
|
||||
// Form layout
|
||||
//== Vertical Form
|
||||
.@{form-prefix-cls}-vertical .@{form-prefix-cls}-item-label,
|
||||
.@{ant-prefix}-col-24.@{form-prefix-cls}-item-label { // when labelCol is 24, it is a vertical form
|
||||
padding: 0 0 8px;
|
||||
display: block;
|
||||
text-align: left;
|
||||
|
||||
label:after {
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
//== Inline Form
|
||||
.@{form-prefix-cls}-inline {
|
||||
.@{form-prefix-cls}-item {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 0;
|
||||
|
||||
&-with-help {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
> div {
|
||||
@media (min-width: @screen-sm) {
|
||||
// Form layout
|
||||
// == common style of Horizontal Form & Inline Form
|
||||
.@{form-prefix-cls}-horizontal,
|
||||
.@{form-prefix-cls}-inline {
|
||||
// when labelCol is 24, it is a vertical form
|
||||
.@{form-prefix-cls}-item-label:not(.@{ant-prefix}-col-24) {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
float: left; // To revert `col-*`
|
||||
padding: 0;
|
||||
text-align: right;
|
||||
|
||||
label:after {
|
||||
content: ":";
|
||||
margin: 0 8px 0 2px;
|
||||
position: relative;
|
||||
top: -0.5px;
|
||||
}
|
||||
}
|
||||
.@{form-prefix-cls}-item-no-colon .@{form-prefix-cls}-item-label label:after {
|
||||
content: " ";
|
||||
}
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-text {
|
||||
display: inline-block;
|
||||
}
|
||||
//== Inline Form
|
||||
.@{form-prefix-cls}-inline {
|
||||
.@{form-prefix-cls}-item {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 0;
|
||||
|
||||
.has-feedback {
|
||||
display: inline-block;
|
||||
}
|
||||
&-with-help {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
// Fix https://github.comdesigndesign/issues/1040
|
||||
.@{form-prefix-cls}-explain {
|
||||
position: absolute;
|
||||
> div {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-text {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.has-feedback {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
// Fix https://github.comdesigndesign/issues/1040
|
||||
.@{form-prefix-cls}-explain {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -566,15 +566,15 @@ exports[`test renders ./components/grid/demo/reponsive.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-row">
|
||||
<div
|
||||
class="ant-col-xs-2 ant-col-sm-4 ant-col-md-6 ant-col-lg-8">
|
||||
class="ant-col-xs-2 ant-col-sm-4 ant-col-md-6 ant-col-lg-8 ant-col-xl-10">
|
||||
Col
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-xs-20 ant-col-sm-16 ant-col-md-12 ant-col-lg-8">
|
||||
class="ant-col-xs-20 ant-col-sm-16 ant-col-md-12 ant-col-lg-8 ant-col-xl-4">
|
||||
Col
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-xs-2 ant-col-sm-4 ant-col-md-6 ant-col-lg-8">
|
||||
class="ant-col-xs-2 ant-col-sm-4 ant-col-md-6 ant-col-lg-8 ant-col-xl-10">
|
||||
Col
|
||||
</div>
|
||||
</div>
|
||||
|
@ -25,6 +25,7 @@ export interface ColProps {
|
||||
sm?: number | ColSize;
|
||||
md?: number | ColSize;
|
||||
lg?: number | ColSize;
|
||||
xl?: number | ColSize;
|
||||
prefixCls?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
@ -42,13 +43,14 @@ export default class Col extends React.Component<ColProps, any> {
|
||||
sm: objectOrNumber,
|
||||
md: objectOrNumber,
|
||||
lg: objectOrNumber,
|
||||
xl: objectOrNumber,
|
||||
};
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const { span, order, offset, push, pull, className, children, prefixCls = 'ant-col', ...others } = props;
|
||||
let sizeClassObj = {};
|
||||
['xs', 'sm', 'md', 'lg'].forEach(size => {
|
||||
['xs', 'sm', 'md', 'lg', 'xl'].forEach(size => {
|
||||
let sizeProps: ColSize = {};
|
||||
if (typeof props[size] === 'number') {
|
||||
sizeProps.span = props[size];
|
||||
|
@ -7,13 +7,13 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
`span` `pull` `push` `offset` `order` 属性可以通过内嵌到 `xs` `sm` `md` `lg` 属性中来使用。
|
||||
`span` `pull` `push` `offset` `order` 属性可以通过内嵌到 `xs` `sm` `md` `lg` `xl` 属性中来使用。
|
||||
|
||||
其中 `xs={6}` 相当于 `xs={{ span: 6 }}`。
|
||||
|
||||
## en-US
|
||||
|
||||
`Span` `pull` `push` `offset` `order` property can be embedded into `xs` `sm` `md` `lg` properties to use,
|
||||
`Span` `pull` `push` `offset` `order` property can be embedded into `xs` `sm` `md` `lg` `xl` properties to use,
|
||||
where `xs = {6}` is equivalent to `xs = {{span: 6}}`.
|
||||
|
||||
````jsx
|
||||
|
@ -7,20 +7,20 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
参照 Bootstrap 的 [响应式设计](http://getbootstrap.com/css/#grid-media-queries),预设四个响应尺寸:`xs` `sm` `md` `lg`。
|
||||
参照 Bootstrap 的 [响应式设计](http://getbootstrap.com/css/#grid-media-queries),预设五个响应尺寸:`xs` `sm` `md` `lg` `xl`。
|
||||
|
||||
## en-US
|
||||
|
||||
Referring to the Bootstrap [responsive design] (http://getbootstrap.com/css/#grid-media-queries), here preset four dimensions: `xs` `sm` `md` `lg`.
|
||||
Referring to the Bootstrap [responsive design] (http://getbootstrap.com/css/#grid-media-queries), here preset five dimensions: `xs` `sm` `md` `lg` `xl`.
|
||||
|
||||
````jsx
|
||||
import { Row, Col } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Row>
|
||||
<Col xs={2} sm={4} md={6} lg={8}>Col</Col>
|
||||
<Col xs={20} sm={16} md={12} lg={8}>Col</Col>
|
||||
<Col xs={2} sm={4} md={6} lg={8}>Col</Col>
|
||||
<Col xs={2} sm={4} md={6} lg={8} xl={10}>Col</Col>
|
||||
<Col xs={20} sm={16} md={12} lg={8} xl={4}>Col</Col>
|
||||
<Col xs={2} sm={4} md={6} lg={8} xl={10}>Col</Col>
|
||||
</Row>
|
||||
, mountNode);
|
||||
````
|
||||
|
@ -108,5 +108,6 @@ Ant Design layout component if it can not meet your needs, you can use the excel
|
||||
| sm | `≥768px`, could be a `span` value or a object contain above props | number\|object | - |
|
||||
| md | `≥992px`, could be a `span` value or a object contain above props | number\|object | - |
|
||||
| lg | `≥1200px`, could be a `span` value or a object contain above props | number\|object | - |
|
||||
| xl | `≥1600px`, could be a `span` value or a object contain above props | number\|object | - |
|
||||
|
||||
The breakpoints of responsive grid follow [BootStrap 3 media queries rules](http://getbootstrap.com/css/#grid-media-queries)(not contain `occasionally part`).
|
||||
|
@ -107,5 +107,6 @@ Ant Design 的布局组件若不能满足你的需求,你也可以直接使用
|
||||
| sm | `≥768px` 响应式栅格,可为栅格数或一个包含其他属性的对象 | number\|object | - |
|
||||
| md | `≥992px` 响应式栅格,可为栅格数或一个包含其他属性的对象 | number\|object | - |
|
||||
| lg | `≥1200px` 响应式栅格,可为栅格数或一个包含其他属性的对象 | number\|object | - |
|
||||
| xl | `≥1600px` 响应式栅格,可为栅格数或一个包含其他属性的对象 | number\|object | - |
|
||||
|
||||
响应式栅格的断点遵循了 [BootStrap 3 的规则](http://getbootstrap.com/css/#grid-media-queries)(不包含链接里 `occasionally` 的部分)。
|
||||
|
@ -98,3 +98,11 @@
|
||||
@media (min-width: @screen-lg-min) {
|
||||
.make-grid(-lg);
|
||||
}
|
||||
|
||||
// Extra Large grid
|
||||
//
|
||||
// Columns, offsets, pushes, and pulls for the full hd device range.
|
||||
|
||||
@media (min-width: @screen-xl-min) {
|
||||
.make-grid(-xl);
|
||||
}
|
||||
|
@ -51,13 +51,20 @@ import IconSet from 'site/theme/template/IconSet';
|
||||
ReactDOM.render(<IconSet className="icons" catigory="suggestion" />, mountNode);
|
||||
```
|
||||
|
||||
### Other Icons
|
||||
### Application Icons
|
||||
|
||||
```__react
|
||||
import IconSet from 'site/theme/template/IconSet';
|
||||
ReactDOM.render(<IconSet className="icons" catigory="other" />, mountNode);
|
||||
```
|
||||
|
||||
### Brand and Logos
|
||||
|
||||
```__react
|
||||
import IconSet from 'site/theme/template/IconSet';
|
||||
ReactDOM.render(<IconSet className="icons" catigory="logo" />, mountNode);
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|
@ -59,6 +59,13 @@ import IconSet from 'site/theme/template/IconSet';
|
||||
ReactDOM.render(<IconSet className="icons" catigory="other" />, mountNode);
|
||||
```
|
||||
|
||||
### 品牌和标识
|
||||
|
||||
```__react
|
||||
import IconSet from 'site/theme/template/IconSet';
|
||||
ReactDOM.render(<IconSet className="icons" catigory="logo" />, mountNode);
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|
@ -1,8 +1,32 @@
|
||||
// matchMedia polyfill for
|
||||
// https://github.com/WickyNilliams/enquire.js/issues/82
|
||||
if (typeof window !== 'undefined') {
|
||||
const matchMediaPolyfill = function matchMediaPolyfill(mediaQuery: string): MediaQueryList {
|
||||
return {
|
||||
media: mediaQuery,
|
||||
matches: false,
|
||||
addListener() {
|
||||
},
|
||||
removeListener() {
|
||||
},
|
||||
};
|
||||
};
|
||||
window.matchMedia = window.matchMedia || matchMediaPolyfill;
|
||||
}
|
||||
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import Icon from '../icon';
|
||||
|
||||
const dimensionMap = {
|
||||
xs: '480px',
|
||||
sm: '768px',
|
||||
md: '992px',
|
||||
lg: '1200px',
|
||||
xl: '1600px',
|
||||
};
|
||||
|
||||
export interface SiderProps {
|
||||
style?: React.CSSProperties;
|
||||
prefixCls?: string;
|
||||
@ -11,13 +35,15 @@ export interface SiderProps {
|
||||
collapsed?: boolean;
|
||||
defaultCollapsed?: boolean;
|
||||
reverseArrow?: boolean;
|
||||
onCollapse?: (collapsed: boolean) => void;
|
||||
onCollapse?: (collapsed: boolean, type: 'clickTrigger' | 'responsive') => void;
|
||||
trigger?: React.ReactNode;
|
||||
width?: number | string;
|
||||
collapsedWidth?: number;
|
||||
collapsedWidth?: number | string;
|
||||
breakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
}
|
||||
|
||||
export default class Sider extends React.Component<SiderProps, any> {
|
||||
static __ANT_LAYOUT_SIDER: any = true;
|
||||
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-layout-sider',
|
||||
@ -27,11 +53,19 @@ export default class Sider extends React.Component<SiderProps, any> {
|
||||
width: 200,
|
||||
collapsedWidth: 64,
|
||||
style: {},
|
||||
name: 'Sider',
|
||||
};
|
||||
|
||||
private mql: any;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
let matchMedia;
|
||||
if (typeof window !== 'undefined') {
|
||||
matchMedia = window.matchMedia;
|
||||
}
|
||||
if (matchMedia && props.breakpoint && props.breakpoint in dimensionMap) {
|
||||
this.mql = matchMedia(`(max-width: ${dimensionMap[props.breakpoint]})`);
|
||||
}
|
||||
let collapsed;
|
||||
if ('collapsed' in props) {
|
||||
collapsed = props.collapsed;
|
||||
@ -40,6 +74,7 @@ export default class Sider extends React.Component<SiderProps, any> {
|
||||
}
|
||||
this.state = {
|
||||
collapsed,
|
||||
below: false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -51,7 +86,27 @@ export default class Sider extends React.Component<SiderProps, any> {
|
||||
}
|
||||
}
|
||||
|
||||
setCollapsed = (collapsed) => {
|
||||
componentDidMount() {
|
||||
if (this.mql) {
|
||||
this.mql.addListener(this.responsiveHandler);
|
||||
this.responsiveHandler(this.mql);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.mql) {
|
||||
this.mql.removeListener(this.responsiveHandler);
|
||||
}
|
||||
}
|
||||
|
||||
responsiveHandler = (mql) => {
|
||||
this.setState({ below: mql.matches });
|
||||
if (this.state.collapsed !== mql.matches) {
|
||||
this.setCollapsed(mql.matches, 'responsive');
|
||||
}
|
||||
}
|
||||
|
||||
setCollapsed = (collapsed, type) => {
|
||||
if (!('collapsed' in this.props)) {
|
||||
this.setState({
|
||||
collapsed,
|
||||
@ -59,30 +114,32 @@ export default class Sider extends React.Component<SiderProps, any> {
|
||||
}
|
||||
const { onCollapse } = this.props;
|
||||
if (onCollapse) {
|
||||
onCollapse(collapsed);
|
||||
onCollapse(collapsed, type);
|
||||
}
|
||||
}
|
||||
|
||||
toggle = () => {
|
||||
const collapsed = !this.state.collapsed;
|
||||
this.setCollapsed(collapsed);
|
||||
this.setCollapsed(collapsed, 'clickTrigger');
|
||||
}
|
||||
|
||||
belowShowChange = () => {
|
||||
this.setState({ belowShow: !this.state.belowShow });
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
prefixCls, className, collapsible, reverseArrow, trigger, style, width, collapsedWidth,
|
||||
const { prefixCls, className,
|
||||
collapsible, reverseArrow, trigger, style, width, collapsedWidth,
|
||||
...others,
|
||||
} = this.props;
|
||||
const divProps = omit(others, ['collapsed', 'defaultCollapsed', 'onCollapse', 'name']);
|
||||
const siderCls = classNames(className, prefixCls, {
|
||||
[`${prefixCls}-collapsed`]: !!this.state.collapsed,
|
||||
[`${prefixCls}-has-trigger`]: !!trigger,
|
||||
});
|
||||
const divStyle = {
|
||||
...style,
|
||||
flex: `0 0 ${this.state.collapsed ? collapsedWidth : width}px`,
|
||||
width: `${this.state.collapsed ? collapsedWidth : width}px`,
|
||||
};
|
||||
const divProps = omit(others, ['collapsed',
|
||||
'defaultCollapsed', 'onCollapse', 'breakpoint']);
|
||||
const siderWidth = this.state.collapsed ? collapsedWidth : width;
|
||||
// special trigger when collapsedWidth == 0
|
||||
const zeroWidthTrigger = collapsedWidth === 0 || collapsedWidth === '0' ?
|
||||
(<span onClick={this.toggle} className={`${prefixCls}-zero-width-trigger`}>
|
||||
<Icon type="bars" />
|
||||
</span>) : null;
|
||||
const iconObj = {
|
||||
'expanded': reverseArrow ? <Icon type="right" /> : <Icon type="left" />,
|
||||
'collapsed': reverseArrow ? <Icon type="left" /> : <Icon type="right" />,
|
||||
@ -91,15 +148,27 @@ export default class Sider extends React.Component<SiderProps, any> {
|
||||
const defaultTrigger = iconObj[status];
|
||||
const triggerDom = (
|
||||
trigger !== null ?
|
||||
zeroWidthTrigger ||
|
||||
(<div className={`${prefixCls}-trigger`} onClick={this.toggle}>
|
||||
{trigger || defaultTrigger}
|
||||
</div>)
|
||||
: null
|
||||
);
|
||||
const divStyle = {
|
||||
...style,
|
||||
flex: `0 0 ${siderWidth}px`,
|
||||
width: `${siderWidth}px`,
|
||||
};
|
||||
const siderCls = classNames(className, prefixCls, {
|
||||
[`${prefixCls}-collapsed`]: !!this.state.collapsed,
|
||||
[`${prefixCls}-has-trigger`]: !!trigger,
|
||||
[`${prefixCls}-below`]: !!this.state.below,
|
||||
[`${prefixCls}-zero-width`]: siderWidth === 0 || siderWidth === '0',
|
||||
});
|
||||
return (
|
||||
<div className={siderCls} {...divProps} style={divStyle}>
|
||||
{this.props.children}
|
||||
{collapsible && triggerDom}
|
||||
{collapsible || (this.state.below && zeroWidthTrigger) ? triggerDom : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -155,6 +155,173 @@ exports[`test renders ./components/layout/demo/custom-trigger.md correctly 1`] =
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`test renders ./components/layout/demo/fixed.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-layout">
|
||||
<div
|
||||
class="header ant-layout-header">
|
||||
<div
|
||||
class="logo" />
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-horizontal ant-menu-dark ant-menu-root"
|
||||
role="menu"
|
||||
style="line-height:64px;"
|
||||
tabindex="0">
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem">
|
||||
nav 1
|
||||
</li>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item-selected ant-menu-item"
|
||||
role="menuitem">
|
||||
nav 2
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem">
|
||||
nav 3
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="content ant-layout-content">
|
||||
<div
|
||||
class="ant-breadcrumb"
|
||||
style="margin:12px 0;">
|
||||
<span>
|
||||
<span
|
||||
class="ant-breadcrumb-link">
|
||||
Home
|
||||
</span>
|
||||
<span
|
||||
class="ant-breadcrumb-separator">
|
||||
/
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span
|
||||
class="ant-breadcrumb-link">
|
||||
List
|
||||
</span>
|
||||
<span
|
||||
class="ant-breadcrumb-separator">
|
||||
/
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span
|
||||
class="ant-breadcrumb-link">
|
||||
App
|
||||
</span>
|
||||
<span
|
||||
class="ant-breadcrumb-separator">
|
||||
/
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
style="background:#fff;padding:24px;min-height:280px;">
|
||||
Content
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-layout-footer"
|
||||
style="text-align:center;">
|
||||
Ant Design ©2016 Created by Ant UED
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`test renders ./components/layout/demo/responsive.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-layout ant-layout-has-sider">
|
||||
<div
|
||||
class="ant-layout-sider"
|
||||
style="flex:0 0 200px;width:200px;">
|
||||
<div
|
||||
class="logo" />
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-inline ant-menu-dark ant-menu-root"
|
||||
role="menu"
|
||||
tabindex="0">
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px;">
|
||||
<i
|
||||
class="anticon anticon-user" />
|
||||
<span
|
||||
class="nav-text">
|
||||
nav 1
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px;">
|
||||
<i
|
||||
class="anticon anticon-video-camera" />
|
||||
<span
|
||||
class="nav-text">
|
||||
nav 2
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px;">
|
||||
<i
|
||||
class="anticon anticon-upload" />
|
||||
<span
|
||||
class="nav-text">
|
||||
nav 3
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item-selected ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px;">
|
||||
<i
|
||||
class="anticon anticon-user" />
|
||||
<span
|
||||
class="nav-text">
|
||||
nav 4
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="ant-layout">
|
||||
<div
|
||||
class="ant-layout-header"
|
||||
style="background:#fff;padding:0;" />
|
||||
<div
|
||||
class="ant-layout-content"
|
||||
style="margin:24px 16px 0;">
|
||||
<div
|
||||
style="padding:24px;background:#fff;min-height:360px;">
|
||||
content
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-layout-footer"
|
||||
style="text-align:center;">
|
||||
Ant Design ©2016 Created by Ant UED
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`test renders ./components/layout/demo/side.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-layout ant-layout-has-sider">
|
||||
|
71
components/layout/demo/responsive.md
Normal file
71
components/layout/demo/responsive.md
Normal file
@ -0,0 +1,71 @@
|
||||
---
|
||||
order: 5
|
||||
title:
|
||||
zh-CN: 响应式布局
|
||||
en-US: Responsive
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
Layout.Sider 支持响应式布局。
|
||||
|
||||
> 说明:配置 `breakpoint` 属性即生效,视窗宽度小于 `breakpoint` 时 Sider 缩小为 `collapsedWidth` 宽度,若将 `collapsedWidth` 设置为零,会出现特殊 trigger。
|
||||
|
||||
## en-US
|
||||
|
||||
Layout.Sider supports responsive layout.
|
||||
|
||||
> Note: You can get a responsive layout by setting `breakpoint`, the Sider will collapse to the width of `collapsedWidth` when window width is below the `breakpoint`. And a special trigger will appear if the `collapsedWidth` is set to `0`.
|
||||
|
||||
````jsx
|
||||
import { Layout, Menu, Icon } from 'antd';
|
||||
const { Header, Content, Footer, Sider } = Layout;
|
||||
|
||||
ReactDOM.render(<Layout>
|
||||
<Sider
|
||||
breakpoint="lg"
|
||||
collapsedWidth="0"
|
||||
onCollapse={(collapsed, type) => { console.log(collapsed, type); }}
|
||||
>
|
||||
<div className="logo" />
|
||||
<Menu theme="dark" mode="inline" defaultSelectedKeys={['4']}>
|
||||
<Menu.Item key="1">
|
||||
<Icon type="user" />
|
||||
<span className="nav-text">nav 1</span>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2">
|
||||
<Icon type="video-camera" />
|
||||
<span className="nav-text">nav 2</span>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3">
|
||||
<Icon type="upload" />
|
||||
<span className="nav-text">nav 3</span>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="4">
|
||||
<Icon type="user" />
|
||||
<span className="nav-text">nav 4</span>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</Sider>
|
||||
<Layout>
|
||||
<Header style={{ background: '#fff', padding: 0 }} />
|
||||
<Content style={{ margin: '24px 16px 0' }}>
|
||||
<div style={{ padding: 24, background: '#fff', minHeight: 360 }}>
|
||||
content
|
||||
</div>
|
||||
</Content>
|
||||
<Footer style={{ textAlign: 'center' }}>
|
||||
Ant Design ©2016 Created by Ant UED
|
||||
</Footer>
|
||||
</Layout>
|
||||
</Layout>, mountNode);
|
||||
````
|
||||
|
||||
````css
|
||||
#components-layout-demo-responsive .logo {
|
||||
height: 32px;
|
||||
background: #333;
|
||||
border-radius: 6px;
|
||||
margin: 16px;
|
||||
}
|
||||
````
|
@ -51,9 +51,19 @@ Property | Description | Type | Default
|
||||
collapsible | whether can be collapsed | boolean | false
|
||||
defaultCollapsed | to set the initial status | boolean | false |
|
||||
collapsed | to set the current status | boolean | -
|
||||
onCollapse | the callback function, can be executed when you switch the sidebar, available only `collapsible: true` | (collapsed) => {} | -
|
||||
onCollapse | the callback function, can be executed by clicking the trigger or activating the responsive layout | (collapsed, type) => {} | -
|
||||
trigger | specify the customized trigger, set to null to hide the trigger | string\|ReactNode| - |
|
||||
width | width of the sidebar | number\|string | 200
|
||||
collapsedWidth | width of the collapsed sidebar, available only `collapsible: true` | number | 64
|
||||
collapsedWidth | width of the collapsed sidebar, by setting to `0` a special trigger will appear | number | 64
|
||||
breakpoint | breakpoint of the responsive layout | Enum { 'xs', 'sm', 'md', 'lg', 'xl' } | - |
|
||||
style | to custom the styles | object | -
|
||||
className | container className | string | -
|
||||
|
||||
> Note: If you want to wrap the `Sider`, do not forget to add this setting to the customized component: `__ANT_LAYOUT_SIDER = true`. e.g.
|
||||
|
||||
```jsx
|
||||
const CustomizedSider = (props) => <Sider {...props} />
|
||||
CustomizedSider.__ANT_LAYOUT_SIDER = true;
|
||||
...
|
||||
<CustomizedSider>Sider Content</CustomizedSider>
|
||||
```
|
||||
|
@ -52,9 +52,19 @@ title: Layout
|
||||
| collapsible | 是否可收起 | boolean | false |
|
||||
| defaultCollapsed | 是否默认收起 | boolean | false |
|
||||
| collapsed | 当前收起状态 | boolean | - |
|
||||
| onCollapse | 展开-收起时的回调函数,仅当 `collapsible:true` 时生效 | (collapsed) => {} | - |
|
||||
| onCollapse | 展开-收起时的回调函数,有点击 trigger 以及响应式反馈两种方式可以触发 | (collapsed, type) => {} | - |
|
||||
| trigger | 自定义 trigger,设置为 null 时隐藏 trigger | string\|ReactNode | - |
|
||||
| width | 宽度 | number\|string | 200 |
|
||||
| collapsedWidth | 收缩宽度,仅当 `collapsible:true` 时生效 | number | 64 |
|
||||
| collapsedWidth | 收缩宽度,设置为 0 会出现特殊 trigger | number | 64 |
|
||||
| breakpoint | 触发响应式布局的断点 | Enum { 'xs', 'sm', 'md', 'lg', 'xl' } | - |
|
||||
| style | 指定样式 | object | - |
|
||||
| className | 容器 className | string | - |
|
||||
|
||||
> 注意:如果你想在 `Sider` 基础上进行包装,需要给自定义组件加上 `__ANT_LAYOUT_SIDER = true` 设置,例如:
|
||||
|
||||
```jsx
|
||||
const CustomizedSider = (props) => <Sider {...props} />
|
||||
CustomizedSider.__ANT_LAYOUT_SIDER = true;
|
||||
...
|
||||
<CustomizedSider>Sider Content</CustomizedSider>
|
||||
```
|
||||
|
@ -5,7 +5,6 @@ export interface BasicProps {
|
||||
style?: React.CSSProperties;
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
function generator(props) {
|
||||
@ -17,7 +16,7 @@ function generator(props) {
|
||||
static Sider: any;
|
||||
render() {
|
||||
const { prefixCls } = props;
|
||||
return <Basic prefixCls={prefixCls} name={props.name} {...this.props}/>;
|
||||
return <Basic prefixCls={prefixCls} {...this.props}/>;
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -25,15 +24,13 @@ function generator(props) {
|
||||
|
||||
class Basic extends React.Component<BasicProps, any> {
|
||||
render() {
|
||||
const { prefixCls, className, children, name, ...others } = this.props;
|
||||
const { prefixCls, className, children, ...others } = this.props;
|
||||
let hasSider;
|
||||
if (name === 'Layout') {
|
||||
React.Children.forEach(children, (ele: React.ReactElement<any>) => {
|
||||
if (ele && ele.props && ele.props.name === 'Sider') {
|
||||
hasSider = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
React.Children.forEach(children, (element: any) => {
|
||||
if (element && element.type && element.type.__ANT_LAYOUT_SIDER) {
|
||||
hasSider = true;
|
||||
}
|
||||
});
|
||||
const divCls = classNames(className, prefixCls, {
|
||||
[`${prefixCls}-has-sider`]: hasSider,
|
||||
});
|
||||
@ -45,22 +42,18 @@ class Basic extends React.Component<BasicProps, any> {
|
||||
|
||||
const Layout = generator({
|
||||
prefixCls: 'ant-layout',
|
||||
name: 'Layout',
|
||||
})(Basic);
|
||||
|
||||
const Header = generator({
|
||||
prefixCls: 'ant-layout-header',
|
||||
name: 'Header',
|
||||
})(Basic);
|
||||
|
||||
const Footer = generator({
|
||||
prefixCls: 'ant-layout-footer',
|
||||
name: 'Footer',
|
||||
})(Basic);
|
||||
|
||||
const Content = generator({
|
||||
prefixCls: 'ant-layout-content',
|
||||
name: 'Content',
|
||||
})(Basic);
|
||||
|
||||
Layout.Header = Header;
|
||||
|
@ -60,5 +60,31 @@
|
||||
background: tint(@heading-color, 20%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&-zero-width {
|
||||
& > * {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&-trigger {
|
||||
position: absolute;
|
||||
top: @layout-header-height;
|
||||
right: -@layout-zero-trigger-width;
|
||||
text-align: center;
|
||||
width: @layout-zero-trigger-width;
|
||||
height: @layout-zero-trigger-height;
|
||||
line-height: @layout-zero-trigger-height;
|
||||
background: @layout-sider-background;
|
||||
color: #fff;
|
||||
font-size: @layout-zero-trigger-width / 2;
|
||||
border-radius: 0 @border-radius-base @border-radius-base 0;
|
||||
cursor: pointer;
|
||||
transition: background .3s ease;
|
||||
|
||||
&:hover {
|
||||
background: tint(@layout-sider-background, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,10 @@ import esES from '../es_ES';
|
||||
import svSE from '../sv_SE';
|
||||
import frBE from '../fr_BE';
|
||||
import deDE from '../de_DE';
|
||||
import nlNL from '../nl_NL';
|
||||
import caES from '../ca_ES';
|
||||
import csCZ from '../cs_CZ';
|
||||
import koKR from '../ko_KR';
|
||||
|
||||
const Option = Select.Option;
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
@ -55,7 +59,7 @@ const App = () => (
|
||||
|
||||
describe('Locale Provider', () => {
|
||||
it('should display the text as locale changed', () => {
|
||||
[enUS, ptBR, ruRU, esES, svSE, frBE, deDE].forEach((locale) => {
|
||||
[enUS, ptBR, ruRU, esES, svSE, frBE, deDE, nlNL, caES, csCZ, koKR].forEach((locale) => {
|
||||
const wrapper = mount(
|
||||
<LocaleProvider locale={locale}>
|
||||
<App />
|
||||
|
39
components/locale-provider/ca_ES.tsx
Normal file
39
components/locale-provider/ca_ES.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import moment from 'moment';
|
||||
moment.locale('ca');
|
||||
|
||||
import Pagination from 'rc-pagination/lib/locale/ca_ES';
|
||||
import DatePicker from '../date-picker/locale/ca_ES';
|
||||
import TimePicker from '../time-picker/locale/ca_ES';
|
||||
import Calendar from '../calendar/locale/ca_ES';
|
||||
|
||||
export default {
|
||||
locale: 'ca',
|
||||
Pagination,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Calendar,
|
||||
Table: {
|
||||
filterTitle: 'Filtrar Menu',
|
||||
filterConfirm: 'OK',
|
||||
filterReset: 'Restablir',
|
||||
emptyText: 'Sense dades',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'OK',
|
||||
cancelText: 'Cancel·lar',
|
||||
justOkText: 'OK',
|
||||
},
|
||||
Popconfirm: {
|
||||
okText: 'OK',
|
||||
cancelText: 'Cancel·lar',
|
||||
},
|
||||
Transfer: {
|
||||
notFoundContent: 'No trobat',
|
||||
searchPlaceholder: 'Cercar aquí',
|
||||
itemUnit: 'item',
|
||||
itemsUnit: 'items',
|
||||
},
|
||||
Select: {
|
||||
notFoundContent: 'No trobat',
|
||||
},
|
||||
};
|
45
components/locale-provider/cs_CZ.tsx
Normal file
45
components/locale-provider/cs_CZ.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import moment from 'moment';
|
||||
moment.locale('cs');
|
||||
|
||||
import Pagination from 'rc-pagination/lib/locale/cs_CZ';
|
||||
import DatePicker from '../date-picker/locale/cs_CZ';
|
||||
import TimePicker from '../time-picker/locale/cs_CZ';
|
||||
import Calendar from '../calendar/locale/cs_CZ';
|
||||
|
||||
export default {
|
||||
locale: 'cs',
|
||||
Pagination,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Calendar,
|
||||
Table: {
|
||||
filterTitle: 'Filtr',
|
||||
filterConfirm: 'Potvrdit',
|
||||
filterReset: 'Obnovit',
|
||||
emptyText: 'Žádná data',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'Ok',
|
||||
cancelText: 'Storno',
|
||||
justOkText: 'Ok',
|
||||
},
|
||||
Popconfirm: {
|
||||
okText: 'Ok',
|
||||
cancelText: 'Storno',
|
||||
},
|
||||
Transfer: {
|
||||
notFoundContent: 'Nenalezeno',
|
||||
searchPlaceholder: 'Vyhledávání',
|
||||
itemUnit: 'položka',
|
||||
itemsUnit: 'položek',
|
||||
},
|
||||
Select: {
|
||||
notFoundContent: 'Nenalezeno',
|
||||
},
|
||||
Upload: {
|
||||
uploading: 'Nahrávání...',
|
||||
removeFile: 'Odstranit soubor',
|
||||
uploadError: 'Chyba při nahrávání',
|
||||
previewFile: 'Zobrazit soubor',
|
||||
},
|
||||
};
|
@ -36,4 +36,10 @@ export default {
|
||||
Select: {
|
||||
notFoundContent: 'Not Found',
|
||||
},
|
||||
Upload: {
|
||||
uploading: 'Uploading...',
|
||||
removeFile: 'Remove file',
|
||||
uploadError: 'Upload error',
|
||||
previewFile: 'Preview file',
|
||||
},
|
||||
};
|
||||
|
45
components/locale-provider/ko_KR.tsx
Normal file
45
components/locale-provider/ko_KR.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import moment from 'moment';
|
||||
moment.locale('ko');
|
||||
|
||||
import Pagination from 'rc-pagination/lib/locale/ko_KR';
|
||||
import DatePicker from '../date-picker/locale/ko_KR';
|
||||
import TimePicker from '../time-picker/locale/ko_KR';
|
||||
import Calendar from '../calendar/locale/ko_KR';
|
||||
|
||||
export default {
|
||||
locale: 'ko',
|
||||
Pagination,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Calendar,
|
||||
Table: {
|
||||
filterTitle: '필터 메뉴',
|
||||
filterConfirm: '확인',
|
||||
filterReset: '초기화',
|
||||
emptyText: '데이터 없음',
|
||||
},
|
||||
Modal: {
|
||||
okText: '확인',
|
||||
cancelText: '취소',
|
||||
justOkText: '확인',
|
||||
},
|
||||
Popconfirm: {
|
||||
okText: '확인',
|
||||
cancelText: '취소',
|
||||
},
|
||||
Transfer: {
|
||||
notFoundContent: '데이터 없음',
|
||||
searchPlaceholder: '여기에 검색하세요',
|
||||
itemUnit: '개',
|
||||
itemsUnit: '개',
|
||||
},
|
||||
Select: {
|
||||
notFoundContent: '데이터 없음',
|
||||
},
|
||||
Upload: {
|
||||
uploading: '업로드 중...',
|
||||
removeFile: '파일 삭제',
|
||||
uploadError: '업로드 실패',
|
||||
previewFile: '파일 미리보기',
|
||||
},
|
||||
};
|
39
components/locale-provider/nl_NL.tsx
Normal file
39
components/locale-provider/nl_NL.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import moment from 'moment';
|
||||
moment.locale('nl');
|
||||
|
||||
import Pagination from 'rc-pagination/lib/locale/nl_NL';
|
||||
import DatePicker from '../date-picker/locale/nl_NL';
|
||||
import TimePicker from '../time-picker/locale/nl_NL';
|
||||
import Calendar from '../calendar/locale/nl_NL';
|
||||
|
||||
export default {
|
||||
locale: 'nl',
|
||||
Pagination,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Calendar,
|
||||
Table: {
|
||||
filterTitle: 'Filter Menu',
|
||||
filterConfirm: 'OK',
|
||||
filterReset: 'Reset',
|
||||
emptyText: 'Geen gegevens',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'OK',
|
||||
cancelText: 'Annuleren',
|
||||
justOkText: 'OK',
|
||||
},
|
||||
Popconfirm: {
|
||||
okText: 'OK',
|
||||
cancelText: 'Annuleren',
|
||||
},
|
||||
Transfer: {
|
||||
notFoundContent: 'Niet gevonden',
|
||||
searchPlaceholder: 'Zoeken',
|
||||
itemUnit: 'item',
|
||||
itemsUnit: 'items',
|
||||
},
|
||||
Select: {
|
||||
notFoundContent: 'Niet gevonden',
|
||||
},
|
||||
};
|
63
components/mention/demo/multiple-trigger.md
Normal file
63
components/mention/demo/multiple-trigger.md
Normal file
@ -0,0 +1,63 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 自定义触发字符
|
||||
en-US: Customize Trigger Token
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
通过 `prefix` 属性自定义触发字符。默认为 `@`, 可以定义为数组。
|
||||
|
||||
## en-US
|
||||
|
||||
Customize Trigger Token by `prefix` props. Default to `@`, `Array<string>` also supported.
|
||||
|
||||
````jsx
|
||||
import { Mention } from 'antd';
|
||||
const { toString } = Mention;
|
||||
|
||||
function onChange(editorState) {
|
||||
console.log(toString(editorState));
|
||||
}
|
||||
|
||||
function onSelect(suggestion) {
|
||||
console.log('onSelect', suggestion);
|
||||
}
|
||||
|
||||
const users = ['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai'];
|
||||
const tags = ['1.0', '2.0', '3.0'];
|
||||
|
||||
class App extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
suggestions: [],
|
||||
};
|
||||
}
|
||||
onSearchChange = (value, trigger) => {
|
||||
console.log('onSearchChange', value, trigger);
|
||||
const dataSource = trigger === '@' ? users : tags;
|
||||
this.setState({
|
||||
suggestions: dataSource.filter(item => item.indexOf(value) !== -1),
|
||||
});
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Mention
|
||||
style={{ width: '100%', height: 100 }}
|
||||
onChange={onChange}
|
||||
placeholder="input @ to mention people, # to mention tag"
|
||||
prefix={['@', '#']}
|
||||
onSearchChange={this.onSearchChange}
|
||||
suggestions={this.state.suggestions}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<App />
|
||||
, mountNode);
|
||||
````
|
@ -34,13 +34,13 @@ When need to mention someone or something.
|
||||
|----------|---------------|----------|--------------|
|
||||
| suggestions | suggestion content | Array<string\|Mention.Nav> | [] |
|
||||
| suggestionStyle | style of suggestion container | object | {} |
|
||||
| onSearchChange | Callback function called when search content changes | function(value:string) | [] |
|
||||
| onSearchChange | Callback function called when search content changes | function(value:string, trigger: string) | [] |
|
||||
| onChange | Callback function called when content of input changes | function(editorState: EditorState) | null |
|
||||
| onSelect | Callback function called when select from suggestions | function(suggestion: string, data?: any) | null |
|
||||
| notFoundContent| suggestion when suggestions empty | string | '无匹配结果,轻敲空格完成输入' |
|
||||
| loading | loading mode | boolean | false |
|
||||
| multiLines | multilines mode | boolean | false |
|
||||
| prefix | character which will trigger Mention to show mention list | string | '@' |
|
||||
| prefix | character which will trigger Mention to show mention list | string or Array<string> | '@' |
|
||||
| defaultValue | default value | EditorState, you can use `Mention.toEditorState` to convert text to `EditorState` | null |
|
||||
| value | core state of mention | EditorState | null |
|
||||
| placeholder | placeholder of input | string | null |
|
||||
|
@ -56,9 +56,9 @@ export default class Mention extends React.Component<MentionProps, MentionState>
|
||||
}
|
||||
}
|
||||
|
||||
onSearchChange = (value) => {
|
||||
onSearchChange = (value, prefix) => {
|
||||
if (this.props.onSearchChange) {
|
||||
return this.props.onSearchChange(value);
|
||||
return this.props.onSearchChange(value, prefix);
|
||||
}
|
||||
return this.defaultSearchChange(value);
|
||||
}
|
||||
|
@ -34,13 +34,13 @@ title: Mention
|
||||
|----------|---------------|----------|--------------|
|
||||
| suggestions | 建议内容 | Array<string\|Mention.Nav> | [] |
|
||||
| suggestionStyle | 弹出下拉框样式 | object | {} |
|
||||
| onSearchChange | 输入框中 @ 变化时回调 | function(value:string) | [] |
|
||||
| onSearchChange | 输入框中 @ 变化时回调 | function(value:string, trigger: string) | [] |
|
||||
| onChange | 输入框内容变化时回调 | function(editorState: EditorState) | null |
|
||||
| onSelect | 下拉框选择建议时回调 | function(suggestion: string, data?: any) | null |
|
||||
| notFoundContent| 未找到时的内容 | string | '无匹配结果,轻敲空格完成输入' |
|
||||
| loading | 加载中 | boolean | false |
|
||||
| multiLines | 多行模式 | boolean | false |
|
||||
| prefix | 触发弹出下拉框的字符 | string | '@' |
|
||||
| prefix | 触发弹出下拉框的字符 | string or Array<string> | '@' |
|
||||
| placeholder | 输入框默认文字 | string | null |
|
||||
| defaultValue | 默认值 | EditorState, 可以用 Mention.toEditorState(text) 把文字转换成 EditorState | null |
|
||||
| value | 值 | EditorState | null |
|
||||
|
@ -28,6 +28,7 @@ This components provides 4 static methods, with arguments as following:
|
||||
| content | content of the message | string\|ReactNode | - |
|
||||
| duration | time before auto-dismiss,in seconds | number | 1.5 |
|
||||
| onClose | Specify a function that will be called after the message closed| Function | - |
|
||||
| getContainer | specify render container | () => HTMLElement | () => document.body |
|
||||
|
||||
Methods for global configuration and destruction are also provided:
|
||||
|
||||
|
@ -61,6 +61,7 @@ export interface ConfigOptions {
|
||||
top?: number;
|
||||
duration?: number;
|
||||
prefixCls?: string;
|
||||
getContainer?: () => HTMLElement;
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -29,7 +29,7 @@ title: Message
|
||||
| content | 提示内容 | string\|ReactNode | - |
|
||||
| duration | 自动关闭的延时,单位秒 | number | 1.5 |
|
||||
| onClose | 关闭时触发的回调函数 | Function | - |
|
||||
|
||||
| getContainer | 配置渲染节点的输出位置 | () => HTMLElement | () => document.body |
|
||||
|
||||
还提供了全局配置和全局销毁方法:
|
||||
|
||||
|
@ -38,7 +38,7 @@ The properties of config are as follows:
|
||||
| onClose | Specify a function that will be called after clicking the default close button | Function | - |
|
||||
| duration | A notification box is closed after 4.5s by default. When specifying `duration` to null or 0, it will never be closed automatically | number | 4.5 |
|
||||
| placement | To set the position, which can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight |
|
||||
|
||||
| getContainer | specify render container | () => HTMLNode | () => document.body |
|
||||
|
||||
`notification` also provide a global `config()` method that can be used for specifying the default options. Once this method is used, all the notification boxes
|
||||
will take into account these globally defined options before displaying.
|
||||
|
@ -53,6 +53,7 @@ export interface ArgsProps {
|
||||
duration?: number;
|
||||
icon?: React.ReactNode;
|
||||
placement?: notificationPlacement;
|
||||
getContainer?: () => HTMLElement;
|
||||
}
|
||||
|
||||
export interface ConfigProps {
|
||||
|
@ -38,6 +38,7 @@ config 参数如下:
|
||||
| onClose | 点击默认关闭按钮时触发的回调函数 | Function | - |
|
||||
| duration | 默认 4.5 秒后自动关闭,配置为 null 则不自动关闭 | number | 4.5 |
|
||||
| placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight |
|
||||
| getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body |
|
||||
|
||||
还提供了一个全局配置方法,在调用前提前配置,全局一次生效。
|
||||
|
||||
|
@ -1,92 +1,404 @@
|
||||
exports[`test renders ./components/rate/demo/basic.md correctly 1`] = `
|
||||
<ul
|
||||
class="ant-rate ">
|
||||
class="ant-rate">
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
exports[`test renders ./components/rate/demo/charactor.md correctly 1`] = `
|
||||
<div>
|
||||
<ul
|
||||
class="ant-rate">
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-heart" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-heart" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-heart" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-heart" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-heart" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-heart" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-heart" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-heart" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-heart" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-heart" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<br />
|
||||
<ul
|
||||
class="ant-rate"
|
||||
style="font-size:36px;">
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
A
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
A
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
A
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
A
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
A
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
A
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
A
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
A
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
A
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
A
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<br />
|
||||
<ul
|
||||
class="ant-rate">
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
好
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
好
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
好
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
好
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
好
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
好
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
好
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
好
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-first">
|
||||
好
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
好
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`test renders ./components/rate/demo/disabled.md correctly 1`] = `
|
||||
<ul
|
||||
class="ant-rate ant-rate-disabled">
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-full">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-full">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
exports[`test renders ./components/rate/demo/half.md correctly 1`] = `
|
||||
<ul
|
||||
class="ant-rate ">
|
||||
class="ant-rate">
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-full">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-full">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-half ant-rate-star-active">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
`;
|
||||
@ -94,31 +406,71 @@ exports[`test renders ./components/rate/demo/half.md correctly 1`] = `
|
||||
exports[`test renders ./components/rate/demo/text.md correctly 1`] = `
|
||||
<span>
|
||||
<ul
|
||||
class="ant-rate ">
|
||||
class="ant-rate">
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-full">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-full">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-full">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="ant-rate-star ant-rate-star-zero">
|
||||
<div
|
||||
class="ant-rate-star-content" />
|
||||
class="ant-rate-star-first">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
<div
|
||||
class="ant-rate-star-second">
|
||||
<i
|
||||
class="anticon anticon-star" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<span
|
||||
|
28
components/rate/demo/charactor.md
Normal file
28
components/rate/demo/charactor.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
order: 4
|
||||
title:
|
||||
zh-CN: 其他字符
|
||||
en-US: Other Charactor
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以将星星替换为其他字符,比如字母,数字,字体图标甚至中文。
|
||||
|
||||
## en-US
|
||||
|
||||
Replace the default star to other charactor like alphabet, digit, iconfont or even Chinese word.
|
||||
|
||||
````jsx
|
||||
import { Rate, Icon } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Rate charactor={<Icon type="heart" />} allowHalf />
|
||||
<br />
|
||||
<Rate charactor="A" allowHalf style={{ fontSize: 36 }} />
|
||||
<br />
|
||||
<Rate charactor="好" allowHalf />
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
@ -18,6 +18,10 @@ Rate component.
|
||||
| count | star count | number | 5 |
|
||||
| value | current value | number | - |
|
||||
| defaultValue | default value | number | 0 |
|
||||
| onChange | callback | Function(value: number) | - |
|
||||
| onChange | callback when select value | Function(value: number) | - |
|
||||
| onHoverChange | callback when hover item | Function(value: number) | - |
|
||||
| allowHalf | whether to allow semi selection | boolean | false |
|
||||
| disabled | read only, unable to interact | boolean | false |
|
||||
| charactor | custom charactor of rate | ReactNode | `<Icon type="star" />` |
|
||||
| className | custom class name of rate | string | - |
|
||||
| style | custom style object of rate | object | - |
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { PropTypes } from 'react';
|
||||
import RcRate from 'rc-rate';
|
||||
import Icon from '../icon';
|
||||
|
||||
export interface RateProps {
|
||||
prefixCls?: string;
|
||||
@ -10,14 +11,20 @@ export interface RateProps {
|
||||
allowHalf?: boolean;
|
||||
disabled?: boolean;
|
||||
onChange?: (value: number) => any;
|
||||
onHoverChange?: (value: number) => any;
|
||||
charactor?: React.ReactNode;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export default class Rate extends React.Component<RateProps, any> {
|
||||
static propTypes = {
|
||||
prefixCls: PropTypes.string,
|
||||
charactor: PropTypes.node,
|
||||
};
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-rate',
|
||||
charactor: <Icon type="star" />,
|
||||
};
|
||||
render() {
|
||||
return <RcRate {...this.props} />;
|
||||
|
@ -19,6 +19,10 @@ title: Rate
|
||||
| count | star 总数 | number | 5 |
|
||||
| value | 当前数,受控值 | number | - |
|
||||
| defaultValue | 默认值 | number | 0 |
|
||||
| onChange | 回调 | Function(value: number) | - |
|
||||
| onChange | 选择时的回调 | Function(value: number) | - |
|
||||
| onHoverChange | 鼠标经过时数值变化的回调 | Function(value: number) | - |
|
||||
| allowHalf | 是否允许半选 | boolean | false |
|
||||
| disabled | 只读,无法进行交互 | boolean | false |
|
||||
| charactor | 自定义字符 | ReactNode | `<Icon type="star" />` |
|
||||
| className | 自定义样式类名 | string | - |
|
||||
| style | 自定义样式对象 | object | - |
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
@rate-prefix-cls: ~"@{ant-prefix}-rate";
|
||||
@rate-star-color: #f5a623;
|
||||
@rate-star-bg: #e9e9e9;
|
||||
|
||||
.@{rate-prefix-cls} {
|
||||
margin: 0;
|
||||
@ -11,15 +12,9 @@
|
||||
font-size: 20px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
font-family: 'anticon';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
|
||||
&-disabled &-star {
|
||||
&:before,
|
||||
&-content:before {
|
||||
cursor: default;
|
||||
}
|
||||
cursor: not-allowed;
|
||||
&:hover {
|
||||
transform: scale(1);
|
||||
}
|
||||
@ -31,40 +26,42 @@
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
position: relative;
|
||||
transition: all 0.3s ease;
|
||||
transition: all .3s;
|
||||
color: @rate-star-bg;
|
||||
cursor: pointer;
|
||||
|
||||
&-first,
|
||||
&-second {
|
||||
user-select: none;
|
||||
transition: all .3s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
&:before,
|
||||
&-content:before {
|
||||
color: #e9e9e9;
|
||||
cursor: pointer;
|
||||
content: "\e660";
|
||||
transition: all 0.3s ease;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&-content {
|
||||
&-first {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
&:before {
|
||||
color: transparent;
|
||||
}
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&-half &-content:before,
|
||||
&-full:before {
|
||||
&-half &-first,
|
||||
&-half &-second {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&-half &-first,
|
||||
&-full &-second {
|
||||
color: @rate-star-color;
|
||||
}
|
||||
|
||||
&-half:hover &-content:before,
|
||||
&-full:hover:before {
|
||||
&-half:hover &-first,
|
||||
&-full:hover &-second {
|
||||
color: tint(@rate-star-color, 20%);
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +250,45 @@
|
||||
.@{iconfont-css-prefix}-rocket:before { content: "\e90f"; }
|
||||
.@{iconfont-css-prefix}-dingding:before { content: "\e923"; }
|
||||
.@{iconfont-css-prefix}-dingding-o:before { content: "\e925"; }
|
||||
|
||||
.@{iconfont-css-prefix}-bell:before { content: "\e64e"; }
|
||||
.@{iconfont-css-prefix}-disconnect:before { content: "\e64f"; }
|
||||
.@{iconfont-css-prefix}-database:before { content: "\e650"; }
|
||||
.@{iconfont-css-prefix}-compass:before { content: "\e6db"; }
|
||||
.@{iconfont-css-prefix}-barcode:before { content: "\e652"; }
|
||||
.@{iconfont-css-prefix}-hourglass:before { content: "\e653"; }
|
||||
.@{iconfont-css-prefix}-key:before { content: "\e654"; }
|
||||
.@{iconfont-css-prefix}-flag:before { content: "\e655"; }
|
||||
.@{iconfont-css-prefix}-layout:before { content: "\e656"; }
|
||||
.@{iconfont-css-prefix}-login:before { content: "\e657"; }
|
||||
.@{iconfont-css-prefix}-printer:before { content: "\e673"; }
|
||||
.@{iconfont-css-prefix}-sound:before { content: "\e6e9"; }
|
||||
.@{iconfont-css-prefix}-usb:before { content: "\e6d7"; }
|
||||
.@{iconfont-css-prefix}-skin:before { content: "\e6d8"; }
|
||||
.@{iconfont-css-prefix}-tool:before { content: "\e6d9"; }
|
||||
.@{iconfont-css-prefix}-sync:before { content: "\e6da"; }
|
||||
.@{iconfont-css-prefix}-wifi:before { content: "\e6d6"; }
|
||||
.@{iconfont-css-prefix}-car:before { content: "\e6dc"; }
|
||||
.@{iconfont-css-prefix}-copyright:before { content: "\e6de"; }
|
||||
.@{iconfont-css-prefix}-schedule:before { content: "\e6df"; }
|
||||
.@{iconfont-css-prefix}-user-add:before { content: "\e6ed"; }
|
||||
.@{iconfont-css-prefix}-user-delete:before { content: "\e6e0"; }
|
||||
.@{iconfont-css-prefix}-usergroup-add:before { content: "\e6dd"; }
|
||||
.@{iconfont-css-prefix}-usergroup-delete:before { content: "\e6e1"; }
|
||||
.@{iconfont-css-prefix}-man:before { content: "\e6e2"; }
|
||||
.@{iconfont-css-prefix}-woman:before { content: "\e6ec"; }
|
||||
.@{iconfont-css-prefix}-shop:before { content: "\e6e3"; }
|
||||
.@{iconfont-css-prefix}-gift:before { content: "\e6e4"; }
|
||||
.@{iconfont-css-prefix}-idcard:before { content: "\e6e5"; }
|
||||
.@{iconfont-css-prefix}-medicine-box:before { content: "\e6e6"; }
|
||||
.@{iconfont-css-prefix}-red-envelope:before { content: "\e6e7"; }
|
||||
.@{iconfont-css-prefix}-coffee:before { content: "\e6e8"; }
|
||||
.@{iconfont-css-prefix}-trademark:before { content: "\e651"; }
|
||||
.@{iconfont-css-prefix}-safety:before { content: "\e6ea"; }
|
||||
.@{iconfont-css-prefix}-wallet:before { content: "\e6eb"; }
|
||||
.@{iconfont-css-prefix}-bank:before { content: "\e6ee"; }
|
||||
.@{iconfont-css-prefix}-trophy:before { content: "\e6ef"; }
|
||||
.@{iconfont-css-prefix}-contacts:before { content: "\e6f0"; }
|
||||
.@{iconfont-css-prefix}-global:before { content: "\e6f1"; }
|
||||
.@{iconfont-css-prefix}-spin:before {
|
||||
display: inline-block;
|
||||
animation: loadingCircle 1s infinite linear;
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
// ICONFONT
|
||||
@iconfont-css-prefix : anticon;
|
||||
@icon-url : "https://at.alicdn.com/t/font_r5u29ls31bgldi";
|
||||
@icon-url : "https://at.alicdn.com/t/font_smk8xgfen9xxn7b9";
|
||||
|
||||
// LINK
|
||||
@link-color : @primary-color;
|
||||
@ -122,35 +122,43 @@
|
||||
// Extra small screen / phone
|
||||
@screen-xs : 480px;
|
||||
@screen-xs-min : @screen-xs;
|
||||
@screen-xs-max : (@screen-xs-min - 1);
|
||||
|
||||
// Small screen / tablet
|
||||
@screen-sm : 768px;
|
||||
@screen-sm-min : @screen-sm;
|
||||
@screen-sm-max : (@screen-sm-min - 1);
|
||||
|
||||
// Medium screen / desktop
|
||||
@screen-md : 992px;
|
||||
@screen-md-min : @screen-md;
|
||||
@screen-md-max : (@screen-md-min - 1);
|
||||
|
||||
// Large screen / wide desktop
|
||||
@screen-lg : 1200px;
|
||||
@screen-lg-min : @screen-lg;
|
||||
@screen-lg-max : (@screen-lg-min - 1);
|
||||
|
||||
// Extra Large screen / full hd
|
||||
@screen-xl : 1600px;
|
||||
@screen-xl-min : @screen-xl;
|
||||
|
||||
// provide a maximum
|
||||
@screen-xs-max : (@screen-sm-min - 1);
|
||||
@screen-sm-max : (@screen-md-min - 1);
|
||||
@screen-md-max : (@screen-lg-min - 1);
|
||||
@screen-lg-max : (@screen-xl-min - 1);
|
||||
|
||||
// Grid system
|
||||
@grid-columns : 24;
|
||||
@grid-gutter-width : 0;
|
||||
|
||||
// Layout
|
||||
@layout-body-background : #ececec;
|
||||
@layout-header-background : #404040;
|
||||
@layout-header-height : 64px;
|
||||
@layout-header-padding : 0 50px;
|
||||
@layout-footer-padding : 24px 50px;
|
||||
@layout-sider-background : @layout-header-background;
|
||||
@layout-trigger-height : 48px;
|
||||
@layout-body-background : #ececec;
|
||||
@layout-header-background : #404040;
|
||||
@layout-header-height : 64px;
|
||||
@layout-header-padding : 0 50px;
|
||||
@layout-footer-padding : 24px 50px;
|
||||
@layout-sider-background : @layout-header-background;
|
||||
@layout-trigger-height : 48px;
|
||||
@layout-zero-trigger-width : 36px;
|
||||
@layout-zero-trigger-height : 42px;
|
||||
|
||||
// z-index list
|
||||
@zindex-affix : 10;
|
||||
|
@ -1,6 +1,15 @@
|
||||
import React from 'react';
|
||||
import Checkbox from '../checkbox';
|
||||
import { Store } from './createStore';
|
||||
import Dropdown from '../dropdown';
|
||||
import Menu from '../menu';
|
||||
import Icon from '../icon';
|
||||
|
||||
export interface SelectionDecorator {
|
||||
key: string;
|
||||
text: React.ReactNode;
|
||||
onSelect: (changeableRowKeys: string[]) => void;
|
||||
}
|
||||
|
||||
export interface SelectionCheckboxAllProps {
|
||||
store: Store;
|
||||
@ -8,9 +17,21 @@ export interface SelectionCheckboxAllProps {
|
||||
getCheckboxPropsByItem: (item, index) => any;
|
||||
getRecordKey: (record, index?) => string;
|
||||
data: any[];
|
||||
onChange: (e) => void;
|
||||
prefixCls: string | undefined;
|
||||
onSelect: (key: string, index: number, selectFunc: any) => void;
|
||||
selections: SelectionDecorator[];
|
||||
}
|
||||
|
||||
const defaultSelections: SelectionDecorator[] = [{
|
||||
key: 'all',
|
||||
text: '全选',
|
||||
onSelect: () => {},
|
||||
}, {
|
||||
key: 'invert',
|
||||
text: '反选',
|
||||
onSelect: () => {},
|
||||
}];
|
||||
|
||||
export default class SelectionCheckboxAll extends React.Component<SelectionCheckboxAllProps, any> {
|
||||
unsubscribe: () => void;
|
||||
|
||||
@ -106,17 +127,61 @@ export default class SelectionCheckboxAll extends React.Component<SelectionCheck
|
||||
return indeterminate;
|
||||
}
|
||||
|
||||
handleSelectAllChagne = (e) => {
|
||||
let checked = e.target.checked;
|
||||
this.props.onSelect(checked ? 'all' : 'removeAll', 0, null);
|
||||
}
|
||||
|
||||
renderMenus(selections: SelectionDecorator[]) {
|
||||
return selections.map((selection, index) => {
|
||||
return (
|
||||
<Menu.Item
|
||||
key={selection.key || index}
|
||||
>
|
||||
<div
|
||||
onClick={() => {this.props.onSelect(selection.key, index, selection.onSelect);}}
|
||||
>
|
||||
{selection.text}
|
||||
</div>
|
||||
</Menu.Item>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { disabled, onChange } = this.props;
|
||||
const { disabled, prefixCls } = this.props;
|
||||
const { checked, indeterminate } = this.state;
|
||||
|
||||
let selectionPrefixCls = `${prefixCls}-selection`;
|
||||
|
||||
let selections = defaultSelections.concat(this.props.selections || []);
|
||||
|
||||
let menu = (
|
||||
<Menu
|
||||
className={`${selectionPrefixCls}-menu`}
|
||||
>
|
||||
{this.renderMenus(selections)}
|
||||
</Menu>
|
||||
);
|
||||
|
||||
return (
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
indeterminate={indeterminate}
|
||||
disabled={disabled}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<div className={selectionPrefixCls}>
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
indeterminate={indeterminate}
|
||||
disabled={disabled}
|
||||
onChange={this.handleSelectAllChagne}
|
||||
/>
|
||||
<Dropdown
|
||||
overlay={menu}
|
||||
>
|
||||
<div className={`${selectionPrefixCls}-down`}>
|
||||
<span>
|
||||
<Icon type="down" />
|
||||
</span>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,10 @@ import assign from 'object-assign';
|
||||
import warning from '../_util/warning';
|
||||
import createStore, { Store } from './createStore';
|
||||
import SelectionBox from './SelectionBox';
|
||||
import SelectionCheckboxAll from './SelectionCheckboxAll';
|
||||
import SelectionCheckboxAll, { SelectionDecorator } from './SelectionCheckboxAll';
|
||||
import Column, { ColumnProps } from './Column';
|
||||
import ColumnGroup from './ColumnGroup';
|
||||
import { SpinProps } from '../spin';
|
||||
|
||||
function noop() {
|
||||
}
|
||||
@ -45,6 +46,8 @@ export interface TableRowSelection<T> {
|
||||
getCheckboxProps?: (record: T) => Object;
|
||||
onSelect?: (record: T, selected: boolean, selectedRows: Object[]) => any;
|
||||
onSelectAll?: (selected: boolean, selectedRows: Object[], changeRows: Object[]) => any;
|
||||
onSelectInvert?: (selectedRows: Object[]) => any;
|
||||
selections?: SelectionDecorator[];
|
||||
}
|
||||
|
||||
export interface TableProps<T> {
|
||||
@ -65,7 +68,7 @@ export interface TableProps<T> {
|
||||
onExpandedRowsChange?: (expandedRowKeys: string[]) => void;
|
||||
onExpand?: (expanded: boolean, record: T) => void;
|
||||
onChange?: (pagination: PaginationProps | boolean, filters: string[], sorter: Object) => any;
|
||||
loading?: boolean;
|
||||
loading?: boolean | SpinProps ;
|
||||
locale?: Object;
|
||||
indentSize?: number;
|
||||
onRowClick?: (record: T, index: number) => any;
|
||||
@ -99,7 +102,10 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
|
||||
rowSelection: React.PropTypes.object,
|
||||
className: React.PropTypes.string,
|
||||
size: React.PropTypes.string,
|
||||
loading: React.PropTypes.bool,
|
||||
loading: React.PropTypes.oneOfType([
|
||||
React.PropTypes.bool,
|
||||
React.PropTypes.object,
|
||||
]),
|
||||
bordered: React.PropTypes.bool,
|
||||
onChange: React.PropTypes.func,
|
||||
locale: React.PropTypes.object,
|
||||
@ -268,6 +274,8 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
|
||||
(row, i) => changeRowKeys.indexOf(this.getRecordKey(row, i)) >= 0
|
||||
);
|
||||
rowSelection.onSelectAll(checked, selectedRows, changeRows);
|
||||
} else if (selectWay === 'onSelectInvert' && rowSelection.onSelectInvert) {
|
||||
rowSelection.onSelectInvert(selectedRowKeys);
|
||||
}
|
||||
}
|
||||
|
||||
@ -466,37 +474,63 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
|
||||
});
|
||||
}
|
||||
|
||||
handleSelectAllRow = (e) => {
|
||||
const checked = e.target.checked;
|
||||
handleSelectRow = (selectionKey, index, onSelectFunc) => {
|
||||
const data = this.getFlatCurrentPageData();
|
||||
const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection();
|
||||
const selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
|
||||
const changableRowKeys = data
|
||||
const changeableRowKeys = data
|
||||
.filter((item, i) => !this.getCheckboxPropsByItem(item, i).disabled)
|
||||
.map((item, i) => this.getRecordKey(item, i));
|
||||
|
||||
// 记录变化的列
|
||||
const changeRowKeys: string[] = [];
|
||||
if (checked) {
|
||||
changableRowKeys.forEach(key => {
|
||||
if (selectedRowKeys.indexOf(key) < 0) {
|
||||
selectedRowKeys.push(key);
|
||||
let changeRowKeys: string[] = [];
|
||||
let selectWay = '';
|
||||
let checked;
|
||||
// handle default selection
|
||||
switch (selectionKey) {
|
||||
case 'all':
|
||||
changeableRowKeys.forEach(key => {
|
||||
if (selectedRowKeys.indexOf(key) < 0) {
|
||||
selectedRowKeys.push(key);
|
||||
changeRowKeys.push(key);
|
||||
}
|
||||
});
|
||||
selectWay = 'onSelectAll';
|
||||
checked = true;
|
||||
break;
|
||||
case 'removeAll':
|
||||
changeableRowKeys.forEach(key => {
|
||||
if (selectedRowKeys.indexOf(key) >= 0) {
|
||||
selectedRowKeys.splice(selectedRowKeys.indexOf(key), 1);
|
||||
changeRowKeys.push(key);
|
||||
}
|
||||
});
|
||||
selectWay = 'onSelectAll';
|
||||
checked = false;
|
||||
break;
|
||||
case 'invert':
|
||||
changeableRowKeys.forEach(key => {
|
||||
if (selectedRowKeys.indexOf(key) < 0) {
|
||||
selectedRowKeys.push(key);
|
||||
}else {
|
||||
selectedRowKeys.splice(selectedRowKeys.indexOf(key), 1);
|
||||
}
|
||||
changeRowKeys.push(key);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
changableRowKeys.forEach(key => {
|
||||
if (selectedRowKeys.indexOf(key) >= 0) {
|
||||
selectedRowKeys.splice(selectedRowKeys.indexOf(key), 1);
|
||||
changeRowKeys.push(key);
|
||||
}
|
||||
});
|
||||
selectWay = 'onSelectInvert';
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this.store.setState({
|
||||
selectionDirty: true,
|
||||
});
|
||||
// when select custom selection, callback selections[n].onSelect
|
||||
if (index > 1 && typeof onSelectFunc === 'function') {
|
||||
return onSelectFunc(changeableRowKeys);
|
||||
}
|
||||
this.setSelectedRowKeys(selectedRowKeys, {
|
||||
selectWay: 'onSelectAll',
|
||||
selectWay: selectWay,
|
||||
checked,
|
||||
changeRowKeys,
|
||||
});
|
||||
@ -597,7 +631,9 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
|
||||
getCheckboxPropsByItem={this.getCheckboxPropsByItem}
|
||||
getRecordKey={this.getRecordKey}
|
||||
disabled={checkboxAllDisabled}
|
||||
onChange={this.handleSelectAllRow}
|
||||
prefixCls={prefixCls}
|
||||
onSelect={this.handleSelectRow}
|
||||
selections={rowSelection.selections || []}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -837,7 +873,7 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { style, className, prefixCls, showHeader, loading, ...restProps } = this.props;
|
||||
const { style, className, prefixCls, showHeader, ...restProps } = this.props;
|
||||
const data = this.getCurrentPageData();
|
||||
let columns = this.renderRowSelection();
|
||||
const expandIconAsCell = this.props.expandedRowRender && this.props.expandIconAsCell !== false;
|
||||
@ -882,10 +918,17 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
|
||||
const paginationPatchClass = (this.hasPagination() && data && data.length !== 0)
|
||||
? `${prefixCls}-with-pagination` : `${prefixCls}-without-pagination`;
|
||||
|
||||
let loading = this.props.loading;
|
||||
if (typeof loading === 'boolean') {
|
||||
loading = {
|
||||
spinning: loading,
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames(`${prefixCls}-wrapper`, className)} style={style}>
|
||||
<Spin
|
||||
spinning={loading}
|
||||
{...loading}
|
||||
className={loading ? `${paginationPatchClass} ${prefixCls}-spin-holder` : ''}
|
||||
>
|
||||
{table}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { mount, render } from 'enzyme';
|
||||
import { renderToJson } from 'enzyme-to-json';
|
||||
import Table from '..';
|
||||
|
||||
describe('Table.rowSelection', () => {
|
||||
@ -166,6 +167,68 @@ describe('Table.rowSelection', () => {
|
||||
|
||||
wrapper.find('input').first().simulate('change', { target: { checked: true } });
|
||||
expect(handleSelectAll).toBeCalledWith(true, data, data);
|
||||
|
||||
wrapper.find('input').first().simulate('change', { target: { checked: false } });
|
||||
expect(handleSelectAll).toBeCalledWith(false, [], data);
|
||||
});
|
||||
|
||||
it('render selection correctly', () => {
|
||||
const wrapper = mount(createTable());
|
||||
const dropdownWrapper = render(wrapper.find('Trigger').node.getComponent());
|
||||
expect(renderToJson(dropdownWrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('click select all selection', () => {
|
||||
const handleSelectAll = jest.fn();
|
||||
const rowSelection = {
|
||||
onSelectAll: handleSelectAll,
|
||||
};
|
||||
const wrapper = mount(createTable({ rowSelection }));
|
||||
|
||||
const dropdownWrapper = mount(wrapper.find('Trigger').node.getComponent());
|
||||
dropdownWrapper.find('.ant-dropdown-menu-item > div').first().simulate('click');
|
||||
|
||||
expect(handleSelectAll).toBeCalledWith(true, data, data);
|
||||
});
|
||||
|
||||
it('fires selectInvert event', () => {
|
||||
const handleSelectInvert = jest.fn();
|
||||
const rowSelection = {
|
||||
onSelectInvert: handleSelectInvert,
|
||||
};
|
||||
const wrapper = mount(createTable({ rowSelection }));
|
||||
const checkboxes = wrapper.find('input');
|
||||
|
||||
checkboxes.at(1).simulate('change', { target: { checked: true } });
|
||||
const dropdownWrapper = mount(wrapper.find('Trigger').node.getComponent());
|
||||
dropdownWrapper.find('.ant-dropdown-menu-item > div').last().simulate('click');
|
||||
|
||||
expect(handleSelectInvert).toBeCalledWith([1, 2, 3]);
|
||||
});
|
||||
|
||||
it('fires selection event', () => {
|
||||
const handleSelectOdd = jest.fn();
|
||||
const handleSelectEven = jest.fn();
|
||||
const rowSelection = {
|
||||
selections: [{
|
||||
key: 'odd',
|
||||
text: '奇数项',
|
||||
onSelect: handleSelectOdd,
|
||||
}, {
|
||||
key: 'even',
|
||||
text: '偶数项',
|
||||
onSelect: handleSelectEven,
|
||||
}],
|
||||
};
|
||||
const wrapper = mount(createTable({ rowSelection }));
|
||||
|
||||
const dropdownWrapper = mount(wrapper.find('Trigger').node.getComponent());
|
||||
|
||||
dropdownWrapper.find('.ant-dropdown-menu-item > div').at(2).simulate('click');
|
||||
expect(handleSelectOdd).toBeCalledWith([0, 1, 2, 3]);
|
||||
|
||||
dropdownWrapper.find('.ant-dropdown-menu-item > div').at(3).simulate('click');
|
||||
expect(handleSelectEven).toBeCalledWith([0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/4245
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { render, shallow } from 'enzyme';
|
||||
import { render, shallow, mount } from 'enzyme';
|
||||
import { renderToJson } from 'enzyme-to-json';
|
||||
import Table from '..';
|
||||
|
||||
@ -60,4 +60,20 @@ describe('Table', () => {
|
||||
|
||||
expect(wrapper.instance().columns).toBe(newColumns);
|
||||
});
|
||||
|
||||
it('loading with Spin', async () => {
|
||||
const loading = {
|
||||
spinning: false,
|
||||
delay: 500,
|
||||
};
|
||||
const wrapper = mount(<Table loading={loading} />);
|
||||
expect(wrapper.find('.ant-spin')).toHaveLength(0);
|
||||
|
||||
loading.spinning = true;
|
||||
wrapper.setProps({ loading });
|
||||
expect(wrapper.find('.ant-spin')).toHaveLength(0);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
expect(wrapper.find('.ant-spin')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,29 @@
|
||||
exports[`Table.rowSelection render selection correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-dropdown ant-dropdown-placement-bottomLeft ant-dropdown-hidden">
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-dropdown-menu ant-dropdown-menu-vertical ant-table-selection-menu ant-dropdown-menu-light ant-dropdown-menu-root"
|
||||
role="menu"
|
||||
tabindex="0">
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-dropdown-menu-item"
|
||||
role="menuitem">
|
||||
<div>
|
||||
全选
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-dropdown-menu-item"
|
||||
role="menuitem">
|
||||
<div>
|
||||
反选
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -1132,17 +1132,27 @@ exports[`test renders ./components/table/demo/dynamic-settings.md correctly 1`]
|
||||
<th
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<div
|
||||
class="ant-table-selection">
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
<div
|
||||
class="ant-table-selection-down ant-dropdown-trigger">
|
||||
<span>
|
||||
<i
|
||||
class="anticon anticon-down" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
@ -2322,17 +2332,27 @@ exports[`test renders ./components/table/demo/expand-children.md correctly 1`] =
|
||||
<th
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<div
|
||||
class="ant-table-selection">
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
<div
|
||||
class="ant-table-selection-down ant-dropdown-trigger">
|
||||
<span>
|
||||
<i
|
||||
class="anticon anticon-down" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
@ -6964,17 +6984,27 @@ exports[`test renders ./components/table/demo/row-selection.md correctly 1`] = `
|
||||
<th
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<div
|
||||
class="ant-table-selection">
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
<div
|
||||
class="ant-table-selection-down ant-dropdown-trigger">
|
||||
<span>
|
||||
<i
|
||||
class="anticon anticon-down" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
@ -7220,17 +7250,27 @@ exports[`test renders ./components/table/demo/row-selection-and-operation.md cor
|
||||
<th
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<div
|
||||
class="ant-table-selection">
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
<div
|
||||
class="ant-table-selection-down ant-dropdown-trigger">
|
||||
<span>
|
||||
<i
|
||||
class="anticon anticon-down" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
@ -7655,6 +7695,477 @@ exports[`test renders ./components/table/demo/row-selection-and-operation.md cor
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`test renders ./components/table/demo/row-selection-custom.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-table-wrapper">
|
||||
<div
|
||||
class="ant-spin-nested-loading">
|
||||
<div
|
||||
class="ant-spin-container">
|
||||
<div
|
||||
class="ant-table ant-table-large ant-table-scroll-position-left">
|
||||
<div
|
||||
class="ant-table-content">
|
||||
<div
|
||||
class="ant-table-body">
|
||||
<table
|
||||
class="">
|
||||
<colgroup>
|
||||
<col />
|
||||
<col />
|
||||
<col />
|
||||
<col />
|
||||
</colgroup>
|
||||
<thead
|
||||
class="ant-table-thead">
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<div
|
||||
class="ant-table-selection">
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
<div
|
||||
class="ant-table-selection-down ant-dropdown-trigger">
|
||||
<span>
|
||||
<i
|
||||
class="anticon anticon-down" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="">
|
||||
<span>
|
||||
Name
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="">
|
||||
<span>
|
||||
Age
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="">
|
||||
<span>
|
||||
Address
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
class="ant-table-tbody">
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0">
|
||||
<td
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px;" />
|
||||
Edward King 0
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
London, Park Lane no. 0
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0">
|
||||
<td
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px;" />
|
||||
Edward King 1
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
London, Park Lane no. 1
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0">
|
||||
<td
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px;" />
|
||||
Edward King 2
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
London, Park Lane no. 2
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0">
|
||||
<td
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px;" />
|
||||
Edward King 3
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
London, Park Lane no. 3
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0">
|
||||
<td
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px;" />
|
||||
Edward King 4
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
London, Park Lane no. 4
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0">
|
||||
<td
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px;" />
|
||||
Edward King 5
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
London, Park Lane no. 5
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0">
|
||||
<td
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px;" />
|
||||
Edward King 6
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
London, Park Lane no. 6
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0">
|
||||
<td
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px;" />
|
||||
Edward King 7
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
London, Park Lane no. 7
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0">
|
||||
<td
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px;" />
|
||||
Edward King 8
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
London, Park Lane no. 8
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0">
|
||||
<td
|
||||
class="ant-table-selection-column">
|
||||
<span>
|
||||
<label
|
||||
class="ant-checkbox-wrapper">
|
||||
<span
|
||||
class="ant-checkbox">
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox" />
|
||||
<span
|
||||
class="ant-checkbox-inner" />
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px;" />
|
||||
Edward King 9
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="">
|
||||
London, Park Lane no. 9
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
class="ant-pagination ant-table-pagination"
|
||||
unselectable="unselectable">
|
||||
<li
|
||||
class="ant-pagination-disabled ant-pagination-prev"
|
||||
title="上一页">
|
||||
<a />
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"
|
||||
title="1">
|
||||
<a>
|
||||
1
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-2"
|
||||
title="2">
|
||||
<a>
|
||||
2
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-3"
|
||||
title="3">
|
||||
<a>
|
||||
3
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-4"
|
||||
title="4">
|
||||
<a>
|
||||
4
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-5"
|
||||
title="5">
|
||||
<a>
|
||||
5
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class=" ant-pagination-next"
|
||||
title="下一页">
|
||||
<a />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`test renders ./components/table/demo/size.md correctly 1`] = `
|
||||
<div>
|
||||
<h4>
|
||||
|
@ -119,7 +119,7 @@ class Demo extends React.Component {
|
||||
return (
|
||||
<div>
|
||||
<div className="components-table-demo-control-bar">
|
||||
<Form inline>
|
||||
<Form layout="inline">
|
||||
<FormItem label="Bordered">
|
||||
<Switch checked={state.bordered} onChange={this.handleToggle('bordered')} />
|
||||
</FormItem>
|
||||
|
90
components/table/demo/row-selection-custom.md
Normal file
90
components/table/demo/row-selection-custom.md
Normal file
@ -0,0 +1,90 @@
|
||||
---
|
||||
order: 4
|
||||
title:
|
||||
en-US: Custom selection
|
||||
zh-CN: 自定义选择项
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
默认有全选和反选,通过 `rowSelection.selections` 自定义选择项。
|
||||
|
||||
## en-US
|
||||
|
||||
Default selection is select all and select invert, Use `rowSelection.selections` custom selections.
|
||||
|
||||
|
||||
````jsx
|
||||
import { Table } from 'antd';
|
||||
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
}, {
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
}];
|
||||
|
||||
const data = [];
|
||||
for (let i = 0; i < 46; i++) {
|
||||
data.push({
|
||||
key: i,
|
||||
name: `Edward King ${i}`,
|
||||
age: 32,
|
||||
address: `London, Park Lane no. ${i}`,
|
||||
});
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
selectedRowKeys: [], // Check here to configure the default column
|
||||
};
|
||||
onSelectChange = (selectedRowKeys) => {
|
||||
console.log('selectedRowKeys changed: ', selectedRowKeys);
|
||||
this.setState({ selectedRowKeys });
|
||||
}
|
||||
render() {
|
||||
const { selectedRowKeys } = this.state;
|
||||
const rowSelection = {
|
||||
selectedRowKeys,
|
||||
onChange: this.onSelectChange,
|
||||
selections: [{
|
||||
key: 'odd',
|
||||
text: '奇数项',
|
||||
onSelect: (changableRowKeys) => {
|
||||
let newSelectedRowKeys = [];
|
||||
newSelectedRowKeys = changableRowKeys.filter((key, index) => {
|
||||
if (index % 2 !== 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
this.setState({ selectedRowKeys: newSelectedRowKeys });
|
||||
},
|
||||
}, {
|
||||
key: 'even',
|
||||
text: '偶数项',
|
||||
onSelect: (changableRowKeys) => {
|
||||
let newSelectedRowKeys = [];
|
||||
newSelectedRowKeys = changableRowKeys.filter((key, index) => {
|
||||
if (index % 2 !== 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
this.setState({ selectedRowKeys: newSelectedRowKeys });
|
||||
},
|
||||
}],
|
||||
onSelection: this.onSelection,
|
||||
};
|
||||
return (
|
||||
<Table rowSelection={rowSelection} columns={columns} dataSource={data} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
````
|
@ -119,6 +119,16 @@ Properties for selection.
|
||||
| getCheckboxProps | get Checkbox or Radio props | Function(record) | - |
|
||||
| onSelect | callback that is called when select/deselect one row | Function(record, selected, selectedRows) | - |
|
||||
| onSelectAll | callback that is called when select/deselect all | Function(selected, selectedRows, changeRows) | - |
|
||||
| onSelectInvert | callback that is called when select invert | Function(selectedRows) | - |
|
||||
| selections | custom selection, [config](#rowSelection) | object[] | - |
|
||||
|
||||
### selection
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|---------------|--------------------------|-----------------|--------------|
|
||||
| key | key of this selection | string | - |
|
||||
| text | display text is this selection | string\|React.ReactNode | - |
|
||||
| onSelect | callback when click this selection | Function(changeableRowKeys) | - |
|
||||
|
||||
## Using in TypeScript
|
||||
|
||||
|
@ -120,6 +120,16 @@ const columns = [{
|
||||
| getCheckboxProps | 选择框的默认属性配置 | Function(record) | - |
|
||||
| onSelect | 用户手动选择/取消选择某列的回调 | Function(record, selected, selectedRows) | - |
|
||||
| onSelectAll | 用户手动选择/取消选择所有列的回调 | Function(selected, selectedRows, changeRows) | - |
|
||||
| onSelectInvert | 用户手动选择反选的回调 | Function(selectedRows) | - |
|
||||
| selections | 自定义选择项, [配置项](#selection) | object[] | - |
|
||||
|
||||
### selection
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------------------|--------------------------|-----------------|---------------------|---------|
|
||||
| key | React 需要的 key,建议设置 | string | - |
|
||||
| text | 选择项显示的文字 | string\|React.ReactNode | - |
|
||||
| onSelect | 选择项点击回调 | Function(changeableRowKeys) | - |
|
||||
|
||||
## 在 TypeScript 中使用
|
||||
|
||||
|
@ -434,6 +434,36 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-selection {
|
||||
width: 40px;
|
||||
|
||||
.@{iconfont-css-prefix}-down {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
&-menu {
|
||||
min-width: 96px;
|
||||
margin-top: 5px;
|
||||
margin-left: -30px;
|
||||
background: @component-background;
|
||||
border-radius: @border-radius-base;
|
||||
box-shadow: @box-shadow-base;
|
||||
|
||||
.@{ant-prefix}-dropdown-menu-item {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.@{ant-prefix}-action-down {
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
&-down {
|
||||
padding: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
&-row {
|
||||
&-expand-icon {
|
||||
cursor: pointer;
|
||||
|
@ -362,10 +362,9 @@ exports[`test renders ./components/tabs/demo/editable-card.md correctly 1`] = `
|
||||
aria-selected="true"
|
||||
class="ant-tabs-tab-active ant-tabs-tab"
|
||||
role="tab">
|
||||
<div>
|
||||
<div
|
||||
class="ant-tabs-tab-unclosable">
|
||||
Tab 1
|
||||
<i
|
||||
class="anticon anticon-close" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
@ -8,10 +8,12 @@ title:
|
||||
## zh-CN
|
||||
|
||||
只有卡片样式的页签支持新增和关闭选项。
|
||||
使用 `closable={false}` 禁止关闭。
|
||||
|
||||
## en-US
|
||||
|
||||
Only card type Tabs support adding & closeable.
|
||||
Only card type Tabs support adding & closable.
|
||||
+Use `closable={false}` to disable close.
|
||||
|
||||
````jsx
|
||||
import { Tabs } from 'antd';
|
||||
@ -23,7 +25,7 @@ class Demo extends React.Component {
|
||||
super(props);
|
||||
this.newTabIndex = 0;
|
||||
const panes = [
|
||||
{ title: 'Tab 1', content: 'Content of Tab 1', key: '1' },
|
||||
{ title: 'Tab 1', content: 'Content of Tab 1', key: '1', closable: false },
|
||||
{ title: 'Tab 2', content: 'Content of Tab 2', key: '2' },
|
||||
];
|
||||
this.state = {
|
||||
@ -66,7 +68,7 @@ class Demo extends React.Component {
|
||||
type="editable-card"
|
||||
onEdit={this.onEdit}
|
||||
>
|
||||
{this.state.panes.map(pane => <TabPane tab={pane.title} key={pane.key}>{pane.content}</TabPane>)}
|
||||
{this.state.panes.map(pane => <TabPane tab={pane.title} key={pane.key} closable={pane.closable}>{pane.content}</TabPane>)}
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ Ant Design has 3 types Tabs for different situation.
|
||||
| onChange | Callback when tab is switched | Function | - |
|
||||
| onTabClick | Callback when tab 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 |
|
||||
| size | Tab bar size. Options: default, small. Only works while `type="line"`. | string | default |
|
||||
| tabPosition | Position of tabs. Options: top, right, bottom & left | string | top |
|
||||
|
@ -19,6 +19,7 @@ export interface TabsProps {
|
||||
onChange?: (activeKey: string) => void;
|
||||
onTabClick?: Function;
|
||||
tabBarExtraContent?: React.ReactNode | null;
|
||||
tabBarStyle?: React.CSSProperties;
|
||||
type?: TabsType;
|
||||
tabPosition?: TabsPosition;
|
||||
onEdit?: (targetKey: string, action: any) => void;
|
||||
@ -34,6 +35,7 @@ export interface TabPaneProps {
|
||||
/** 选项卡头显示文字 */
|
||||
tab?: React.ReactNode | string;
|
||||
style?: React.CSSProperties;
|
||||
closable?: boolean;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
@ -90,6 +92,7 @@ export default class Tabs extends React.Component<TabsProps, any> {
|
||||
tabPosition,
|
||||
children,
|
||||
tabBarExtraContent,
|
||||
tabBarStyle,
|
||||
hideAdd,
|
||||
onTabClick,
|
||||
animated,
|
||||
@ -110,11 +113,19 @@ export default class Tabs extends React.Component<TabsProps, any> {
|
||||
if (type === 'editable-card') {
|
||||
childrenWithClose = [];
|
||||
React.Children.forEach(children as React.ReactNode, (child: React.ReactElement<any>, index) => {
|
||||
let closable = child.props.closable;
|
||||
closable = typeof closable === 'undefined' ? true : closable;
|
||||
const closeIcon = closable ? (
|
||||
<Icon
|
||||
type="close"
|
||||
onClick={e => this.removeTab(child.key, e)}
|
||||
/>
|
||||
) : null;
|
||||
childrenWithClose.push(cloneElement(child, {
|
||||
tab: (
|
||||
<div>
|
||||
<div className={closable ? undefined : `${prefixCls}-tab-unclosable`}>
|
||||
{child.props.tab}
|
||||
<Icon type="close" onClick={(e) => this.removeTab(child.key, e)} />
|
||||
{closeIcon}
|
||||
</div>
|
||||
),
|
||||
key: child.key || index,
|
||||
@ -141,6 +152,7 @@ export default class Tabs extends React.Component<TabsProps, any> {
|
||||
<ScrollableInkTabBar
|
||||
extraContent={tabBarExtraContent}
|
||||
onTabClick={onTabClick}
|
||||
style={tabBarStyle}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -28,6 +28,7 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。
|
||||
| onChange | 切换面板的回调 | Function | 无 |
|
||||
| onTabClick | tab 被点击的回调 | Function | 无 |
|
||||
| tabBarExtraContent | tab bar 上额外的元素 | React.ReactNode | 无 |
|
||||
| tabBarStyle | tar bar 的样式对象 | object | - |
|
||||
| type | 页签的基本样式,可选 `line`、`card` `editable-card` 类型 | string | 'line' |
|
||||
| size | 大小,提供 `default` 和 `small` 两种大小,仅当 `type="line"` 时生效。 | string | 'default' |
|
||||
| tabPosition | 页签位置,可选值有 `top` `right` `bottom` `left` | string | 'top' |
|
||||
|
@ -52,9 +52,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
&&-editable-card > &-bar &-tab:not(&-tab-active):hover {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
&&-editable-card > &-bar &-tab > div {
|
||||
transition: all 0.3s @ease-in-out;
|
||||
}
|
||||
&&-editable-card > &-bar &-tab:not(&-tab-active):hover > div:not(&-tab-unclosable) {
|
||||
margin-left: -8px;
|
||||
margin-right: -8px;
|
||||
}
|
||||
|
||||
&&-card > &-bar &-tab-active .@{iconfont-css-prefix}-close,
|
||||
|
5
components/time-picker/locale/ca_ES.tsx
Normal file
5
components/time-picker/locale/ca_ES.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
const locale = {
|
||||
placeholder: 'Seleccionar hora',
|
||||
};
|
||||
|
||||
export default locale;
|
5
components/time-picker/locale/cs_CZ.tsx
Normal file
5
components/time-picker/locale/cs_CZ.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
const locale = {
|
||||
placeholder: 'Vybrat čas',
|
||||
};
|
||||
|
||||
export default locale;
|
5
components/time-picker/locale/ko_KR.tsx
Normal file
5
components/time-picker/locale/ko_KR.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
const locale = {
|
||||
placeholder: '날짜 선택',
|
||||
};
|
||||
|
||||
export default locale;
|
5
components/time-picker/locale/nl_NL.tsx
Normal file
5
components/time-picker/locale/nl_NL.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
const locale = {
|
||||
placeholder: 'Selecteer tijd',
|
||||
};
|
||||
|
||||
export default locale;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user