mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-09 10:59:19 +08:00
Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b092c022aa | ||
|
|
5995aef78a | ||
|
|
449a982f92 | ||
|
|
446315faf4 | ||
|
|
e02d77b3df | ||
|
|
b64ea0edcc | ||
|
|
7f422c9e18 | ||
|
|
ba9949adcc | ||
|
|
af2cec65c5 | ||
|
|
63a15f0d92 | ||
|
|
d9dd3114c3 | ||
|
|
caf09cd99e | ||
|
|
e4b35e02d2 | ||
|
|
d3788034e5 | ||
|
|
d4e13e7616 | ||
|
|
952f8aabbc | ||
|
|
afb49f95d0 | ||
|
|
e253cce993 | ||
|
|
7373ce0758 | ||
|
|
6a1b1476be | ||
|
|
45b8a9b507 | ||
|
|
894a4ceb53 | ||
|
|
33a30ae927 | ||
|
|
7f974877bc | ||
|
|
ad88118373 | ||
|
|
bd8482c893 | ||
|
|
d44271ce45 | ||
|
|
5fb01c8300 | ||
|
|
01ddb398c7 | ||
|
|
7d2328b910 | ||
|
|
d10026b094 | ||
|
|
81a8b65e6a | ||
|
|
fba7d62648 | ||
|
|
d0c34380d4 | ||
|
|
5c711a275e | ||
|
|
4ae2467668 | ||
|
|
24f71ac6be | ||
|
|
ae5f8c1a04 | ||
|
|
e4b6ccf7f0 | ||
|
|
248f0d12ad | ||
|
|
137299f4c8 | ||
|
|
168370fb82 | ||
|
|
6e6970dbd5 | ||
|
|
7fad45403e | ||
|
|
2dc5b11c43 | ||
|
|
59805843e5 | ||
|
|
f443032caa | ||
|
|
82c816fbc9 | ||
|
|
d198c63a68 | ||
|
|
7372893b8e | ||
|
|
20bbf43ccd | ||
|
|
1eb3d68656 | ||
|
|
f40ba76ba7 | ||
|
|
7e73725c68 | ||
|
|
29a732e3a9 | ||
|
|
a105876ff1 | ||
|
|
479e975d29 | ||
|
|
14cbb03dc1 | ||
|
|
fa06625de0 | ||
|
|
b54020ea01 | ||
|
|
8c68e8f64b | ||
|
|
60ecb3c628 | ||
|
|
0b7856b712 | ||
|
|
048e3c9246 | ||
|
|
984a03e203 | ||
|
|
fc6ce27fd5 | ||
|
|
002f3f5127 | ||
|
|
d997dc9e1e | ||
|
|
ad9cfe8914 | ||
|
|
b2e6bdcf94 | ||
|
|
44f61ac987 | ||
|
|
4b5353b457 | ||
|
|
42d06e1f0e | ||
|
|
c5a043b4c8 | ||
|
|
037d739fa4 | ||
|
|
49e5bfa7ca | ||
|
|
27708b702c | ||
|
|
ea4e98d5f7 | ||
|
|
edb41f4420 | ||
|
|
1deea83a05 | ||
|
|
915ebd6a28 | ||
|
|
baa0c53132 | ||
|
|
746790a44e | ||
|
|
e7fb3447a2 | ||
|
|
a7d335ec7a | ||
|
|
2cb147f96d | ||
|
|
1e1a3e755c | ||
|
|
216f046f3b | ||
|
|
83ba6d96b4 |
@@ -9,6 +9,63 @@ If you want to read change logs before `2.0.0`, please visit [GitHub](https://gi
|
||||
|
||||
---
|
||||
|
||||
## 2.3.2
|
||||
|
||||
`2016-11-09`
|
||||
|
||||
* Fix dead loop while using `getFieldProps`.
|
||||
|
||||
## 2.3.1
|
||||
|
||||
`2016-11-07`
|
||||
|
||||
* Add missing `dist/antd.css` back.
|
||||
|
||||
## 2.3.0
|
||||
|
||||
`2016-11-04`
|
||||
|
||||
* Upgrade normalize.css to 5.0.
|
||||
* Point main file to `lib/index.js` in package.json. [#3397](https://github.com/ant-design/ant-design/pull/3397)
|
||||
* A brand new `Spin` design.
|
||||
* Add `addon` for `TimePicker` to allow render some addon to its bottom.
|
||||
* Add `onDragEnd` for `Tree`.
|
||||
* Add `bordered` for `Collapse`.
|
||||
* Improve `Tabs` switch animation.
|
||||
* Improve `Radio` and `Checkbox` style when it's disabled and mouse hovered. [#3590](https://github.com/ant-design/ant-design/issues/3590)
|
||||
* Opitimize `Transfer` performance.[#2860](https://github.com/ant-design/ant-design/issues/2860)
|
||||
* Fix nested `Popover` style issue. [#3448](https://github.com/ant-design/ant-design/issues/3448)
|
||||
* Fix issue resulting in server side render `Transfer` failed. [#3686](https://github.com/ant-design/ant-design/issues/3686)
|
||||
* Fix issue resulting in preview image not display when `Upload` in `picture-card` mode. [#3706](https://github.com/ant-design/ant-design/pull/3706) [@denzw](https://github.com/denzw)
|
||||
* DatePicker
|
||||
* `onChange` will be triggered when `DatePicker` in `showTime` mode on blur now.
|
||||
* Add `monthCellContentRender` and `cellContentRender` for `MonthPicker`.
|
||||
* `Rangepicker` can input time manually now.[#3718](https://github.com/ant-design/ant-design/issues/3718)
|
||||
* Add czech locale/translations.
|
||||
* Badge
|
||||
* Improve number over 99 displaying when mouse hovering. [#3645](https://github.com/ant-design/ant-design/issues/3645)
|
||||
* Fix moving animation when using `Badge` alone. [#3709](https://github.com/ant-design/ant-design/issues/3709)
|
||||
* Mention
|
||||
* Fix issue resulting in `Mention` will be covered by `Table`. [#3588](https://github.com/ant-design/ant-design/issues/3588)
|
||||
* Add `getSuggestionContainer` to allow specify container. [#3658](https://github.com/ant-design/ant-design/pull/3658)
|
||||
* Tag
|
||||
* Deprecate `color`. [#3560](https://github.com/ant-design/ant-design/issues/3560)
|
||||
* Add `type`. [#3560](https://github.com/ant-design/ant-design/issues/3560)
|
||||
* Add `checkable`. [#3560](https://github.com/ant-design/ant-design/issues/3560)
|
||||
* Radio.Group
|
||||
* Add `className`。
|
||||
* `null` or `undefined` `children` will be ignored.
|
||||
* Select
|
||||
* Add `tokenSeparators` to supoort automatic tokenization。[#2071](https://github.com/ant-design/ant-design/issues/2071)
|
||||
* Add `onFocus` callback. [#3587](https://github.com/ant-design/ant-design/issues/3587)
|
||||
* Fix issue resulting in Select can't display correct selected item text in `combobox` mode. [#3401](https://github.com/ant-design/ant-design/issues/3401)
|
||||
|
||||
## 2.2.1
|
||||
|
||||
`2016-11-02`
|
||||
|
||||
* Fix controlled DatePicker[showTime] not working bug. [#3665](https://github.com/ant-design/ant-design/issues/3665)
|
||||
|
||||
## 2.2.0
|
||||
|
||||
`2016-10-28`
|
||||
@@ -27,7 +84,6 @@ If you want to read change logs before `2.0.0`, please visit [GitHub](https://gi
|
||||
* New icons `bulb` `select` `like-o` `dislike-o`.
|
||||
* Adjust existing icons `loading` `like` `dislike`.
|
||||
* Improve the TypeScript definition of Card & DatePicker & Icon & Table. [@infeng](https://github.com/infeng) [3468](https://github.com/ant-design/ant-design/pull/3468) [#3603](https://github.com/ant-design/ant-design/pull/3603) [#3531](https://github.com/ant-design/ant-design/pull/3531)
|
||||
|
||||
* Fix Cascader `defaultValue` should work. [#3470](https://github.com/ant-design/ant-design/issues/3470)
|
||||
* Fix the alignment of Button & Input & DatePicker & Select. [#3481](https://github.com/ant-design/ant-design/issues/3481)
|
||||
* DatePicker
|
||||
|
||||
@@ -9,6 +9,63 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 2.3.2
|
||||
|
||||
`2016-11-09`
|
||||
|
||||
* 修复使用 `getFieldProps` 会导致死循环的问题。
|
||||
|
||||
## 2.3.1
|
||||
|
||||
`2016-11-07`
|
||||
|
||||
* 修正上个版本缺少 `dist/antd.css` 的问题。
|
||||
|
||||
## 2.3.0
|
||||
|
||||
`2016-11-04`
|
||||
|
||||
* 升级 normalize.css 到 5.0。
|
||||
* package.json 的 main 换成了 `lib/index.js`。[#3397](https://github.com/ant-design/ant-design/pull/3397)
|
||||
* 全新的 `Spin` 设计。
|
||||
* `TimePicker` 新增了 `addon` 以支持自定义的附加内容。
|
||||
* `Tree` 新增了 `onDragEnd`。
|
||||
* `Collapse` 新增了 `bordered`。
|
||||
* 优化 `Tabs` 切换时的动画效果。
|
||||
* 优化 `Radio` 和 `Checkbox` 在禁用和鼠标停留时的样式。[#3590](https://github.com/ant-design/ant-design/issues/3590)
|
||||
* 优化 `Transfer` 的性能。[#2860](https://github.com/ant-design/ant-design/issues/2860)
|
||||
* 修复 `Popover` 嵌套时的样式问题。[#3448](https://github.com/ant-design/ant-design/issues/3448)
|
||||
* 修复 `Transfer` 服务端渲染报错的问题。[#3686](https://github.com/ant-design/ant-design/issues/3686)
|
||||
* 修复 `Upload` `picture-card` 模式下新上传的图片不显示预览的问题。[#3706](https://github.com/ant-design/ant-design/pull/3706) [@denzw](https://github.com/denzw)
|
||||
* DatePicker
|
||||
* 在 `showTime` 模式下现在失去焦点也会触发 `onChange`。
|
||||
* `MonthPicker` 增加了 `monthCellContentRender` 和 `cellContentRender`。
|
||||
* `RangePicker` 现在可以手动输入时间了。[#3718](https://github.com/ant-design/ant-design/issues/3718)
|
||||
* 新增了捷克语的翻译。
|
||||
* Badge
|
||||
* 优化鼠标停留时超过 99 的数字显示。[#3645](https://github.com/ant-design/ant-design/issues/3645)
|
||||
* 修复单独使用时会有移动动画的问题。[#3709](https://github.com/ant-design/ant-design/issues/3709)
|
||||
* Mention
|
||||
* 修复会被 `Table` 遮住的问题。[#3588](https://github.com/ant-design/ant-design/issues/3588)
|
||||
* 新增 `getSuggestionContainer` 来指定容器。[#3658](https://github.com/ant-design/ant-design/pull/3658)
|
||||
* Tag
|
||||
* 废弃 `color` 属性。[#3560](https://github.com/ant-design/ant-design/issues/3560)
|
||||
* 新增 `type`。[#3560](https://github.com/ant-design/ant-design/issues/3560)
|
||||
* 新增 `checkable`。[#3560](https://github.com/ant-design/ant-design/issues/3560)
|
||||
* Radio.Group
|
||||
* 新增 `className`。
|
||||
* `children` 为 `null` 或 `undefined` 时现在会被忽略。
|
||||
* Select
|
||||
* 新增 `tokenSeparators` 支持粘贴时自动分词。[#2071](https://github.com/ant-design/ant-design/issues/2071)
|
||||
* 新增 `onFocus` 回调。[#3587](https://github.com/ant-design/ant-design/issues/3587)
|
||||
* 修复 `combobox` 模式下选中项不能正确显示的问题。[#3401](https://github.com/ant-design/ant-design/issues/3401)
|
||||
|
||||
## 2.2.1
|
||||
|
||||
`2016-11-02`
|
||||
|
||||
* 修复 Form 中 DatePicker[showTime](受控)无法使用的问题。[#3665](https://github.com/ant-design/ant-design/issues/3665)
|
||||
|
||||
## 2.2.0
|
||||
|
||||
`2016-10-28`
|
||||
@@ -27,7 +84,6 @@ timeline: true
|
||||
* 新增 `bulb` `select` `like-o` `dislike-o`。
|
||||
* 调整 `loading` `like` `dislike`。
|
||||
* 优化 Card DatePicker Icon Table 的 TypeScript 定义。[@infeng](https://github.com/infeng) [3468](https://github.com/ant-design/ant-design/pull/3468) [#3603](https://github.com/ant-design/ant-design/pull/3603) [#3531](https://github.com/ant-design/ant-design/pull/3531)
|
||||
|
||||
* 修复 Cascader `defaultValue` 失效的问题。[#3470](https://github.com/ant-design/ant-design/issues/3470)
|
||||
* 修复在一行内同时使用 Button Input DatePicker Select 时对齐的问题。[#3481](https://github.com/ant-design/ant-design/issues/3481)
|
||||
* DatePicker
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
[](https://travis-ci.org/ant-design/ant-design)
|
||||
[](https://www.npmjs.org/package/antd)
|
||||
[](https://npmjs.org/package/antd)
|
||||
[](https://cdnjs.com/libraries/antd)
|
||||
[](https://david-dm.org/ant-design/ant-design)
|
||||
[](http://isitmaintained.com/project/ant-design/ant-design "Average time to resolve an issue")
|
||||
[](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
An enterprise-class UI design language and React-based implementation.
|
||||
|
||||
9
components/_util/warning.tsx
Normal file
9
components/_util/warning.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import warning from 'warning';
|
||||
|
||||
const warned: { [msg: string]: boolean} = {};
|
||||
export default (valid: boolean, message: string): void => {
|
||||
if (!valid && !warned[message]) {
|
||||
warning(false, message);
|
||||
warned[message] = true;
|
||||
}
|
||||
};
|
||||
@@ -17,8 +17,15 @@ The simplest usage.
|
||||
import { Affix, Button } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Affix>
|
||||
<Button type="primary">Affix top</Button>
|
||||
</Affix>
|
||||
, mountNode);
|
||||
<div>
|
||||
<Affix>
|
||||
<Button type="primary">Affix top</Button>
|
||||
</Affix>
|
||||
<br />
|
||||
<Affix offsetBottom={0}>
|
||||
<Button type="primary">Affix bottom</Button>
|
||||
</Affix>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 下方固定
|
||||
en-US: Bottom
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
固定在屏幕下方。
|
||||
|
||||
## en-US
|
||||
|
||||
Affix to bottom.
|
||||
|
||||
````jsx
|
||||
import { Affix, Button } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Affix offsetBottom={20}>
|
||||
<Button type="primary">20px to affix bottom</Button>
|
||||
</Affix>
|
||||
, mountNode);
|
||||
````
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 偏移
|
||||
en-US: Offset
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
达到一定的偏移量才触发。
|
||||
|
||||
## en-US
|
||||
|
||||
Affix element according to offset value.
|
||||
|
||||
````jsx
|
||||
import { Affix, Button } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Affix offsetTop={75}>
|
||||
<Button type="primary">75px to affix top</Button>
|
||||
</Affix>
|
||||
, mountNode);
|
||||
````
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 3
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 固定状态改变的回调
|
||||
en-US: Callback
|
||||
@@ -19,6 +19,7 @@ import { Affix, Button } from 'antd';
|
||||
ReactDOM.render(
|
||||
<Affix offsetTop={120} onChange={affixed => console.log(affixed)}>
|
||||
<Button>120px to affix top</Button>
|
||||
</Affix>
|
||||
, mountNode);
|
||||
</Affix>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 4
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 滚动容器
|
||||
en-US: Container to scroll.
|
||||
@@ -11,20 +11,20 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
Set a `target` for 'Affix', which is listen to scroll event of target element (default is `window`).
|
||||
Set a `target` for 'Affix', which is listen to scroll event of target element (default is `window`).
|
||||
|
||||
````jsx
|
||||
import { Affix, Button } from 'antd';
|
||||
|
||||
const Demo = () => {
|
||||
return (
|
||||
<div style={{ height: 100, overflow: 'hidden' }}>
|
||||
<div style={{ height: '100%', overflowY: 'scroll' }} id="affix-target">
|
||||
<div style={{ height: 300, backgroundImage: 'url(https://zos.alipayobjects.com/rmsportal/RmjwQiJorKyobvI.jpg)' }}>
|
||||
<div className="view-port">
|
||||
<div id="scrollable-container">
|
||||
<div className="background">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<Affix target={() => document.getElementById('affix-target')} offsetTop={20}>
|
||||
<Affix target={() => document.getElementById('scrollable-container')} offsetTop={20}>
|
||||
<Button type="primary">Fixed at the top of container</Button>
|
||||
</Affix>
|
||||
</div>
|
||||
@@ -35,3 +35,18 @@ const Demo = () => {
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
````
|
||||
|
||||
<style>
|
||||
#components-affix-demo-target .view-port {
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
#components-affix-demo-target #scrollable-container {
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
#components-affix-demo-target .background {
|
||||
height: 300px;
|
||||
background-image: url('https://zos.alipayobjects.com/rmsportal/RmjwQiJorKyobvI.jpg');
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -17,7 +17,7 @@ When need to use autocomplete function.
|
||||
const dataSource = ['12345', '23456', '34567'];
|
||||
<AutoComplete dataSource={dataSource} />
|
||||
```
|
||||
|
||||
Since `AutoComplete` is based on `Select`, so besides following API, `AutoComplete` has same API as `Select`.
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|----------------|----------------------------------|------------|--------|
|
||||
|
||||
@@ -18,7 +18,7 @@ title: AutoComplete
|
||||
const dataSource = ['12345', '23456', '34567'];
|
||||
<AutoComplete dataSource={dataSource} />
|
||||
```
|
||||
|
||||
因为 `AutoComplete` 是基于 `Select` 封装的,所以除了以下 API 外,`AutoComplete` 跟 `Select` 拥有一样的 API。
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|----------------|----------------------------------|------------|---------|
|
||||
|
||||
@@ -19,7 +19,8 @@ import { BackTop } from 'antd';
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<BackTop />
|
||||
Scroll down to see the bottom right gray button.
|
||||
</div>
|
||||
, mountNode);
|
||||
Scroll down to see the bottom right <strong>gray</strong> button.
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -17,23 +17,29 @@ You can customize the style of the button, just note the size limit: no more tha
|
||||
````jsx
|
||||
import { BackTop } from 'antd';
|
||||
|
||||
const style = {
|
||||
height: 40,
|
||||
width: 40,
|
||||
lineHeight: '40px',
|
||||
borderRadius: 4,
|
||||
backgroundColor: '#57c5f7',
|
||||
color: '#fff',
|
||||
textAlign: 'center',
|
||||
fontSize: 20,
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<BackTop style={{ bottom: 100 }}>
|
||||
<div style={style}>UP</div>
|
||||
<BackTop>
|
||||
<div className="ant-back-top-inner">UP</div>
|
||||
</BackTop>
|
||||
Scroll down to see the bottom right blue button.
|
||||
</div>
|
||||
, mountNode);
|
||||
Scroll down to see the bottom right <strong>blue</strong> button.
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
````css
|
||||
#components-back-top-demo-custom .ant-back-top {
|
||||
bottom: 100px;
|
||||
}
|
||||
#components-back-top-demo-custom .ant-back-top-inner {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
line-height: 40px;
|
||||
border-radius: 4px;
|
||||
background-color: #57c5f7;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
````
|
||||
|
||||
@@ -67,7 +67,5 @@ const Test = React.createClass({
|
||||
},
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<Test />
|
||||
, mountNode);
|
||||
ReactDOM.render(<Test />, mountNode);
|
||||
````
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import Animate from 'rc-animate';
|
||||
import ScrollNumber from './ScrollNumber';
|
||||
import classNames from 'classnames';
|
||||
import warning from 'warning';
|
||||
import warning from '../_util/warning';
|
||||
import splitObject from '../_util/splitObject';
|
||||
|
||||
export interface BadgeProps {
|
||||
@@ -44,7 +44,7 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
['count', 'prefixCls', 'overflowCount', 'className', 'style', 'children', 'dot', 'status', 'text']
|
||||
);
|
||||
const isDot = dot || status;
|
||||
|
||||
const realCount = count;
|
||||
count = count > overflowCount ? `${overflowCount}+` : count;
|
||||
|
||||
// dot mode don't need count
|
||||
@@ -84,12 +84,12 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
}
|
||||
|
||||
return (
|
||||
<span {...restProps} className={badgeCls} title={count}>
|
||||
<span {...restProps} className={badgeCls} title={realCount}>
|
||||
{children}
|
||||
<Animate
|
||||
component=""
|
||||
showProp="data-show"
|
||||
transitionName={`${prefixCls}-zoom`}
|
||||
transitionName={children ? `${prefixCls}-zoom` : ''}
|
||||
transitionAppear
|
||||
>
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { cloneElement } from 'react';
|
||||
import warning from 'warning';
|
||||
import warning from '../_util/warning';
|
||||
import BreadcrumbItem from './BreadcrumbItem';
|
||||
|
||||
export interface BreadcrumbProps {
|
||||
@@ -52,9 +52,8 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
nameRender: React.PropTypes.func,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super();
|
||||
|
||||
componentDidMount() {
|
||||
const props = this.props;
|
||||
warning(
|
||||
!('linkRender' in props || 'nameRender' in props),
|
||||
'`linkRender` and `nameRender` are removed, please use `itemRender` instead.'
|
||||
|
||||
44
components/button/demo/multiple.md
Normal file
44
components/button/demo/multiple.md
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 多个按钮组合
|
||||
en-US: Multiple Buttons
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
按钮组合使用时,推荐使用1个主操作 + n 个次操作,3个以上操作时把更多操作放到 `Dropdown.Button` 中组合使用。
|
||||
|
||||
## en-US
|
||||
|
||||
If you need several buttons, we recommend that you use 1 primary button + n secondary buttons, and if there are more than three operations, you can group some of them into `Dropdown.Button`.
|
||||
|
||||
|
||||
````jsx
|
||||
import { Button, Menu, Dropdown, Icon } from 'antd';
|
||||
|
||||
function handleMenuClick(e) {
|
||||
console.log('click', e);
|
||||
}
|
||||
|
||||
const menu = (
|
||||
<Menu onClick={handleMenuClick}>
|
||||
<Menu.Item key="1">1st item</Menu.Item>
|
||||
<Menu.Item key="2">2nd item</Menu.Item>
|
||||
<Menu.Item key="3">3rd item</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Button type="primary">primary</Button>
|
||||
<Button type="ghost">secondary</Button>
|
||||
<Dropdown overlay={menu}>
|
||||
<Button type="ghost">
|
||||
more <Icon type="down" />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
@@ -20,9 +20,12 @@ If a large or small button is desired, set the `size` property to either `large`
|
||||
````jsx
|
||||
import { Button } from 'antd';
|
||||
|
||||
ReactDOM.render(<div>
|
||||
<Button type="primary" size="large">Large</Button>
|
||||
<Button type="primary">Default</Button>
|
||||
<Button type="primary" size="small">Small</Button>
|
||||
</div>, mountNode);
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Button type="primary" size="large">Large</Button>
|
||||
<Button type="primary">Default</Button>
|
||||
<Button type="primary" size="small">Small</Button>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
&:hover {
|
||||
box-shadow: @box-shadow-base;
|
||||
border-color: #eee;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
&-bordered {
|
||||
|
||||
@@ -12,14 +12,26 @@
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
|
||||
.@{checkbox-prefix-cls}-wrapper:hover &,
|
||||
&:hover,
|
||||
&-focused {
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: #bcbcbc;
|
||||
border-color: #bbb;
|
||||
}
|
||||
}
|
||||
|
||||
&-inner {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: inline-block;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border: 1px solid @border-color-base;
|
||||
border-radius: 3px;
|
||||
background-color: #fff;
|
||||
transition: all .3s;
|
||||
|
||||
&:after {
|
||||
transform: rotate(45deg) scale(0);
|
||||
position: absolute;
|
||||
@@ -34,19 +46,6 @@
|
||||
content: ' ';
|
||||
transition: all .1s @ease-in-back;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: inline-block;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-radius: 3px;
|
||||
border-color: @border-color-base;
|
||||
background-color: #fff;
|
||||
transition: border-color 0.1s @ease-in-out-back, background-color 0.1s @ease-in-out-back;
|
||||
}
|
||||
|
||||
&-input {
|
||||
@@ -64,83 +63,56 @@
|
||||
}
|
||||
|
||||
// 半选状态
|
||||
.@{checkbox-prefix-cls}-indeterminate .@{checkbox-inner-prefix-cls}:after {
|
||||
content: ' ';
|
||||
transform: scale(1);
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 5px;
|
||||
width: 8px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
// 选中状态
|
||||
.@{checkbox-prefix-cls}-checked .@{checkbox-inner-prefix-cls}:after {
|
||||
transform: rotate(45deg) scale(1);
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 1px;
|
||||
display: table;
|
||||
width: 5px;
|
||||
height: 8px;
|
||||
border: 2px solid #fff;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
content: ' ';
|
||||
transition: all .2s @ease-out-back .1s;
|
||||
}
|
||||
|
||||
.@{checkbox-prefix-cls}-checked,
|
||||
.@{checkbox-prefix-cls}-indeterminate {
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: @primary-color;
|
||||
background-color: @primary-color;
|
||||
&:after {
|
||||
content: ' ';
|
||||
transform: scale(1);
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 5px;
|
||||
width: 8px;
|
||||
height: 1px;
|
||||
}
|
||||
}
|
||||
.@{checkbox-prefix-cls}-wrapper:hover &,
|
||||
&:hover {
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 选中状态
|
||||
.@{checkbox-prefix-cls}-checked {
|
||||
|
||||
&:hover {
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: @primary-color;
|
||||
background-color: @primary-color;
|
||||
|
||||
&:after {
|
||||
transform: rotate(45deg) scale(1);
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 1px;
|
||||
display: table;
|
||||
width: 5px;
|
||||
height: 8px;
|
||||
border: 2px solid #fff;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
content: ' ';
|
||||
transition: all .2s @ease-out-back .1s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{checkbox-prefix-cls}-disabled {
|
||||
&.@{checkbox-prefix-cls}-checked {
|
||||
&:hover {
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: @border-color-base;
|
||||
}
|
||||
}
|
||||
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
background-color: #f3f3f3;
|
||||
border-color: @border-color-base;
|
||||
|
||||
&:after {
|
||||
animation-name: none;
|
||||
border-color: #ccc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: @border-color-base;
|
||||
.@{checkbox-inner-prefix-cls}:after {
|
||||
animation-name: none;
|
||||
border-color: #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: @border-color-base;
|
||||
border-color: @border-color-base!important;
|
||||
background-color: #f3f3f3;
|
||||
&:after {
|
||||
animation-name: none;
|
||||
@@ -148,10 +120,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.@{checkbox-inner-prefix-cls}-input {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
& + span {
|
||||
color: #ccc;
|
||||
cursor: @cursor-disabled;
|
||||
@@ -169,8 +137,8 @@
|
||||
|
||||
.@{checkbox-prefix-cls}-wrapper + span,
|
||||
.@{checkbox-prefix-cls} + span {
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.@{checkbox-prefix-cls}-group {
|
||||
|
||||
39
components/collapse/demo/borderless.md
Normal file
39
components/collapse/demo/borderless.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 简洁风格
|
||||
en-US: Borderless
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
一套没有边框的简洁样式。
|
||||
|
||||
## en-US
|
||||
|
||||
A borderless style of Collapse.
|
||||
|
||||
````jsx
|
||||
import { Collapse } from 'antd';
|
||||
const Panel = Collapse.Panel;
|
||||
|
||||
const text = `
|
||||
A dog is a type of domesticated animal.
|
||||
Known for its loyalty and faithfulness,
|
||||
it can be found as a welcome guest in many households across the world.
|
||||
`;
|
||||
|
||||
ReactDOM.render(
|
||||
<Collapse bordered={false} defaultActiveKey={['1']}>
|
||||
<Panel header="This is panel header 1" key="1">
|
||||
<p>{text}</p>
|
||||
</Panel>
|
||||
<Panel header="This is panel header 2" key="2">
|
||||
<p>{text}</p>
|
||||
</Panel>
|
||||
<Panel header="This is panel header 3" key="3">
|
||||
<p>{text}</p>
|
||||
</Panel>
|
||||
</Collapse>
|
||||
, mountNode);
|
||||
````
|
||||
@@ -1,17 +1,17 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
title:
|
||||
zh-CN: 面板嵌套
|
||||
en-US: Nested panel
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
手风琴嵌套折叠面板。
|
||||
嵌套折叠面板。
|
||||
|
||||
## en-US
|
||||
|
||||
`Collapse` is nested inside the `Accordion`.
|
||||
`Collapse` is nested inside the `Collapse`.
|
||||
|
||||
````jsx
|
||||
import { Collapse } from 'antd';
|
||||
@@ -28,7 +28,7 @@ const text = `
|
||||
`;
|
||||
|
||||
ReactDOM.render(
|
||||
<Collapse onChange={callback} accordion>
|
||||
<Collapse onChange={callback}>
|
||||
<Panel header={'This is panel header 1'} key="1">
|
||||
<Collapse defaultActiveKey="1">
|
||||
<Panel header={'This is panel nest panel'} key="1">
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
category: Components
|
||||
type: Views
|
||||
title: Collapse
|
||||
cols: 1
|
||||
---
|
||||
|
||||
A content area which can be collapsed and expanded.
|
||||
@@ -27,4 +28,3 @@ A content area which can be collapsed and expanded.
|
||||
|----------|----------------|----------|--------------|
|
||||
| key | corresponds to the `activeKey` | String | - |
|
||||
| header | title of the panel | React.Element or String | - |
|
||||
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
import RcCollapse from 'rc-collapse';
|
||||
import React from 'react';
|
||||
import RcCollapse from 'rc-collapse';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export interface CollapseProps {
|
||||
activeKey?: Array<string> | string;
|
||||
/** 初始化选中面板的key */
|
||||
defaultActiveKey?: Array<string>;
|
||||
/** accordion 为 true 的时候,一次只可以打开一个面板 */
|
||||
/** 手风琴效果 */
|
||||
accordion?: boolean;
|
||||
/** 切换面板的回调 */
|
||||
onChange?: (key: string) => void;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
bordered?: boolean;
|
||||
prefixCls?: string;
|
||||
}
|
||||
|
||||
export interface CollapsePanelProps {
|
||||
/** 对应 activeKey */
|
||||
key: string;
|
||||
/** 面板头内容 */
|
||||
header: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export class CollapsePanel extends React.Component<CollapsePanelProps, {}> {
|
||||
|
||||
}
|
||||
|
||||
export default class Collapse extends React.Component<CollapseProps, any> {
|
||||
@@ -29,9 +29,15 @@ export default class Collapse extends React.Component<CollapseProps, any> {
|
||||
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-collapse',
|
||||
bordered: true,
|
||||
};
|
||||
|
||||
render() {
|
||||
return <RcCollapse {...this.props} />;
|
||||
const { prefixCls, className = '', bordered } = this.props;
|
||||
const collapseClassName = classNames({
|
||||
[`${prefixCls}-borderless`]: !bordered,
|
||||
[className]: !!className,
|
||||
});
|
||||
return <RcCollapse {...this.props} className={collapseClassName} />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
type: Views
|
||||
title: Collapse
|
||||
subtitle: 折叠面板
|
||||
cols: 1
|
||||
---
|
||||
|
||||
可以折叠/展开的内容区域。
|
||||
|
||||
@@ -82,4 +82,22 @@
|
||||
.collapse-open();
|
||||
}
|
||||
}
|
||||
|
||||
&-borderless {
|
||||
background-color: #fff;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&-borderless > &-item {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&-borderless > &-item > &-header {
|
||||
border-bottom: 1px solid @border-color-base;
|
||||
transition: all .3s;
|
||||
border-radius: @border-color-base @border-color-base 0 0;
|
||||
&:hover {
|
||||
background-color: #fcfcfc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import moment from 'moment';
|
||||
import MonthCalendar from 'rc-calendar/lib/MonthCalendar';
|
||||
import RcDatePicker from 'rc-calendar/lib/Picker';
|
||||
import classNames from 'classnames';
|
||||
import assign from 'object-assign';
|
||||
import omit from 'omit.js';
|
||||
import Icon from '../icon';
|
||||
|
||||
@@ -31,9 +30,10 @@ export default function createPicker(TheCalendar) {
|
||||
},
|
||||
|
||||
componentWillReceiveProps(nextProps: PickerProps) {
|
||||
if ('value' in nextProps) {
|
||||
if (nextProps.value !== undefined) {
|
||||
this.setState({
|
||||
value: nextProps.value,
|
||||
tempValue: nextProps.value,
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -47,27 +47,30 @@ export default function createPicker(TheCalendar) {
|
||||
|
||||
handleChange(value) {
|
||||
const props = this.props;
|
||||
if (!('value' in props)) {
|
||||
if (props.value === undefined) {
|
||||
this.setState({ value });
|
||||
}
|
||||
props.onChange(value, (value && value.format(props.format)) || '');
|
||||
},
|
||||
|
||||
handleTempChange(tempValue) {
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ tempValue });
|
||||
}
|
||||
this.setState({ tempValue });
|
||||
},
|
||||
|
||||
// Clear temp value when hide picker panel
|
||||
handleOpenChange(open) {
|
||||
const { showTime, onOpenChange } = this.props;
|
||||
const { tempValue } = this.state;
|
||||
if (!open) {
|
||||
if (showTime && tempValue) {
|
||||
this.handleChange(tempValue);
|
||||
}
|
||||
this.setState({
|
||||
tempValue: undefined,
|
||||
});
|
||||
}
|
||||
if (this.props.onOpenChange) {
|
||||
this.props.onOpenChange(open);
|
||||
if (onOpenChange) {
|
||||
onOpenChange(open);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -91,14 +94,9 @@ export default function createPicker(TheCalendar) {
|
||||
let calendarHandler: Object = {};
|
||||
if (props.showTime) {
|
||||
calendarHandler = {
|
||||
onOk: this.handleChange,
|
||||
// fix https://github.com/ant-design/ant-design/issues/1902
|
||||
onSelect: (value, cause) => {
|
||||
if (cause && cause.source === 'todayButton') {
|
||||
this.handleChange(value);
|
||||
} else {
|
||||
this.handleTempChange(value);
|
||||
}
|
||||
onSelect: (value) => {
|
||||
this.handleTempChange(value);
|
||||
},
|
||||
};
|
||||
} else {
|
||||
@@ -123,19 +121,13 @@ export default function createPicker(TheCalendar) {
|
||||
/>
|
||||
);
|
||||
|
||||
// default width for showTime
|
||||
const pickerStyle: { width?: number } = {};
|
||||
if (props.showTime) {
|
||||
pickerStyle.width = 180;
|
||||
}
|
||||
|
||||
const clearIcon = (!props.disabled && props.allowClear && this.state.value) ?
|
||||
<Icon type="cross-circle"
|
||||
className={`${prefixCls}-picker-clear`}
|
||||
onClick={this.clearSelection}
|
||||
/> : null;
|
||||
return (
|
||||
<span className={props.pickerClass} style={assign({}, pickerStyle, props.style)}>
|
||||
<span className={props.pickerClass} style={props.style}>
|
||||
<RcDatePicker
|
||||
{...props}
|
||||
{...pickerChangeHandler}
|
||||
|
||||
@@ -15,14 +15,11 @@ By clicking the input box, you can select a date from a popup calendar.
|
||||
Note: Part of locale of DatePicker, MonthPicker, RangePicker is read from value. So, please set the locale of moment correctly.
|
||||
|
||||
```jsx
|
||||
import moment from 'moment-timezone/moment-timezone';
|
||||
import moment from 'moment';
|
||||
|
||||
// It's recommended to set locale and timezone in entry file globaly.
|
||||
// It's recommended to set locale in entry file globaly.
|
||||
import 'moment/locale/zh-cn';
|
||||
moment.locale('zh-cn');
|
||||
// The following data is copied from https://github.com/moment/moment-timezone/blob/develop/data/packed/latest.json
|
||||
moment.tz.add('Asia/Shanghai|CST CDT|-80 -90|01010101010101010|-1c1I0 LX0 16p0 1jz0 1Myp0 Rb0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0|23e6');
|
||||
moment.tz.setDefault('Asia/Shanghai')
|
||||
|
||||
<DatePicker defaultValue={moment('2015-01-01', 'YYYY-MM-DD')} />
|
||||
```
|
||||
@@ -62,6 +59,8 @@ The following APIs are shared by DatePicker, MonthPicker, RangePicker.
|
||||
| defaultValue | to set default date | [moment](http://momentjs.com/) | - |
|
||||
| format | to set the date format, refer to [moment.js](http://momentjs.com/) | String | "YYYY-MM" |
|
||||
| onChange | a callback function, can be executed when the selected time is changing | function(date: moment, dateString: string) | - |
|
||||
| monthCellContentRender | Custom month cell render method | function | 无 |
|
||||
| cellContentRender | Custom month cell content render method,the content will be appended to the cell. | function | 无 |
|
||||
|
||||
### RangePicker
|
||||
|
||||
|
||||
@@ -16,14 +16,11 @@ subtitle: 日期选择框
|
||||
注意:DatePicker、MonthPicker、RangePicker 部分 locale 是从 value 中读取,所以请先正确设置 moment 的 locale。
|
||||
|
||||
```jsx
|
||||
import moment from 'moment-timezone/moment-timezone';
|
||||
import moment from 'moment';
|
||||
|
||||
// 推荐在入口文件全局设置 locale 与时区
|
||||
// 推荐在入口文件全局设置 locale
|
||||
import 'moment/locale/zh-cn';
|
||||
moment.locale('zh-cn');
|
||||
// 从 https://github.com/moment/moment-timezone/blob/develop/data/packed/latest.json 复制
|
||||
moment.tz.add('Asia/Shanghai|CST CDT|-80 -90|01010101010101010|-1c1I0 LX0 16p0 1jz0 1Myp0 Rb0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0|23e6');
|
||||
moment.tz.setDefault('Asia/Shanghai')
|
||||
|
||||
<DatePicker defaultValue={moment('2015-01-01', 'YYYY-MM-DD')} />
|
||||
```
|
||||
@@ -63,6 +60,8 @@ moment.tz.setDefault('Asia/Shanghai')
|
||||
| defaultValue | 默认日期 | [moment](http://momentjs.com/) | 无 |
|
||||
| format | 展示的日期格式,配置参考 [moment.js](http://momentjs.com/) | string | "YYYY-MM" |
|
||||
| onChange | 时间发生变化的回调,发生在用户选择时间时 | function(date: moment, dateString: string) | 无 |
|
||||
| monthCellContentRender | 自定义的月份渲染方法 | function | 无 |
|
||||
| cellContentRender | 自定义的月份渲染方法,内容会被附加在月份后面 | function | 无 |
|
||||
|
||||
### RangePicker
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { PropTypes } from 'react';
|
||||
import TimePickerPanel from 'rc-time-picker/lib/Panel';
|
||||
import classNames from 'classnames';
|
||||
import warning from 'warning';
|
||||
import warning from '../_util/warning';
|
||||
import getLocale from '../_util/getLocale';
|
||||
declare const require: Function;
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
import { PropTypes } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import createDOMForm from 'rc-form/lib/createDOMForm';
|
||||
import PureRenderMixin from 'rc-util/lib/PureRenderMixin';
|
||||
import omit from 'omit.js';
|
||||
import warning from 'warning';
|
||||
import assign from 'object-assign';
|
||||
import warning from '../_util/warning';
|
||||
import FormItem from './FormItem';
|
||||
import createDOMForm from 'rc-form/lib/createDOMForm';
|
||||
import { FIELD_META_PROP } from './constants';
|
||||
|
||||
export interface FormCreateOption {
|
||||
@@ -81,8 +81,6 @@ export interface ComponentDecorator {
|
||||
<T extends (typeof FormComponent)>(component: T): T;
|
||||
}
|
||||
|
||||
let warnedGetFieldProps = false;
|
||||
|
||||
export default class Form extends React.Component<FormProps, any> {
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-form',
|
||||
@@ -123,24 +121,17 @@ export default class Form extends React.Component<FormProps, any> {
|
||||
};
|
||||
},
|
||||
componentWillMount() {
|
||||
if (!warnedGetFieldProps) {
|
||||
this.getFieldProps = this.props.form.getFieldProps;
|
||||
}
|
||||
this.__getFieldProps = this.props.form.getFieldProps;
|
||||
},
|
||||
deprecatedGetFieldProps(name, option) {
|
||||
if (!warnedGetFieldProps) {
|
||||
warnedGetFieldProps = true;
|
||||
warning(
|
||||
false,
|
||||
'`getFieldProps` is not recommended, please use `getFieldDecorator` instead'
|
||||
);
|
||||
}
|
||||
return this.getFieldProps(name, option);
|
||||
warning(
|
||||
false,
|
||||
'`getFieldProps` is not recommended, please use `getFieldDecorator` instead'
|
||||
);
|
||||
return this.__getFieldProps(name, option);
|
||||
},
|
||||
render() {
|
||||
if (!warnedGetFieldProps) {
|
||||
this.props.form.getFieldProps = this.deprecatedGetFieldProps;
|
||||
}
|
||||
this.props.form.getFieldProps = this.deprecatedGetFieldProps;
|
||||
|
||||
const withRef: any = {};
|
||||
if (options && options.withRef) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import warning from 'warning';
|
||||
import PureRenderMixin from 'rc-util/lib/PureRenderMixin';
|
||||
import Row from '../row';
|
||||
import Col from '../col';
|
||||
import { WrappedFormUtils } from './Form';
|
||||
import { FIELD_META_PROP } from './constants';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
export interface FormItemLabelColOption {
|
||||
span: number;
|
||||
@@ -26,14 +26,12 @@ export interface FormItemProps {
|
||||
required?: boolean;
|
||||
style?: React.CSSProperties;
|
||||
colon?: boolean;
|
||||
children: any;
|
||||
}
|
||||
|
||||
export interface FormItemContext {
|
||||
form: WrappedFormUtils;
|
||||
}
|
||||
|
||||
let autoGenerateWarning = false;
|
||||
export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
static defaultProps = {
|
||||
hasFeedback: false,
|
||||
@@ -62,14 +60,11 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
context: FormItemContext;
|
||||
|
||||
componentDidMount() {
|
||||
if (!autoGenerateWarning && (this.getControls(this.props.children, true).length > 1)) {
|
||||
autoGenerateWarning = true;
|
||||
warning(
|
||||
false,
|
||||
'`Form.Item` cannot generate `validateStatus` and `help` automatically, ' +
|
||||
'while there are more than one `getFieldDecorator` in it.'
|
||||
);
|
||||
}
|
||||
warning(
|
||||
this.getControls(this.props.children, true).length <= 1,
|
||||
'`Form.Item` cannot generate `validateStatus` and `help` automatically, ' +
|
||||
'while there are more than one `getFieldDecorator` in it.'
|
||||
);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(...args) {
|
||||
@@ -86,7 +81,7 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
return props.help;
|
||||
}
|
||||
|
||||
getControls(children, recursively) {
|
||||
getControls(children, recursively: boolean) {
|
||||
let controls: React.ReactElement<any>[] = [];
|
||||
const childrenArray = React.Children.toArray(children);
|
||||
for (let i = 0; i < childrenArray.length; i++) {
|
||||
@@ -239,7 +234,7 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
|
||||
renderChildren() {
|
||||
const props = this.props;
|
||||
const children = React.Children.map(props.children, (child: React.ReactElement<any>) => {
|
||||
const children = React.Children.map(props.children as React.ReactNode, (child: React.ReactElement<any>) => {
|
||||
if (child && typeof child.type === 'function' && !child.props.size) {
|
||||
return React.cloneElement(child, { size: 'large' });
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ Because the width of label is not fixed, you may need to adjust it by customizin
|
||||
import { Form, Row, Col, Input, Button, Icon } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const usualShowedChildren = 2 * 3; // row * col
|
||||
const AdvancedSearchForm = Form.create()(React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
@@ -31,20 +30,16 @@ const AdvancedSearchForm = Form.create()(React.createClass({
|
||||
},
|
||||
handleSearch(e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Received values of form: ', values);
|
||||
});
|
||||
},
|
||||
handleReset() {
|
||||
this.props.form.resetFields();
|
||||
},
|
||||
toggle(expand) {
|
||||
this.setState({ expand });
|
||||
toggle() {
|
||||
const { expand } = this.state;
|
||||
this.setState({ expand: !expand });
|
||||
},
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
@@ -58,10 +53,7 @@ const AdvancedSearchForm = Form.create()(React.createClass({
|
||||
for (let i = 0; i < 10; i++) {
|
||||
children.push(
|
||||
<Col span={8} key={i}>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label={`Field ${i}`}
|
||||
>
|
||||
<FormItem {...formItemLayout} label={`Field ${i}`}>
|
||||
{getFieldDecorator(`field-${i}`)(
|
||||
<Input placeholder="placeholder" />
|
||||
)}
|
||||
@@ -71,7 +63,7 @@ const AdvancedSearchForm = Form.create()(React.createClass({
|
||||
}
|
||||
|
||||
const expand = this.state.expand;
|
||||
const showedChildren = expand ? children.length : usualShowedChildren;
|
||||
const shownCount = expand ? children.length : 6;
|
||||
return (
|
||||
<Form
|
||||
horizontal
|
||||
@@ -79,23 +71,17 @@ const AdvancedSearchForm = Form.create()(React.createClass({
|
||||
onSubmit={this.handleSearch}
|
||||
>
|
||||
<Row gutter={40}>
|
||||
{children.slice(0, showedChildren)}
|
||||
{children.slice(0, shownCount)}
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={24} style={{ textAlign: 'right' }}>
|
||||
<Button type="primary" htmlType="submit">Search</Button>
|
||||
<Button onClick={this.handleReset}>Clear</Button>
|
||||
{
|
||||
expand ? (
|
||||
<a className="ant-dropdown-link" onClick={() => this.toggle(false)}>
|
||||
Collapse <Icon type="up" />
|
||||
</a>
|
||||
) : (
|
||||
<a className="ant-dropdown-link" onClick={() => this.toggle(true)}>
|
||||
Expand <Icon type="down" />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
<Button style={{ marginLeft: 8 }} onClick={this.handleReset}>
|
||||
Clear
|
||||
</Button>
|
||||
<a style={{ marginLeft: 8, fontSize: 12 }} onClick={this.toggle}>
|
||||
Collapse <Icon type={expand ? 'up' : 'down'} />
|
||||
</a>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
@@ -109,16 +95,10 @@ ReactDOM.render(<AdvancedSearchForm />, mountNode);
|
||||
````css
|
||||
#components-form-demo-advanced-search .ant-advanced-search-form {
|
||||
padding: 24px;
|
||||
background: #f8f8f8;
|
||||
background: #fbfbfb;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 6px;
|
||||
}
|
||||
#components-form-demo-advanced-search .ant-advanced-search-form .ant-btn + .ant-btn {
|
||||
margin-left: 8px;
|
||||
}
|
||||
#components-form-demo-advanced-search .ant-advanced-search-form .ant-dropdown-link {
|
||||
margin-left: 16px;
|
||||
}
|
||||
````
|
||||
|
||||
<style>
|
||||
|
||||
91
components/form/demo/customized-form-controls.md
Normal file
91
components/form/demo/customized-form-controls.md
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 自定义表单控件
|
||||
en-US: Customized Form Controls
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
自定义或第三方的表单控件,也可以与 Form 组件一起使用。只要该组件遵循以下的约定:
|
||||
> * 提供受控属性 `value` 或其它与 [`valuePropName`](http://ant.design/components/form/#getFieldDecorator-参数) 的值同名的属性。
|
||||
> * 提供 `onChange` 事件或 [`trigger`](http://ant.design/components/form/#getFieldDecorator-参数) 的值同名的事件。
|
||||
|
||||
## en-US
|
||||
|
||||
Customized or third-party form controls can be used in Form, too. Controls must follow these conventions:
|
||||
> * It has a controlled property `value` or other name which is equal to the value of [`valuePropName`](http://ant.design/components/form/?locale=en-US#getFieldDecorator's-parameters).
|
||||
> * It has event `onChange` or an event which name is equal to the value of [`trigger`](http://ant.design/components/form/?locale=en-US#getFieldDecorator's-parameters).
|
||||
|
||||
|
||||
````jsx
|
||||
import { Form, Input, Button } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const CustomizedInputNumber = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
value: this.props.value || 0,
|
||||
};
|
||||
},
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// Should be a controlled component.
|
||||
if ('value' in nextProps) {
|
||||
const value = nextProps.value;
|
||||
this.setState({ value });
|
||||
}
|
||||
},
|
||||
handleChange(e) {
|
||||
const number = parseFloat(e.target.value || 0);
|
||||
if (isNaN(number)) {
|
||||
return;
|
||||
}
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ value: number });
|
||||
}
|
||||
// Should provide an event to pass value to Form.
|
||||
const onChange = this.props.onChange;
|
||||
if (onChange) {
|
||||
onChange(number);
|
||||
}
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Input
|
||||
type="text"
|
||||
size={this.props.size}
|
||||
value={this.state.value}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const Demo = Form.create()(React.createClass({
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
console.log('Received values of form: ', values);
|
||||
}
|
||||
});
|
||||
},
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<Form inline onSubmit={this.handleSubmit}>
|
||||
<FormItem label="Number Only">
|
||||
{getFieldDecorator('number', {
|
||||
rules: [{ type: 'number' }],
|
||||
})(<CustomizedInputNumber />)}
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary" htmlType="submit">Submit</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
},
|
||||
}));
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
````
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
order: 15
|
||||
order: 5
|
||||
title:
|
||||
zh-CN: 动态增减表单项
|
||||
en-US: Dynamic form item
|
||||
en-US: Dynamic Form Item
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
@@ -26,34 +26,30 @@ let Demo = React.createClass({
|
||||
remove(k) {
|
||||
const { form } = this.props;
|
||||
// can use data-binding to get
|
||||
let keys = form.getFieldValue('keys');
|
||||
keys = keys.filter((key) => {
|
||||
return key !== k;
|
||||
});
|
||||
const keys = form.getFieldValue('keys');
|
||||
// can use data-binding to set
|
||||
form.setFieldsValue({
|
||||
keys,
|
||||
keys: keys.filter(key => key !== k),
|
||||
});
|
||||
},
|
||||
add() {
|
||||
uuid++;
|
||||
const { form } = this.props;
|
||||
// can use data-binding to get
|
||||
let keys = form.getFieldValue('keys');
|
||||
keys = keys.concat(uuid);
|
||||
const keys = form.getFieldValue('keys');
|
||||
const nextKeys = keys.concat(uuid);
|
||||
// can use data-binding to set
|
||||
// important! notify form to detect changes
|
||||
form.setFieldsValue({
|
||||
keys,
|
||||
keys: nextKeys,
|
||||
});
|
||||
},
|
||||
submit(e) {
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((errors, values) => {
|
||||
if (errors) {
|
||||
console.log(errors);
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
console.log('Received values of form: ', values);
|
||||
}
|
||||
console.log(values);
|
||||
});
|
||||
},
|
||||
render() {
|
||||
@@ -76,16 +72,16 @@ let Demo = React.createClass({
|
||||
})(
|
||||
<Input style={{ width: '60%', marginRight: 8 }} />
|
||||
)}
|
||||
<Button onClick={() => this.remove(k)}>remove</Button>
|
||||
<Button onClick={() => this.remove(k)}>Remove</Button>
|
||||
</Form.Item>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<Form horizontal>
|
||||
<Form horizontal onSubmit={this.handleSubmit}>
|
||||
{formItems}
|
||||
<Form.Item wrapperCol={{ span: 18, offset: 6 }}>
|
||||
<Button onClick={this.add} style={{ marginRight: 8 }}>add good friend</Button>
|
||||
<Button type="primary" onClick={this.submit}>submit</Button>
|
||||
<Button onClick={this.add} style={{ marginRight: 8 }}>Add good friend</Button>
|
||||
<Button type="primary" htmlType="submit">Submit</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
@@ -93,6 +89,5 @@ let Demo = React.createClass({
|
||||
});
|
||||
|
||||
Demo = Form.create()(Demo);
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
````
|
||||
|
||||
82
components/form/demo/global-state.md
Normal file
82
components/form/demo/global-state.md
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 表单数据存储于上层组件
|
||||
en-US: Store Form Data into Upper Component
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
通过使用 `onFieldsChange` 与 `mapPropsToFields`,可以把表单的数据存储到上层组件或者 [Redux](https://github.com/reactjs/redux)、[dva](https://github.com/dvajs/dva) 中。
|
||||
|
||||
## en-US
|
||||
|
||||
We can store form data into upper component or [Redux](https://github.com/reactjs/redux) or [dva](https://github.com/dvajs/dva) by using `onFieldsChange` and `mapPropsToFields`.
|
||||
|
||||
````jsx
|
||||
import { Form, Input } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const CustomizedForm = Form.create({
|
||||
onFieldsChange(props, changedFields) {
|
||||
props.onChange(changedFields);
|
||||
},
|
||||
mapPropsToFields(props) {
|
||||
return {
|
||||
username: {
|
||||
...props.username,
|
||||
value: props.username.value.toUpperCase(),
|
||||
},
|
||||
};
|
||||
},
|
||||
})((props) => {
|
||||
const { getFieldDecorator } = props.form;
|
||||
return (
|
||||
<Form inline>
|
||||
<FormItem label="Username">
|
||||
{getFieldDecorator('username', {
|
||||
rules: [{ required: true, message: 'Username is required!' }],
|
||||
})(<Input />)}
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
});
|
||||
|
||||
const Demo = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
fields: {
|
||||
username: {
|
||||
value: 'benjycui',
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
handleFormChange(changedFields) {
|
||||
this.setState({
|
||||
fields: { ...this.state.fields, ...changedFields },
|
||||
});
|
||||
},
|
||||
render() {
|
||||
const fields = this.state.fields;
|
||||
return (
|
||||
<div>
|
||||
<CustomizedForm {...fields} onChange={this.handleFormChange} />
|
||||
<pre className="language-bash">
|
||||
{JSON.stringify(fields, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
````
|
||||
|
||||
<style>
|
||||
#components-form-demo-global-state .language-bash {
|
||||
max-width: 400px;
|
||||
border-radius: 6px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
order: 0
|
||||
title:
|
||||
zh-CN: 水平登陆栏
|
||||
zh-CN: 水平登录栏
|
||||
en-US: Horizontal Login Form
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
水平登陆栏,常用在顶部导航栏中。
|
||||
水平登录栏,常用在顶部导航栏中。
|
||||
|
||||
## en-US
|
||||
|
||||
@@ -20,13 +20,10 @@ const FormItem = Form.Item;
|
||||
const HorizontalLoginForm = Form.create()(React.createClass({
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (err) {
|
||||
return;
|
||||
if (!err) {
|
||||
console.log('Received values of form: ', values);
|
||||
}
|
||||
|
||||
console.log('Received values of form: ', values);
|
||||
});
|
||||
},
|
||||
render() {
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 表单组合
|
||||
en-US: Mix
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
集中营,展示和表单相关的其他 ant-design 组件。
|
||||
|
||||
## en-US
|
||||
|
||||
A mix to demonstrate others ant-design component related to form.
|
||||
|
||||
````jsx
|
||||
import { Form, Select, InputNumber, DatePicker, TimePicker, Switch, Radio,
|
||||
Cascader, Slider, Button, Col, Upload, Icon } from 'antd';
|
||||
import moment from 'moment';
|
||||
import 'moment/locale/zh-cn';
|
||||
moment.locale('zh-cn');
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
const RadioButton = Radio.Button;
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
const areaData = [{
|
||||
value: 'shanghai',
|
||||
label: 'Shanghai',
|
||||
children: [{
|
||||
value: 'shanghaishi',
|
||||
label: 'Shanghai',
|
||||
children: [{
|
||||
value: 'pudongxinqu',
|
||||
label: 'Pudong New District',
|
||||
}],
|
||||
}],
|
||||
}];
|
||||
|
||||
let Demo = React.createClass({
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
console.log('Received the values of form', this.props.form.getFieldsValue());
|
||||
},
|
||||
|
||||
normFile(e) {
|
||||
if (Array.isArray(e)) {
|
||||
return e;
|
||||
}
|
||||
return e && e.fileList;
|
||||
},
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<Form horizontal onSubmit={this.handleSubmit}>
|
||||
<FormItem
|
||||
label="I'm the title"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
>
|
||||
<p className="ant-form-text" id="static" name="static">O, wind, if winter comes, can spring be far behind?</p>
|
||||
<p className="ant-form-text">
|
||||
<a href="#">link</a>
|
||||
</p>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="InputNumber"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 10 }}
|
||||
>
|
||||
{getFieldDecorator('inputNumber', { initialValue: 3 })(
|
||||
<InputNumber min={1} max={10} style={{ width: 100 }} />
|
||||
)}
|
||||
<span className="ant-form-text"> machines</span>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Switch"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 10 }}
|
||||
required
|
||||
>
|
||||
{getFieldDecorator('switch', { valuePropName: 'checked' })(
|
||||
<Switch />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Slider"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 10 }}
|
||||
required
|
||||
>
|
||||
{getFieldDecorator('slider')(
|
||||
<Slider marks={{ 0: 'A', 20: 'B', 40: 'C', 60: 'D', 80: 'E', 100: 'F' }} />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Select"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
required
|
||||
>
|
||||
{getFieldDecorator('select')(
|
||||
<Select style={{ width: 200 }}>
|
||||
<Option value="Jack">jack</Option>
|
||||
<Option value="Lucy">lucy</Option>
|
||||
<Option value="disabled" disabled>disabled</Option>
|
||||
<Option value="Yiminghe">yiminghe</Option>
|
||||
</Select>
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Cascader"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
required
|
||||
hasFeedback
|
||||
>
|
||||
{getFieldDecorator('area')(
|
||||
<Cascader style={{ width: 200 }} options={areaData} />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="DatePicker"
|
||||
labelCol={{ span: 8 }}
|
||||
required
|
||||
>
|
||||
<Col span="6">
|
||||
<FormItem>
|
||||
{getFieldDecorator('startDate')(
|
||||
<DatePicker />
|
||||
)}
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col span="1">
|
||||
<p className="ant-form-split">-</p>
|
||||
</Col>
|
||||
<Col span="6">
|
||||
<FormItem>
|
||||
{getFieldDecorator('endDate')(
|
||||
<DatePicker />
|
||||
)}
|
||||
</FormItem>
|
||||
</Col>
|
||||
</FormItem>
|
||||
|
||||
|
||||
<FormItem
|
||||
label="TimePicker"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
required
|
||||
>
|
||||
{getFieldDecorator('time')(
|
||||
<TimePicker />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Options"
|
||||
labelCol={{ span: 8 }}
|
||||
>
|
||||
{getFieldDecorator('rg')(
|
||||
<RadioGroup>
|
||||
<RadioButton value="a">item 1</RadioButton>
|
||||
<RadioButton value="b">item 2</RadioButton>
|
||||
<RadioButton value="c">item 3</RadioButton>
|
||||
</RadioGroup>
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="logo"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
help="longgggggggggggggggggggggggggggggggggg"
|
||||
>
|
||||
{getFieldDecorator('upload', {
|
||||
valuePropName: 'fileList',
|
||||
normalize: this.normFile,
|
||||
})(
|
||||
<Upload name="logo" action="/upload.do" listType="picture" onChange={this.handleUpload}>
|
||||
<Button type="ghost">
|
||||
<Icon type="upload" /> Click to upload
|
||||
</Button>
|
||||
</Upload>
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem wrapperCol={{ span: 16, offset: 8 }} style={{ marginTop: 24 }}>
|
||||
<Button type="primary" htmlType="submit">OK</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
Demo = Form.create()(Demo);
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
````
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 登陆框
|
||||
zh-CN: 登录框
|
||||
en-US: Login Form
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
普通的登陆框,可以容纳更多的元素。
|
||||
普通的登录框,可以容纳更多的元素。
|
||||
|
||||
## en-US
|
||||
|
||||
@@ -20,13 +20,10 @@ const FormItem = Form.Item;
|
||||
const NormalLoginForm = Form.create()(React.createClass({
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (err) {
|
||||
return;
|
||||
if (!err) {
|
||||
console.log('Received values of form: ', values);
|
||||
}
|
||||
|
||||
console.log('Received values of form: ', values);
|
||||
});
|
||||
},
|
||||
render() {
|
||||
|
||||
@@ -50,13 +50,10 @@ const RegistrationForm = Form.create()(React.createClass({
|
||||
},
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (err) {
|
||||
return;
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
console.log('Received values of form: ', values);
|
||||
}
|
||||
|
||||
console.log('Received values of form: ', values);
|
||||
});
|
||||
},
|
||||
handlePasswordBlur(e) {
|
||||
@@ -76,7 +73,6 @@ const RegistrationForm = Form.create()(React.createClass({
|
||||
if (value && this.state.passwordDirty) {
|
||||
form.validateFields(['confirm'], { force: true });
|
||||
}
|
||||
|
||||
callback();
|
||||
},
|
||||
render() {
|
||||
@@ -85,6 +81,12 @@ const RegistrationForm = Form.create()(React.createClass({
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 14 },
|
||||
};
|
||||
const tailFormItemLayout = {
|
||||
wrapperCol: {
|
||||
span: 14,
|
||||
offset: 6,
|
||||
},
|
||||
};
|
||||
const prefixSelector = getFieldDecorator('prefix', {
|
||||
initialValue: '86',
|
||||
})(
|
||||
@@ -195,19 +197,15 @@ const RegistrationForm = Form.create()(React.createClass({
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Row>
|
||||
<Col span={14} offset={6}>
|
||||
<p>
|
||||
{getFieldDecorator('agreement', {
|
||||
valuePropName: 'checked',
|
||||
})(
|
||||
<Checkbox>I had read the <a>agreement</a></Checkbox>
|
||||
)}
|
||||
</p>
|
||||
<Button type="primary" htmlType="submit" size="large">Register</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<FormItem {...tailFormItemLayout} style={{ marginBottom: 8 }}>
|
||||
{getFieldDecorator('agreement', {
|
||||
valuePropName: 'checked',
|
||||
})(
|
||||
<Checkbox>I had read the <a>agreement</a></Checkbox>
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem {...tailFormItemLayout}>
|
||||
<Button type="primary" htmlType="submit" size="large">Register</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 5
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 时间类控件
|
||||
en-US: Time-related Controls
|
||||
@@ -14,7 +14,7 @@ title:
|
||||
After `antd@2.0`, the `value` of time-related components had been changed to `moment`. So, we need to pre-process those values.
|
||||
|
||||
````jsx
|
||||
import { Form, DatePicker, TimePicker, Row, Col, Button } from 'antd';
|
||||
import { Form, DatePicker, TimePicker, Button } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
const MonthPicker = DatePicker.MonthPicker;
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
@@ -23,24 +23,40 @@ const TimeRelatedForm = Form.create()(React.createClass({
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const fieldsValue = this.props.form.getFieldsValue();
|
||||
this.props.form.validateFields((err, fieldsValue) => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Should format date value before submit.
|
||||
const rangeValue = fieldsValue['range-picker'];
|
||||
const values = {
|
||||
...fieldsValue,
|
||||
'date-picker': fieldsValue['date-picker'].format('YYYY-MM-DD'),
|
||||
'month-picker': fieldsValue['month-picker'].format('YYYY-MM'),
|
||||
'range-picker': [rangeValue[0].format('YYYY-MM-DD'), rangeValue[1].format('YYYY-MM-DD')],
|
||||
'time-picker': fieldsValue['time-picker'].format('HH:mm:ss'),
|
||||
};
|
||||
console.log('Received values of form: ', values);
|
||||
// Should format date value before submit.
|
||||
const rangeValue = fieldsValue['range-picker'];
|
||||
const rangeTimeValue = fieldsValue['range-time-picker'];
|
||||
const values = {
|
||||
...fieldsValue,
|
||||
'date-picker': fieldsValue['date-picker'].format('YYYY-MM-DD'),
|
||||
'date-time-picker': fieldsValue['date-time-picker'].format('YYYY-MM-DD HH:mm:ss'),
|
||||
'month-picker': fieldsValue['month-picker'].format('YYYY-MM'),
|
||||
'range-picker': [rangeValue[0].format('YYYY-MM-DD'), rangeValue[1].format('YYYY-MM-DD')],
|
||||
'range-time-picker': [
|
||||
rangeTimeValue[0].format('YYYY-MM-DD HH:mm:ss'),
|
||||
rangeTimeValue[1].format('YYYY-MM-DD HH:mm:ss'),
|
||||
],
|
||||
'time-picker': fieldsValue['time-picker'].format('HH:mm:ss'),
|
||||
};
|
||||
console.log('Received values of form: ', values);
|
||||
});
|
||||
},
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 14 },
|
||||
labelCol: { span: 8 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
const config = {
|
||||
rules: [{ type: 'object', required: true, message: 'Please select time!' }],
|
||||
};
|
||||
const rangeConfig = {
|
||||
rules: [{ type: 'array', required: true, message: 'Please select time!' }],
|
||||
};
|
||||
return (
|
||||
<Form horizontal onSubmit={this.handleSubmit}>
|
||||
@@ -48,15 +64,23 @@ const TimeRelatedForm = Form.create()(React.createClass({
|
||||
{...formItemLayout}
|
||||
label="DatePicker"
|
||||
>
|
||||
{getFieldDecorator('date-picker')(
|
||||
{getFieldDecorator('date-picker', config)(
|
||||
<DatePicker />
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="DatePicker[showTime]"
|
||||
>
|
||||
{getFieldDecorator('date-time-picker', config)(
|
||||
<DatePicker showTime format="YYYY-MM-DD HH:mm:ss" />
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="MonthPicker"
|
||||
>
|
||||
{getFieldDecorator('month-picker')(
|
||||
{getFieldDecorator('month-picker', config)(
|
||||
<MonthPicker />
|
||||
)}
|
||||
</FormItem>
|
||||
@@ -64,24 +88,28 @@ const TimeRelatedForm = Form.create()(React.createClass({
|
||||
{...formItemLayout}
|
||||
label="RangePicker"
|
||||
>
|
||||
{getFieldDecorator('range-picker')(
|
||||
{getFieldDecorator('range-picker', rangeConfig)(
|
||||
<RangePicker />
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="RangePicker[showTime]"
|
||||
>
|
||||
{getFieldDecorator('range-time-picker', rangeConfig)(
|
||||
<RangePicker showTime format="YYYY-MM-DD HH:mm:ss" />
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="TimePicker"
|
||||
>
|
||||
{getFieldDecorator('time-picker')(
|
||||
{getFieldDecorator('time-picker', config)(
|
||||
<TimePicker />
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Row>
|
||||
<Col span={14} offset={6}>
|
||||
<Button type="primary" htmlType="submit" size="large">Submit</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<FormItem wrapperCol={{ span: 16, offset: 8 }}>
|
||||
<Button type="primary" htmlType="submit" size="large">Submit</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
|
||||
@@ -1,115 +1,80 @@
|
||||
---
|
||||
order: 12
|
||||
order: 11
|
||||
title:
|
||||
zh-CN: 校验其他组件
|
||||
en-US: Others components related to validation
|
||||
en-US: Other Form Controls
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
提供以下组件表单域的校验:`Select` `Radio` `DatePicker` `InputNumber` `Cascader`。在 submit 时使用 `validateFieldsAndScroll`,进行校验,可以自动把不在可见范围内的校验不通过的菜单域滚动进可见范围。
|
||||
以上演示没有出现的表单控件对应的校验演示。
|
||||
|
||||
## en-US
|
||||
|
||||
Provide validation for following input filed: `Select` `Radio` `DatePicker` `InputNumber` `Cascader`. To use `validateFieldsAndScroll` with form validation, it will scroll the form to the failed input field which is not in visible area.
|
||||
Demostration for validataion configuration for form controls which are not show in the above demos.
|
||||
|
||||
````jsx
|
||||
import { Select, Radio, Checkbox, Button, DatePicker, TimePicker, InputNumber, Form, Cascader, Icon } from 'antd';
|
||||
const Option = Select.Option;
|
||||
const RadioGroup = Radio.Group;
|
||||
const createForm = Form.create;
|
||||
import {
|
||||
Form, Select, InputNumber, Switch, Radio,
|
||||
Slider, Button, Upload, Icon,
|
||||
} from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
const RadioButton = Radio.Button;
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
let Demo = React.createClass({
|
||||
componentDidMount() {
|
||||
this.props.form.setFieldsValue({
|
||||
eat: true,
|
||||
sleep: true,
|
||||
beat: true,
|
||||
});
|
||||
},
|
||||
|
||||
handleReset(e) {
|
||||
e.preventDefault();
|
||||
this.props.form.resetFields();
|
||||
},
|
||||
|
||||
const Demo = Form.create()(React.createClass({
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFieldsAndScroll((errors, values) => {
|
||||
if (errors) {
|
||||
console.log('Errors in form!!!');
|
||||
return;
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
console.log('Received values of form: ', values);
|
||||
}
|
||||
console.log('Submit!!!');
|
||||
console.log(values);
|
||||
});
|
||||
},
|
||||
|
||||
checkBirthday(rule, value, callback) {
|
||||
if (value && value.valueOf() >= Date.now()) {
|
||||
callback(new Error("You can't be born in the future!"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
|
||||
checkPrime(rule, value, callback) {
|
||||
if (value !== 11) {
|
||||
callback(new Error('The prime number between 8 to 12 is 11!'));
|
||||
} else {
|
||||
callback();
|
||||
normFile(e) {
|
||||
if (Array.isArray(e)) {
|
||||
return e;
|
||||
}
|
||||
return e && e.fileList;
|
||||
},
|
||||
|
||||
render() {
|
||||
const address = [{
|
||||
value: 'zhejiang',
|
||||
label: 'Zhe Jiang',
|
||||
children: [{
|
||||
value: 'hangzhou',
|
||||
label: 'Hang Zhou',
|
||||
}],
|
||||
}];
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 7 },
|
||||
wrapperCol: { span: 12 },
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 14 },
|
||||
};
|
||||
return (
|
||||
<Form horizontal>
|
||||
<Form horizontal onSubmit={this.handleSubmit}>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Country"
|
||||
label="Select"
|
||||
>
|
||||
{getFieldDecorator('select', {
|
||||
rules: [
|
||||
{ required: true, message: 'Please select your country' },
|
||||
{ required: true, message: 'Please select your country!' },
|
||||
],
|
||||
})(
|
||||
<Select placeholder="Please select a country" style={{ width: '100%' }}>
|
||||
<Select placeholder="Please select a country">
|
||||
<Option value="china">China</Option>
|
||||
<Option value="use">U.S.A</Option>
|
||||
<Option value="japan">Japan</Option>
|
||||
<Option value="korean">Korea</Option>
|
||||
<Option value="Thailand">Thai</Option>
|
||||
</Select>
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Favourite colors"
|
||||
label="Select[multiple]"
|
||||
>
|
||||
{getFieldDecorator('multiSelect', {
|
||||
{getFieldDecorator('select-multiple', {
|
||||
rules: [
|
||||
{ required: true, message: 'Please select your favourite colors', type: 'array' },
|
||||
{ required: true, message: 'Please select your favourite colors!', type: 'array' },
|
||||
],
|
||||
})(
|
||||
<Select multiple placeholder="Please select favourite colors" style={{ width: '100%' }}>
|
||||
<Select multiple placeholder="Please select favourite colors">
|
||||
<Option value="red">Red</Option>
|
||||
<Option value="orange">Orange</Option>
|
||||
<Option value="yellow">Yellow</Option>
|
||||
<Option value="green">Green</Option>
|
||||
<Option value="blue">Blue</Option>
|
||||
</Select>
|
||||
@@ -118,100 +83,69 @@ let Demo = React.createClass({
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Gender"
|
||||
label="InputNumber"
|
||||
>
|
||||
{getFieldDecorator('radio', {
|
||||
rules: [
|
||||
{ required: true, message: 'Please select your gender' },
|
||||
],
|
||||
})(
|
||||
{getFieldDecorator('input-number', { initialValue: 3 })(
|
||||
<InputNumber min={1} max={10} />
|
||||
)}
|
||||
<span className="ant-form-text"> machines</span>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Switch"
|
||||
>
|
||||
{getFieldDecorator('switch', { valuePropName: 'checked' })(
|
||||
<Switch />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Slider"
|
||||
>
|
||||
{getFieldDecorator('slider')(
|
||||
<Slider marks={{ 0: 'A', 20: 'B', 40: 'C', 60: 'D', 80: 'E', 100: 'F' }} />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Radio.Group"
|
||||
>
|
||||
{getFieldDecorator('radio-group')(
|
||||
<RadioGroup>
|
||||
<Radio value="male">male</Radio>
|
||||
<Radio value="female">female</Radio>
|
||||
<RadioButton value="a">item 1</RadioButton>
|
||||
<RadioButton value="b">item 2</RadioButton>
|
||||
<RadioButton value="c">item 3</RadioButton>
|
||||
</RadioGroup>
|
||||
)}
|
||||
<span><Icon type="info-circle-o" /> No other gender</span>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Hobby"
|
||||
label="Upload"
|
||||
help="longgggggggggggggggggggggggggggggggggg"
|
||||
>
|
||||
{getFieldDecorator('hobby')(
|
||||
<Checkbox.Group options={['eat', 'sleeping', 'dozen doug']} />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Birthday"
|
||||
>
|
||||
{getFieldDecorator('birthday', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
type: 'object',
|
||||
message: 'When is your birthday?',
|
||||
}, {
|
||||
validator: this.checkBirthday,
|
||||
},
|
||||
],
|
||||
{getFieldDecorator('upload', {
|
||||
valuePropName: 'fileList',
|
||||
normalize: this.normFile,
|
||||
})(
|
||||
<DatePicker />
|
||||
<Upload name="logo" action="/upload.do" listType="picture" onChange={this.handleUpload}>
|
||||
<Button type="ghost">
|
||||
<Icon type="upload" /> Click to upload
|
||||
</Button>
|
||||
</Upload>
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Select the time"
|
||||
>
|
||||
{getFieldDecorator('time', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
type: 'object',
|
||||
message: 'Please select the time',
|
||||
},
|
||||
],
|
||||
})(
|
||||
<TimePicker />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Prime num between 8, 12"
|
||||
>
|
||||
{getFieldDecorator('primeNumber', {
|
||||
rules: [{ validator: this.checkPrime }],
|
||||
})(
|
||||
<InputNumber min={8} max={12} />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Please select address"
|
||||
>
|
||||
{getFieldDecorator('address', {
|
||||
rules: [{ required: true, type: 'array' }],
|
||||
})(
|
||||
<Cascader options={address} />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
wrapperCol={{ span: 12, offset: 7 }}
|
||||
>
|
||||
<Button type="primary" onClick={this.handleSubmit}>OK</Button>
|
||||
|
||||
<Button type="ghost" onClick={this.handleReset}>Reset</Button>
|
||||
<FormItem wrapperCol={{ span: 12, offset: 7 }}>
|
||||
<Button type="primary" htmlType="submit">Submit</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
|
||||
Demo = createForm()(Demo);
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
````
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 6
|
||||
order: 10
|
||||
title:
|
||||
zh-CN: 校验提示
|
||||
en-US: Validation message
|
||||
@@ -38,7 +38,7 @@ ReactDOM.render(
|
||||
validateStatus="error"
|
||||
help="Should be combination of numbers & alphabets"
|
||||
>
|
||||
<Input defaultValue="unavailable choice" id="error" />
|
||||
<Input placeholder="unavailable choice" id="error" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
@@ -47,7 +47,7 @@ ReactDOM.render(
|
||||
wrapperCol={{ span: 12 }}
|
||||
validateStatus="warning"
|
||||
>
|
||||
<Input defaultValue="Warning" id="warning" />
|
||||
<Input placeholder="Warning" id="warning" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
@@ -58,7 +58,7 @@ ReactDOM.render(
|
||||
validateStatus="validating"
|
||||
help="The information is being validated..."
|
||||
>
|
||||
<Input defaultValue="I'm the content is being validated" id="validating" />
|
||||
<Input placeholder="I'm the content is being validated" id="validating" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
@@ -68,7 +68,7 @@ ReactDOM.render(
|
||||
hasFeedback
|
||||
validateStatus="success"
|
||||
>
|
||||
<Input defaultValue="I'm the content" id="success" />
|
||||
<Input placeholder="I'm the content" id="success" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
@@ -78,7 +78,7 @@ ReactDOM.render(
|
||||
hasFeedback
|
||||
validateStatus="warning"
|
||||
>
|
||||
<Input defaultValue="Warning" id="warning" />
|
||||
<Input placeholder="Warning" id="warning" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
@@ -89,7 +89,7 @@ ReactDOM.render(
|
||||
validateStatus="error"
|
||||
help="Should be combination of numbers & alphabets"
|
||||
>
|
||||
<Input defaultValue="unavailable choice" id="error" />
|
||||
<Input placeholder="unavailable choice" id="error" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
|
||||
75
components/form/demo/without-form-create.md
Normal file
75
components/form/demo/without-form-create.md
Normal file
@@ -0,0 +1,75 @@
|
||||
---
|
||||
order: 9
|
||||
title:
|
||||
zh-CN: 自行处理表单数据
|
||||
en-US: Handle Form Data Manually
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `Form.create` 处理后的表单具有自动收集数据并校验的功能,但如果您不需要这个功能,或者默认的行为无法满足业务需求,可以选择不使用 `Form.create` 并自行处理数据。
|
||||
|
||||
## en-US
|
||||
|
||||
`Form.create` will collect and validate form data automatically. But if you don't need this feature or the default behaviour cannot satisfy you business, you can drop `Form.create` and handle form data manually.
|
||||
|
||||
````jsx
|
||||
import { Form, InputNumber } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const RawForm = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
number: {
|
||||
value: 11,
|
||||
},
|
||||
};
|
||||
},
|
||||
handleNumberChange(value) {
|
||||
this.setState({
|
||||
number: {
|
||||
...this.validatePrimeNumber(value),
|
||||
value,
|
||||
},
|
||||
});
|
||||
},
|
||||
validatePrimeNumber(number) {
|
||||
if (number === 11) {
|
||||
return {
|
||||
validateStatus: 'success',
|
||||
errorMsg: null,
|
||||
};
|
||||
}
|
||||
return {
|
||||
validateStatus: 'error',
|
||||
errorMsg: 'The prime number between 8 to 12 is 11!',
|
||||
};
|
||||
},
|
||||
render() {
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 8 },
|
||||
wrapperCol: { span: 12 },
|
||||
};
|
||||
const number = this.state.number;
|
||||
return (
|
||||
<Form horizontal>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Prime num between 8 & 12"
|
||||
validateStatus={number.validateStatus}
|
||||
help={number.errorMsg}
|
||||
>
|
||||
<InputNumber
|
||||
min={8}
|
||||
max={12}
|
||||
value={number.value}
|
||||
onChange={this.handleNumberChange}
|
||||
/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
ReactDOM.render(<RawForm />, mountNode);
|
||||
````
|
||||
@@ -40,7 +40,6 @@ A form field is defined using `<Form.Item />`.
|
||||
| horizontal | Use horizontal layout. | boolean | false |
|
||||
| inline | Use inline alignment. | boolean | false |
|
||||
| onSubmit | Defines a function will be called if form data validation is successful. | Function(e:Event) | |
|
||||
| prefixCls | Set the CSS class name of form component (optional). | string | 'ant-form' |
|
||||
|
||||
### Form.create(options)
|
||||
|
||||
@@ -102,8 +101,9 @@ If you use `react@<15.3.0`, then, you can't use `getFieldDecorator` in stateless
|
||||
|
||||
### Form.Item
|
||||
|
||||
> * If Form.Item has multiple children, `help`, `required`, and `validateStatus` can't be generated automatically.
|
||||
> * Form controls must be child of Form.Item, otherwise, you need to set `help`, `required` and `validateStatus` by yourself.
|
||||
Note:
|
||||
* If Form.Item has multiple children that had been decorated by `getFieldDecorator`, `help` and `required` and `validateStatus` can't be generated automatically.
|
||||
* Before `2.2.0`, form controls must be child of Form.Item, otherwise, you need to set `help`, `required` and `validateStatus` by yourself.
|
||||
|
||||
| Property | Description | Type | Optional | Default Value |
|
||||
|-----------|------------------------------------------|-----------|-------|--------|
|
||||
@@ -115,7 +115,6 @@ If you use `react@<15.3.0`, then, you can't use `getFieldDecorator` in stateless
|
||||
| required | Whether provided or not, it will be generated by the validation rule. | bool | | false |
|
||||
| validateStatus | The validation status. If not provided, it will be generated by validation rule | string | 'success' 'warning' 'error' 'validating' | |
|
||||
| hasFeedback | Used with `validateStatus`, this option specifies the validation status icon. Recommended to be used only with `Input`. | bool | | false |
|
||||
| prefixCls | The CSS class name of form item (optional). | string | | 'ant-form' |
|
||||
|
||||
<style>
|
||||
.code-box-demo .ant-form-horizontal {
|
||||
|
||||
@@ -42,7 +42,6 @@ title: Form
|
||||
| horizontal | 水平排列布局 | boolean | false |
|
||||
| inline | 行内排列布局 | boolean | false |
|
||||
| onSubmit | 数据验证成功后回调事件 | Function(e:Event) | |
|
||||
| prefixCls | 样式类名,默认为 ant-form,通常您不需要设置 | string | 'ant-form' |
|
||||
|
||||
### Form.create(options)
|
||||
|
||||
@@ -103,8 +102,9 @@ CustomizedForm = Form.create({})(CustomizedForm);
|
||||
|
||||
### Form.Item
|
||||
|
||||
> * 一个 Form.Item 建议只放一个 child,有多个 child 时,`help` `required` `validateStatus` 无法自动生成。
|
||||
> * 只有当表单域为 Form.Item 的子元素时,才会自动生成 `help` `required` `validateStatus`,其它情况请自行设置。
|
||||
注意:
|
||||
* 一个 Form.Item 建议只放一个被 getFieldDecorator 装饰过的 child,当有多个被装饰过的 child 时,`help` `required` `validateStatus` 无法自动生成。
|
||||
* `2.2.0` 之前,只有当表单域为 Form.Item 的子元素时,才会自动生成 `help` `required` `validateStatus`,嵌套情况需要自行设置。
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|-----------|------------------------------------------|-----------|-------|--------|
|
||||
@@ -116,7 +116,6 @@ CustomizedForm = Form.create({})(CustomizedForm);
|
||||
| required | 是否必填,如不设置,则会根据校验规则自动生成 | bool | | false |
|
||||
| validateStatus | 校验状态,如不设置,则会根据校验规则自动生成 | string | 'success' 'warning' 'error' 'validating' | |
|
||||
| hasFeedback | 配合 validateStatus 属性使用,展示校验状态图标,建议只配合 Input 组件使用 | bool | | false |
|
||||
| prefixCls | 样式类名,默认为 ant-form,通常您不需要设置 | string | | 'ant-form' |
|
||||
|
||||
<style>
|
||||
.code-box-demo .ant-form-horizontal {
|
||||
|
||||
@@ -60,8 +60,8 @@ ReactDOM.render(<IconSet className="icons" catigory="other" />, mountNode);
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|----------|------------------|------- |---------|
|
||||
| type | Type of ant design icons | String | - |
|
||||
| spin | Rotate icon with animation | Boolean | false |
|
||||
| type | Type of ant design icons | string | - |
|
||||
| spin | Rotate icon with animation | boolean | false |
|
||||
|
||||
<style>
|
||||
.markdown .icons {
|
||||
|
||||
@@ -61,8 +61,8 @@ ReactDOM.render(<IconSet className="icons" catigory="other" />, mountNode);
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|----------|------------------|----------|--------|
|
||||
| type | 图标类型 | String | - |
|
||||
| spin | 是否有旋转动画 | Boolean | false |
|
||||
| type | 图标类型 | string | - |
|
||||
| spin | 是否有旋转动画 | boolean | false |
|
||||
|
||||
<style>
|
||||
.markdown .icons {
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/* eslint no-console:0 */
|
||||
// this file is not used if use https://github.com/ant-design/babel-plugin-import
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (typeof console !== 'undefined' && console.warn) {
|
||||
console.warn(`You are using prebuilt antd,
|
||||
please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size.`);
|
||||
}
|
||||
}
|
||||
|
||||
export { default as Affix } from './affix';
|
||||
|
||||
export { default as AutoComplete } from './auto-complete';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
order: 0
|
||||
title:
|
||||
zh-CN: 基础布局
|
||||
en-US: Basic Layout
|
||||
zh-CN: 基础栅格
|
||||
en-US: Basic Grid
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
@@ -15,7 +15,7 @@ title:
|
||||
|
||||
From the stack to the horizontal arrangement.
|
||||
|
||||
You can create a basic grid system by using a single set of `Row` and` Col` grid assembly, ,all of the columns (Col) must be placed in `Row`.
|
||||
You can create a basic grid system by using a single set of `Row` and` Col` grid assembly, all of the columns (Col) must be placed in `Row`.
|
||||
|
||||
````jsx
|
||||
import { Row, Col } from 'antd';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
title:
|
||||
zh-CN: 左右偏移
|
||||
en-US: Offset
|
||||
en-US: Column offset
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
@@ -15,9 +15,6 @@ title:
|
||||
|
||||
`Offset` can set the column to the right side. For example, using `offset = {4}` can set the element shifted to the right four columns width.
|
||||
|
||||
Column offset.
|
||||
|
||||
|
||||
````jsx
|
||||
import { Row, Col } from 'antd';
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ title:
|
||||
|
||||
## 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` properties to use,
|
||||
where `xs = {6}` is equivalent to `xs = {{span: 6}}`.
|
||||
|
||||
````jsx
|
||||
|
||||
@@ -11,7 +11,7 @@ title:
|
||||
|
||||
## 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 four dimensions: `xs` sm` `md` lg`.
|
||||
|
||||
````jsx
|
||||
import { Row, Col } from 'antd';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 布局排序
|
||||
en-US: Layout sort
|
||||
title:
|
||||
zh-CN: 栅格排序
|
||||
en-US: Grid sort
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
@@ -44,7 +44,7 @@ const AsyncMention = React.createClass({
|
||||
const { suggestions, loading } = this.state;
|
||||
return (
|
||||
<Mention
|
||||
style={{ width: 500, height: 100 }}
|
||||
style={{ width: '100%', height: 100 }}
|
||||
loading={loading}
|
||||
suggestions={suggestions}
|
||||
onSearchChange={this.onSearchChange}
|
||||
|
||||
@@ -22,7 +22,7 @@ const Nav = Mention.Nav;
|
||||
const webFrameworks = [
|
||||
{ name: 'React', type: 'JavaScript', icon: 'https://zos.alipayobjects.com/rmsportal/LFIeMPzdLcLnEUe.svg' },
|
||||
{ name: 'Angular', type: 'JavaScript', icon: 'https://zos.alipayobjects.com/rmsportal/PJTbxSvzYWjDZnJ.png' },
|
||||
{ name: 'Laravel', type: 'PHP', icon: 'http://laravel-china.org/assets/img/laravel-logo.png' },
|
||||
{ name: 'Dva', type: 'Javascript', icon: 'https://zos.alipayobjects.com/rmsportal/EYPwSeEJKxDtVxI.png' },
|
||||
{ name: 'Flask', type: 'Python', icon: 'https://zos.alipayobjects.com/rmsportal/xaypBUijfnpAlXE.png' },
|
||||
];
|
||||
|
||||
@@ -53,7 +53,7 @@ const CustomNavMention = React.createClass({
|
||||
const { suggestions } = this.state;
|
||||
return (
|
||||
<Mention
|
||||
style={{ width: 500, height: 100 }}
|
||||
style={{ width: '100%', height: 100 }}
|
||||
suggestions={suggestions}
|
||||
onSearchChange={this.onSearchChange}
|
||||
/>
|
||||
|
||||
@@ -27,7 +27,7 @@ function onSelect(suggestion) {
|
||||
|
||||
ReactDOM.render(
|
||||
<Mention
|
||||
style={{ width: 500, height: 100 }}
|
||||
style={{ width: '100%', height: 100 }}
|
||||
onChange={onChange}
|
||||
defaultValue={toEditorState('@afc163')}
|
||||
suggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
|
||||
|
||||
@@ -55,7 +55,7 @@ let App = React.createClass({
|
||||
<Form horizontal>
|
||||
<FormItem
|
||||
id="control-mention"
|
||||
label="Top programmers"
|
||||
label="Top coders"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 14 }}
|
||||
>
|
||||
|
||||
@@ -52,7 +52,7 @@ const CustomNavMention = React.createClass({
|
||||
return (
|
||||
<Mention
|
||||
placeholder="@someone"
|
||||
style={{ width: 500, height: 100 }}
|
||||
style={{ width: '100%', height: 100 }}
|
||||
suggestions={suggestions}
|
||||
onSearchChange={this.onSearchChange}
|
||||
onSelect={onSelect}
|
||||
|
||||
@@ -23,7 +23,7 @@ function onChange(editorState) {
|
||||
|
||||
ReactDOM.render(
|
||||
<Mention
|
||||
style={{ width: 500, height: 100 }}
|
||||
style={{ width: '100%', height: 100 }}
|
||||
onChange={onChange}
|
||||
suggestions={['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai']}
|
||||
multiLines
|
||||
|
||||
47
components/mention/demo/popupContainer.md
Normal file
47
components/mention/demo/popupContainer.md
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 建议渲染父节点
|
||||
en-US: SuggestionContainer
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
指定提示渲染的父节点。
|
||||
|
||||
## en-US
|
||||
|
||||
To set the container of the suggestion.
|
||||
|
||||
````jsx
|
||||
import { Mention, Popover, Button } from 'antd';
|
||||
const { toString, toEditorState } = Mention;
|
||||
|
||||
function onChange(editorState) {
|
||||
console.log(toString(editorState));
|
||||
}
|
||||
|
||||
function onSelect(suggestion) {
|
||||
console.log('onSelect', suggestion);
|
||||
}
|
||||
|
||||
const PopoverContainer = React.createClass({
|
||||
getSuggestionContainer() {
|
||||
return this.popover.getPopupDomNode();
|
||||
},
|
||||
render() {
|
||||
const mention = (<Mention
|
||||
style={{ width: '100%', height: 100 }}
|
||||
onChange={onChange}
|
||||
defaultValue={toEditorState('@afc163')}
|
||||
suggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
|
||||
onSelect={onSelect}
|
||||
getSuggestionContainer={this.getSuggestionContainer}
|
||||
/>);
|
||||
return (<Popover trigger="click" content={mention} title="Title" ref={popover => this.popover = popover}>
|
||||
<Button type="primary">Click Me</Button>
|
||||
</Popover>);
|
||||
},
|
||||
});
|
||||
ReactDOM.render(<PopoverContainer />, mountNode);
|
||||
````
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
category: Components
|
||||
cols: 1
|
||||
type: Views
|
||||
title: Mention
|
||||
---
|
||||
@@ -45,6 +44,7 @@ When need to mention someone or something.
|
||||
| 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 |
|
||||
| getSuggestionContainer | rendered to the root of the menu. Default rendered to the body dom. If gets any problem of the menu while scrolling. Try to make the root the dom scrolled, and make it position relative. | Function() | () => document.body |
|
||||
|
||||
### Nav props
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ export interface MentionProps {
|
||||
multiLines?: Boolean;
|
||||
prefix?: string;
|
||||
placeholder?: string;
|
||||
getSuggestionContainer?: Function;
|
||||
}
|
||||
|
||||
export interface MentionState {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 提及
|
||||
cols: 1
|
||||
type: Views
|
||||
title: Mention
|
||||
---
|
||||
@@ -45,6 +44,7 @@ title: Mention
|
||||
| placeHolder | 输入框默认文字 | string | null |
|
||||
| defaultValue | 默认值 | EditorState, 可以用 Mention.toEditorState(text) 把文字转换成 EditorState | null |
|
||||
| value | 值 | EditorState | null |
|
||||
| getSuggestionContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位| Function() | () => document.body |
|
||||
|
||||
### Nav props
|
||||
|
||||
|
||||
@@ -35,76 +35,77 @@
|
||||
height: auto;
|
||||
padding: 4px 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{ant-prefix}-mention-dropdown {
|
||||
margin-top: 1.5em;
|
||||
max-height: 250px;
|
||||
min-width: 120px;
|
||||
background-color: white;
|
||||
box-shadow: @box-shadow-base;
|
||||
border-radius: @border-radius-base;
|
||||
box-sizing: border-box;
|
||||
z-index: @zindex-dropdown;
|
||||
left: -9999px;
|
||||
top: -9999px;
|
||||
position: absolute;
|
||||
outline: none;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
font-size: @font-size-base;
|
||||
&-notfound.@{ant-prefix}-mention-dropdown-item {
|
||||
.@{ant-prefix}-mention-dropdown {
|
||||
margin-top: 1.5em;
|
||||
max-height: 250px;
|
||||
min-width: 120px;
|
||||
background-color: white;
|
||||
box-shadow: @box-shadow-base;
|
||||
border-radius: @border-radius-base;
|
||||
box-sizing: border-box;
|
||||
z-index: @zindex-dropdown;
|
||||
left: -9999px;
|
||||
top: -9999px;
|
||||
position: absolute;
|
||||
outline: none;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
font-size: @font-size-base;
|
||||
&-notfound.@{ant-prefix}-mention-dropdown-item {
|
||||
color: #ccc;
|
||||
|
||||
.@{iconfont-css-prefix}-loading {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
&-item {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 7px 16px;
|
||||
font-weight: normal;
|
||||
color: #666;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&:hover,
|
||||
&.focus,
|
||||
&-active {
|
||||
background-color: tint(@primary-color, 90%);
|
||||
}
|
||||
|
||||
&-disabled {
|
||||
color: #ccc;
|
||||
cursor: not-allowed;
|
||||
|
||||
.@{iconfont-css-prefix}-loading {
|
||||
color: @primary-color;
|
||||
&:hover {
|
||||
color: #ccc;
|
||||
background-color: #fff;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
&-item {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 7px 16px;
|
||||
font-weight: normal;
|
||||
color: #666;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&-selected {
|
||||
&,
|
||||
&:hover {
|
||||
background-color: @background-color-base;
|
||||
font-weight: bold;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
&-divider {
|
||||
height: 1px;
|
||||
margin: 1px 0;
|
||||
overflow: hidden;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&:hover,
|
||||
&.focus,
|
||||
&-active {
|
||||
background-color: tint(@primary-color, 90%);
|
||||
}
|
||||
|
||||
&-disabled {
|
||||
color: #ccc;
|
||||
cursor: not-allowed;
|
||||
|
||||
&:hover {
|
||||
color: #ccc;
|
||||
background-color: #fff;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
&-selected {
|
||||
&,
|
||||
&:hover {
|
||||
background-color: @background-color-base;
|
||||
font-weight: bold;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
&-divider {
|
||||
height: 1px;
|
||||
margin: 1px 0;
|
||||
overflow: hidden;
|
||||
background-color: #e5e5e5;
|
||||
line-height: 0;
|
||||
}
|
||||
background-color: #e5e5e5;
|
||||
line-height: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import RcMenu, { Item, Divider, SubMenu, ItemGroup } from 'rc-menu';
|
||||
import animation from '../_util/openAnimation';
|
||||
import warning from 'warning';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
export interface SelectParam {
|
||||
key: string;
|
||||
|
||||
@@ -14,11 +14,8 @@ getting feedback or information purposes.
|
||||
Additionally, if you need show a simple confirmation dialog, you can use `ant.Modal.confirm()`,
|
||||
and so on.
|
||||
|
||||
|
||||
|
||||
## API
|
||||
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|------------|----------------|------------------|--------------|
|
||||
| visible | Determine whether a modal dialog is visible or not | Boolean | no |
|
||||
|
||||
@@ -13,10 +13,8 @@ title: Modal
|
||||
|
||||
另外当需要一个简洁的确认框询问用户时,可以使用精心封装好的 `ant.Modal.confirm()` 等方法。
|
||||
|
||||
|
||||
## API
|
||||
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------------|----------------|------------------|--------------|
|
||||
| visible | 对话框是否可见 | Boolean | 无 |
|
||||
|
||||
@@ -113,14 +113,15 @@
|
||||
&-arrow {
|
||||
border-width: @popover-arrow-outer-width;
|
||||
}
|
||||
|
||||
&-arrow:after {
|
||||
border-width: @popover-arrow-width;
|
||||
content: "";
|
||||
}
|
||||
|
||||
&-placement-top &-arrow,
|
||||
&-placement-topLeft &-arrow,
|
||||
&-placement-topRight &-arrow {
|
||||
&-placement-top > &-content > &-arrow,
|
||||
&-placement-topLeft > &-content > &-arrow,
|
||||
&-placement-topRight > &-content > &-arrow {
|
||||
border-bottom-width: 0;
|
||||
border-top-color: @popover-arrow-outer-color;
|
||||
bottom: -1px;
|
||||
@@ -132,20 +133,20 @@
|
||||
border-top-color: @popover-arrow-color;
|
||||
}
|
||||
}
|
||||
&-placement-top &-arrow {
|
||||
&-placement-top > &-content > &-arrow {
|
||||
left: 50%;
|
||||
margin-left: -@popover-arrow-outer-width;
|
||||
}
|
||||
&-placement-topLeft &-arrow {
|
||||
&-placement-topLeft > &-content > &-arrow {
|
||||
left: 16px;
|
||||
}
|
||||
&-placement-topRight &-arrow {
|
||||
&-placement-topRight > &-content > &-arrow {
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
&-placement-right &-arrow,
|
||||
&-placement-rightTop &-arrow,
|
||||
&-placement-rightBottom &-arrow {
|
||||
&-placement-right > &-content > &-arrow,
|
||||
&-placement-rightTop > &-content > &-arrow,
|
||||
&-placement-rightBottom > &-content > &-arrow {
|
||||
left: -1px;
|
||||
border-left-width: 0;
|
||||
border-right-color: @popover-arrow-outer-color;
|
||||
@@ -157,20 +158,20 @@
|
||||
border-right-color: @popover-arrow-color;
|
||||
}
|
||||
}
|
||||
&-placement-right &-arrow {
|
||||
&-placement-right > &-content > &-arrow {
|
||||
top: 50%;
|
||||
margin-top: -@popover-arrow-outer-width;
|
||||
}
|
||||
&-placement-rightTop &-arrow {
|
||||
&-placement-rightTop > &-content > &-arrow {
|
||||
top: 12px;
|
||||
}
|
||||
&-placement-rightBottom &-arrow {
|
||||
&-placement-rightBottom > &-content > &-arrow {
|
||||
bottom: 12px;
|
||||
}
|
||||
|
||||
&-placement-bottom &-arrow,
|
||||
&-placement-bottomLeft &-arrow,
|
||||
&-placement-bottomRight &-arrow {
|
||||
&-placement-bottom > &-content > &-arrow,
|
||||
&-placement-bottomLeft > &-content > &-arrow,
|
||||
&-placement-bottomRight > &-content > &-arrow {
|
||||
border-top-width: 0;
|
||||
border-bottom-color: @popover-arrow-outer-color;
|
||||
top: -1px;
|
||||
@@ -182,20 +183,20 @@
|
||||
border-bottom-color: @popover-arrow-color;
|
||||
}
|
||||
}
|
||||
&-placement-bottom &-arrow {
|
||||
&-placement-bottom > &-content > &-arrow {
|
||||
left: 50%;
|
||||
margin-left: -@popover-arrow-outer-width;
|
||||
}
|
||||
&-placement-bottomLeft &-arrow {
|
||||
&-placement-bottomLeft > &-content > &-arrow {
|
||||
left: 16px;
|
||||
}
|
||||
&-placement-bottomRight &-arrow {
|
||||
&-placement-bottomRight > &-content > &-arrow {
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
&-placement-left &-arrow,
|
||||
&-placement-leftTop &-arrow,
|
||||
&-placement-leftBottom &-arrow {
|
||||
&-placement-left > &-content > &-arrow,
|
||||
&-placement-leftTop > &-content > &-arrow,
|
||||
&-placement-leftBottom > &-content > &-arrow {
|
||||
right: -1px;
|
||||
border-right-width: 0;
|
||||
border-left-color: @popover-arrow-outer-color;
|
||||
@@ -207,14 +208,14 @@
|
||||
bottom: -@popover-arrow-width;
|
||||
}
|
||||
}
|
||||
&-placement-left &-arrow {
|
||||
&-placement-left > &-content > &-arrow {
|
||||
top: 50%;
|
||||
margin-top: -@popover-arrow-outer-width;
|
||||
}
|
||||
&-placement-leftTop &-arrow {
|
||||
&-placement-leftTop > &-content > &-arrow {
|
||||
top: 12px;
|
||||
}
|
||||
&-placement-leftBottom &-arrow {
|
||||
&-placement-leftBottom > &-content > &-arrow {
|
||||
bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ function getCheckedValue(children) {
|
||||
}
|
||||
|
||||
export interface RadioGroupProps {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
/** 选项变化时的回调函数*/
|
||||
onChange?: React.FormEventHandler<any>;
|
||||
/** 用于设置当前选中的值*/
|
||||
@@ -27,7 +29,6 @@ export interface RadioGroupProps {
|
||||
/** 大小,只对按钮样式生效*/
|
||||
size?: 'large' | 'default' | 'small';
|
||||
style?: React.CSSProperties;
|
||||
prefixCls?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
@@ -81,7 +82,7 @@ export default class RadioGroup extends React.Component<RadioGroupProps, any> {
|
||||
}
|
||||
render() {
|
||||
const props = this.props;
|
||||
const children = React.Children.map((props.children || {}), (radio: any) => {
|
||||
const children = !props.children ? [] : React.Children.map(props.children, (radio: any) => {
|
||||
if (radio && (radio.type === Radio || radio.type === RadioButton) && radio.props) {
|
||||
const keyProps = {};
|
||||
if (!('key' in radio) && typeof radio.props.value === 'string') {
|
||||
@@ -95,10 +96,12 @@ export default class RadioGroup extends React.Component<RadioGroupProps, any> {
|
||||
}
|
||||
return radio;
|
||||
});
|
||||
const prefixCls = props.prefixCls || 'ant-radio-group';
|
||||
|
||||
const { prefixCls = 'ant-radio-group', className = '' } = props;
|
||||
const classString = classNames({
|
||||
[prefixCls]: true,
|
||||
[`${prefixCls}-${props.size}`]: props.size,
|
||||
[className]: className,
|
||||
});
|
||||
return <div className={classString} style={props.style}>{children}</div>;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
@radio-prefix-cls: ~"@{ant-prefix}-radio";
|
||||
@radio-group-prefix-cls: ~"@{radio-prefix-cls}-group";
|
||||
@radio-inner-prefix-cls: ~"@{radio-prefix-cls}-inner";
|
||||
@radio-duration: .2s;
|
||||
@radio-duration: .3s;
|
||||
|
||||
.@{radio-group-prefix-cls} {
|
||||
display: inline-block;
|
||||
@@ -19,6 +19,7 @@
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
margin-right: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.@{radio-prefix-cls} {
|
||||
@@ -29,10 +30,11 @@
|
||||
line-height: 1;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
.@{radio-prefix-cls}-wrapper:hover &,
|
||||
&:hover,
|
||||
&-focused {
|
||||
.@{radio-inner-prefix-cls} {
|
||||
border-color: #bcbcbc;
|
||||
border-color: #bbb;
|
||||
}
|
||||
}
|
||||
&-inner {
|
||||
@@ -64,7 +66,7 @@
|
||||
border-radius: 14px;
|
||||
border-color: @border-color-base;
|
||||
background-color: #fff;
|
||||
transition: all @radio-duration @ease-in-out-circ;
|
||||
transition: all @radio-duration;
|
||||
}
|
||||
|
||||
&-input {
|
||||
@@ -92,32 +94,23 @@
|
||||
}
|
||||
|
||||
.@{radio-prefix-cls}-disabled {
|
||||
&:hover {
|
||||
.@{radio-inner-prefix-cls} {
|
||||
border-color: @border-color-base;
|
||||
}
|
||||
}
|
||||
.@{radio-inner-prefix-cls} {
|
||||
border-color: @border-color-base;
|
||||
border-color: @border-color-base!important;
|
||||
background-color: #f3f3f3;
|
||||
&:after {
|
||||
background-color: #cccccc;
|
||||
}
|
||||
}
|
||||
|
||||
.@{radio-inner-prefix-cls}-input {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.@{radio-prefix-cls}-disabled + span {
|
||||
& + span {
|
||||
color: #ccc;
|
||||
cursor: @cursor-disabled;
|
||||
}
|
||||
}
|
||||
|
||||
span.@{radio-prefix-cls} + * {
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.@{radio-prefix-cls}-button-wrapper {
|
||||
|
||||
38
components/select/demo/automatic-tokenization.md
Normal file
38
components/select/demo/automatic-tokenization.md
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
order: 11
|
||||
title:
|
||||
zh-CN: 自动分词
|
||||
en-US: Automatic tokenization
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
试下复制`露西,杰克`到输入框里。只在 tags 和 multiple 模式下可用。
|
||||
|
||||
## en-US
|
||||
|
||||
Try to copy `Lucy,Jack` to the input. Only available in tags and multiple mode.
|
||||
|
||||
````jsx
|
||||
import { Select } from 'antd';
|
||||
const Option = Select.Option;
|
||||
|
||||
const children = [];
|
||||
for (let i = 10; i < 36; i++) {
|
||||
children.push(<Option key={i.toString(36) + i}>{i.toString(36) + i}</Option>);
|
||||
}
|
||||
|
||||
function handleChange(value) {
|
||||
console.log(`selected ${value}`);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<Select tags
|
||||
style={{ width: '100%' }}
|
||||
onChange={handleChange}
|
||||
tokenSeparators={[',']}
|
||||
>
|
||||
{children}
|
||||
</Select>
|
||||
, mountNode);
|
||||
````
|
||||
@@ -33,6 +33,8 @@ A Selector similar to Select2.
|
||||
| onDeselect | Called when a option is deselected. param is option's value. only called for multiple or tags, effective in multiple or tags mode only. | function(value) | - |
|
||||
| onChange | Called when select an option or input value change, or value of input is changed in combobox mode | function(value, label) | - |
|
||||
| onSearch | Callback function that is fired when input changed. | function(value: String) | |
|
||||
| onBlur | Called when blur | function | - |
|
||||
| onFocus | Called when focus | function | - |
|
||||
| placeholder | Placeholder of select | string | - |
|
||||
| notFoundContent | Specify content to show when no result matches..| string | 'Not Found' |
|
||||
| dropdownMatchSelectWidth | Whether dropdown's with is same with select. | boolean | true |
|
||||
@@ -46,6 +48,8 @@ A Selector similar to Select2.
|
||||
| dropdownClassName | className of dropdown menu | string | - |
|
||||
| getPopupContainer | Parent Node which the selector should be rendered to. Default to `body`. When position issues happen, try to modify it into scrollable content and position it relative.[example](http://codepen.io/anon/pen/xVBOVQ?editors=001) | function(triggerNode) | () => document.body |
|
||||
| labelInValue | whether to embed label in value | boolean | false |
|
||||
| tokenSeparators | Separator used to tokenize on tag/multiple mode | string[]? | |
|
||||
|
||||
|
||||
### Option props
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ title: Select
|
||||
| onDeselect | 取消选中时调用,参数为选中项的 option value 值,仅在 multiple 或 tags 模式下生效 | function(value) | 无 |
|
||||
| onChange | 选中 option,或 input 的 value 变化(combobox 模式下)时,调用此函数 | function(value) | 无 |
|
||||
| onSearch | 文本框值变化时回调 | function(value: String) | |
|
||||
| onBlur | 失去焦点的时回调 | function | - |
|
||||
| onFocus | 获得焦点时回调 | function | - |
|
||||
| placeholder | 选择框默认文字 | string | 无 |
|
||||
| notFoundContent | 当下拉列表为空时显示的内容 | string | 'Not Found' |
|
||||
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽 | boolean | true |
|
||||
@@ -48,6 +50,7 @@ title: Select
|
||||
| dropdownClassName | 下拉菜单的 className 属性 | string | - |
|
||||
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](http://codepen.io/anon/pen/xVBOVQ?editors=001) | Function(triggerNode) | () => document.body |
|
||||
| labelInValue | 是否把每个选项的 label 包装到 value 中,决定 Select 的 value 类型。 | boolean | false |
|
||||
| tokenSeparators | 在 tags 和 multiple 模式下自动分词的分隔符 | string[]? | |
|
||||
|
||||
### Option props
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { PropTypes } from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import classNames from 'classnames';
|
||||
import Animate from 'rc-animate';
|
||||
import isCssAnimationSupported from '../_util/isCssAnimationSupported';
|
||||
import splitObject from '../_util/splitObject';
|
||||
import omit from 'omit.js';
|
||||
@@ -67,7 +68,6 @@ export default class Spin extends React.Component<SpinProps, any> {
|
||||
this.setState({ spinning });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const [{
|
||||
className, size, prefixCls, tip,
|
||||
@@ -90,20 +90,33 @@ export default class Spin extends React.Component<SpinProps, any> {
|
||||
]);
|
||||
|
||||
const spinElement = (
|
||||
<div {...divProps} className={spinClassName}>
|
||||
<span className={`${prefixCls}-dot`} />
|
||||
<div {...divProps} className={spinClassName} >
|
||||
<span className={`${prefixCls}-dot`}>
|
||||
<i />
|
||||
<i />
|
||||
<i />
|
||||
<i />
|
||||
</span>
|
||||
{tip ? <div className={`${prefixCls}-text`}>{tip}</div> : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
if (this.isNestedPattern()) {
|
||||
const containerClassName = classNames({
|
||||
[`${prefixCls}-container`]: true,
|
||||
[`${prefixCls}-filter`]: spinning,
|
||||
});
|
||||
return (
|
||||
<div {...divProps} className={spinning ? (`${prefixCls}-nested-loading`) : ''}>
|
||||
{spinElement}
|
||||
<div className={`${prefixCls}-container`}>
|
||||
<Animate
|
||||
{...divProps}
|
||||
component="div"
|
||||
className={`${prefixCls}-nested-loading`}
|
||||
transitionName="fade"
|
||||
>
|
||||
{spinning && <div key="loading">{spinElement}</div>}
|
||||
<div className={containerClassName} key="container">
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
</Animate>
|
||||
);
|
||||
}
|
||||
return spinElement;
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
@spin-prefix-cls: ~"@{ant-prefix}-spin";
|
||||
@spin-dot-default: #999;
|
||||
@spin-dot-size-sm: 12px;
|
||||
@spin-dot-size-sm: 14px;
|
||||
@spin-dot-size: 20px;
|
||||
@spin-dot-size-lg: 32px;
|
||||
@spin-dot-size-lg: 30px;
|
||||
|
||||
.@{spin-prefix-cls} {
|
||||
color: @primary-color;
|
||||
@@ -71,17 +71,16 @@
|
||||
padding-top: (@spin-dot-size-lg - @font-size-base) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
&-container {
|
||||
transition: all 0.3s @ease-in-out-circ;
|
||||
transition: all 0.3s @ease-in-out;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&-nested-loading > &-container {
|
||||
&-filter {
|
||||
opacity: 0.7;
|
||||
-webkit-filter: blur(1px);
|
||||
filter: blur(1px);
|
||||
filter: ~"progid\:DXImageTransform\.Microsoft\.Blur(PixelRadius\=1, MakeShadow\=false)"; /* IE6~IE9 */
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@@ -106,22 +105,38 @@
|
||||
position: relative;
|
||||
display: block;
|
||||
.square(@spin-dot-size);
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
transform: rotate(45deg);
|
||||
animation: antRotate 3.2s infinite linear;
|
||||
i {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: @primary-color;
|
||||
animation: antSpinBounce 2.2s infinite ease-in-out;
|
||||
transform: scale(0.6);
|
||||
display: block;
|
||||
position: absolute;
|
||||
opacity: 0.5;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
&:after {
|
||||
animation-delay: -1.1s;
|
||||
opacity: 0.3;
|
||||
animation: antSpinMove .8s infinite linear alternate;
|
||||
transform-origin: 0 0;
|
||||
&:nth-child(1) {
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
right: 0;
|
||||
top: 0;
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
&:nth-child(4) {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,11 +145,19 @@
|
||||
// small
|
||||
&-sm &-dot {
|
||||
.square(@spin-dot-size-sm);
|
||||
i {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
// large
|
||||
&-lg &-dot {
|
||||
.square(@spin-dot-size-lg);
|
||||
i {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
&&-show-text &-text {
|
||||
@@ -142,16 +165,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSpinBounce {
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
|
||||
/* IE10+ */
|
||||
.@{ant-prefix}-spin-nested-loading > .@{ant-prefix}-spin-container {
|
||||
@@ -159,3 +172,16 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSpinMove {
|
||||
to {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antRotate {
|
||||
to {
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
|
||||
274
components/style/core/normalize.less
vendored
274
components/style/core/normalize.less
vendored
@@ -1,16 +1,25 @@
|
||||
/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */
|
||||
/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/**
|
||||
* 1. Change the default font family in all browsers (opinionated).
|
||||
* 2. Prevent adjustments of font size after orientation changes in IE and iOS.
|
||||
* 2. Correct the line height in all browsers.
|
||||
* 3. Prevent adjustments of font size after orientation changes in
|
||||
* IE on Windows Phone and in iOS.
|
||||
*/
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
line-height: 1.15; /* 2 */
|
||||
-ms-text-size-adjust: 100%; /* 3 */
|
||||
-webkit-text-size-adjust: 100%; /* 3 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers (opinionated).
|
||||
*/
|
||||
@@ -19,69 +28,73 @@ body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in Edge, IE, and Firefox.
|
||||
* 2. Add the correct display in IE.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details, /* 1 */
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
main, /* 2 */
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary { /* 1 */
|
||||
section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in iOS 4-7.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10-.
|
||||
* 1. Add the correct display in IE.
|
||||
*/
|
||||
|
||||
template, /* 1 */
|
||||
[hidden] {
|
||||
display: none;
|
||||
figcaption,
|
||||
figure,
|
||||
main { /* 1 */
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Links
|
||||
/**
|
||||
* Add the correct margin in IE 8.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
@@ -104,9 +117,6 @@ a:hover {
|
||||
outline-width: 0;
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Firefox 39-.
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
@@ -136,6 +146,18 @@ strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font style in Android 4.3-.
|
||||
*/
|
||||
@@ -144,16 +166,6 @@ dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct background and color in IE 9-.
|
||||
*/
|
||||
@@ -195,6 +207,24 @@ sup {
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
audio,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in iOS 4-7.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10-.
|
||||
*/
|
||||
@@ -211,65 +241,25 @@ svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct margin in IE 8.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change font properties to `inherit` in all browsers (opinionated).
|
||||
* 1. Change the font styles in all browsers (opinionated).
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font: inherit; /* 1 */
|
||||
font-family: sans-serif; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the font weight unset by the previous rule.
|
||||
*/
|
||||
|
||||
optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
@@ -352,6 +342,16 @@ legend {
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct display in IE 9-.
|
||||
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE.
|
||||
*/
|
||||
@@ -391,7 +391,7 @@ textarea {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding and cancel buttons in Chrome and Safari on OS X.
|
||||
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
@@ -399,15 +399,6 @@ textarea {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the text style of placeholders in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
::-webkit-input-placeholder {
|
||||
color: inherit;
|
||||
opacity: 0.54;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
@@ -417,3 +408,54 @@ textarea {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in Edge, IE, and Firefox.
|
||||
*/
|
||||
|
||||
details, /* 1 */
|
||||
menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Scripting
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
canvas {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hidden
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10-.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
// ICONFONT
|
||||
@iconfont-css-prefix : anticon;
|
||||
@icon-url : "https://at.alicdn.com/t/font_pldm8phsjkathuxr";
|
||||
@icon-url : "https://at.alicdn.com/t/font_uzv8nkw1nabgldi";
|
||||
|
||||
// LINK
|
||||
@link-color : #2db7f5;
|
||||
|
||||
@@ -10,7 +10,7 @@ import classNames from 'classnames';
|
||||
import { flatArray, treeMap } from './util';
|
||||
import assign from 'object-assign';
|
||||
import splitObject from '../_util/splitObject';
|
||||
import warning from 'warning';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
function noop() {
|
||||
}
|
||||
|
||||
156
components/table/demo/dynamic-settings.md
Normal file
156
components/table/demo/dynamic-settings.md
Normal file
@@ -0,0 +1,156 @@
|
||||
---
|
||||
order: 21
|
||||
title:
|
||||
en-US: Dynamic Settings
|
||||
zh-CN: 动态控制表格属性
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
选择不同配置组合查看效果。
|
||||
|
||||
## en-US
|
||||
|
||||
Select different settings to see the result.
|
||||
|
||||
````jsx
|
||||
import { Table, Icon, Switch, Radio, Form } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
render: text => <a href="#">{text}</a>,
|
||||
}, {
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
}, {
|
||||
title: 'Action',
|
||||
key: 'action',
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
<a href="#">Action 一 {record.name}</a>
|
||||
<span className="ant-divider" />
|
||||
<a href="#">Delete</a>
|
||||
<span className="ant-divider" />
|
||||
<a href="#" className="ant-dropdown-link">
|
||||
More actions<Icon type="down" />
|
||||
</a>
|
||||
</span>
|
||||
),
|
||||
}];
|
||||
|
||||
const data = [{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
age: 32,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.',
|
||||
}, {
|
||||
key: '2',
|
||||
name: 'Jim Green',
|
||||
age: 42,
|
||||
address: 'London No. 1 Lake Park',
|
||||
description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.',
|
||||
}, {
|
||||
key: '3',
|
||||
name: 'Joe Black',
|
||||
age: 32,
|
||||
address: 'Sidney No. 1 Lake Park',
|
||||
description: 'My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park.',
|
||||
}];
|
||||
|
||||
const expandedRowRender = record => <p>{record.description}</p>;
|
||||
const title = () => 'Here is title';
|
||||
const footer = () => 'Here is footer';
|
||||
|
||||
class Demo extends React.Component {
|
||||
state = {
|
||||
bordered: true,
|
||||
loading: false,
|
||||
pagination: true,
|
||||
size: 'default',
|
||||
expandedRowRender,
|
||||
title,
|
||||
footer,
|
||||
}
|
||||
|
||||
handleToggle = (prop) => {
|
||||
return (enable) => {
|
||||
this.setState({ [prop]: enable });
|
||||
};
|
||||
}
|
||||
|
||||
handleSizeChange = (e) => {
|
||||
this.setState({ size: e.target.value });
|
||||
}
|
||||
|
||||
handleExpandChange = (enable) => {
|
||||
this.setState({ expandedRowRender: enable ? expandedRowRender : false });
|
||||
}
|
||||
|
||||
handleTitleChange = (enable) => {
|
||||
this.setState({ title: enable ? title : undefined });
|
||||
}
|
||||
|
||||
handleFooterChange = (enable) => {
|
||||
this.setState({ footer: enable ? footer : undefined });
|
||||
}
|
||||
|
||||
render() {
|
||||
const state = this.state;
|
||||
return (
|
||||
<div>
|
||||
<div className="components-table-demo-control-bar">
|
||||
<Form inline>
|
||||
<FormItem label="Bordered">
|
||||
<Switch checked={state.bordered} onChange={this.handleToggle('bordered')} />
|
||||
</FormItem>
|
||||
<FormItem label="loading">
|
||||
<Switch checked={state.loading} onChange={this.handleToggle('loading')} />
|
||||
</FormItem>
|
||||
<FormItem label="Pagination">
|
||||
<Switch checked={state.pagination} onChange={this.handleToggle('pagination')} />
|
||||
</FormItem>
|
||||
<FormItem label="Title">
|
||||
<Switch defaultChecked onChange={this.handleTitleChange} />
|
||||
</FormItem>
|
||||
<FormItem label="Footer">
|
||||
<Switch defaultChecked onChange={this.handleFooterChange} />
|
||||
</FormItem>
|
||||
<FormItem label="Expandable">
|
||||
<Switch defaultChecked onChange={this.handleExpandChange} />
|
||||
</FormItem>
|
||||
<FormItem label="Size">
|
||||
<Radio.Group value={state.size} onChange={this.handleSizeChange}>
|
||||
<Radio.Button value="default">Default</Radio.Button>
|
||||
<Radio.Button value="middle">Middle</Radio.Button>
|
||||
<Radio.Button value="small">Small</Radio.Button>
|
||||
</Radio.Group>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<Table {...this.state} columns={columns} dataSource={data} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
````
|
||||
|
||||
<style>
|
||||
.components-table-demo-control-bar {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.components-table-demo-control-bar .ant-form-item {
|
||||
margin-right: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,68 +0,0 @@
|
||||
---
|
||||
order: 14
|
||||
title:
|
||||
en-US: Loading
|
||||
zh-CN: 加载中的表格
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
用属性 `loading` 控制表格加载中状态。
|
||||
|
||||
## en-US
|
||||
|
||||
Controll loading states by `loading` property.
|
||||
|
||||
````jsx
|
||||
import { Table, Button } from 'antd';
|
||||
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
}, {
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
}];
|
||||
const data = [{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
age: 32,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
}, {
|
||||
key: '2',
|
||||
name: 'Jim Green',
|
||||
age: 42,
|
||||
address: 'London No. 1 Lake Park',
|
||||
}, {
|
||||
key: '3',
|
||||
name: 'Joe Black',
|
||||
age: 32,
|
||||
address: 'Sidney No. 1 Lake Park',
|
||||
}];
|
||||
|
||||
const App = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
toggleLoading() {
|
||||
this.setState({
|
||||
loading: !this.state.loading,
|
||||
});
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={data} loading={this.state.loading} />
|
||||
<Button type="primary" onClick={this.toggleLoading}>Switch loading state</Button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
````
|
||||
@@ -11,7 +11,7 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
Rows can be selectable by making fisrt column as a selectable column.
|
||||
Rows can be selectable by making first column as a selectable column.
|
||||
|
||||
````jsx
|
||||
import { Table } from 'antd';
|
||||
|
||||
@@ -53,7 +53,7 @@ const columns = [{
|
||||
| Property | Description | Type | Default |
|
||||
|---------------|--------------------------|-----------------|--------------|
|
||||
| rowSelection | row selection [config](#rowSelection) | Object | null |
|
||||
| pagination | pagination [config](/components/pagination), hide it via setting to `false` | Object | |
|
||||
| pagination | pagination [config](/components/pagination/), hide it via setting to `false` | Object | |
|
||||
| size | size of table: `default` or `small` | String | `default` |
|
||||
| dataSource | data record array to be rendered | Array | |
|
||||
| columns | columns of table | Array | - |
|
||||
|
||||
@@ -24,7 +24,6 @@ export interface TabsProps {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
animated?: boolean;
|
||||
children: any;
|
||||
}
|
||||
|
||||
// Tabs
|
||||
@@ -94,7 +93,7 @@ export default class Tabs extends React.Component<TabsProps, any> {
|
||||
let childrenWithClose;
|
||||
if (type === 'editable-card') {
|
||||
childrenWithClose = [];
|
||||
React.Children.forEach(children, (child: React.ReactElement<any>, index) => {
|
||||
React.Children.forEach(children as React.ReactNode, (child: React.ReactElement<any>, index) => {
|
||||
childrenWithClose.push(cloneElement(child, {
|
||||
tab: (
|
||||
<div>
|
||||
|
||||
@@ -200,6 +200,8 @@
|
||||
.@{tab-prefix-cls}-tabpane {
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
transition: opacity 0.3s;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.@{tab-prefix-cls}-tabpane-inactive {
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 各种类型
|
||||
en-US: Colorful tags
|
||||
debug: true
|
||||
order: -1
|
||||
title: Colorful Tags for Debugging
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
四种颜色的标签。
|
||||
|
||||
## en-US
|
||||
Colorful tags.
|
||||
`Tag[color]` is deprecated, but we need this demo for debugging until next major version.
|
||||
|
||||
````jsx
|
||||
import { Tag } from 'antd';
|
||||
|
||||
ReactDOM.render(<div>
|
||||
<Tag closable color="blue">Blue</Tag>
|
||||
<Tag closable color="green">Green</Tag>
|
||||
<Tag closable color="yellow"><a href="https://github.com/ant-design/ant-design/issues/1862">Yellow</a></Tag>
|
||||
<Tag closable color="red">Red</Tag>
|
||||
</div>, mountNode);
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Tag closable color="blue">Blue</Tag>
|
||||
<Tag closable color="green">Green</Tag>
|
||||
<Tag closable color="yellow"><a href="https://github.com/ant-design/ant-design/issues/1862">Yellow</a></Tag>
|
||||
<Tag closable color="red">Red</Tag>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 2
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 动态添加和删除
|
||||
en-US: Dynamically add and remove
|
||||
|
||||
@@ -19,4 +19,3 @@ Tag for categorizing or markuping.
|
||||
| closable | Tag can be closed. | boolean | false |
|
||||
| onClose | Callback when tag was closed | function(event)| - |
|
||||
| afterClose | Callback when closed animation is complete | function(event)| - |
|
||||
| color | Tag's color: `blue` `green` `yellow` `red` | string | - |
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Animate from 'rc-animate';
|
||||
import Icon from '../icon';
|
||||
import classNames from 'classnames';
|
||||
import splitObject from '../_util/splitObject';
|
||||
import omit from 'omit.js';
|
||||
import Icon from '../icon';
|
||||
import warning from '../_util/warning';
|
||||
import splitObject from '../_util/splitObject';
|
||||
|
||||
export interface TagProps {
|
||||
/** 标签是否可以关闭 */
|
||||
@@ -13,8 +14,6 @@ export interface TagProps {
|
||||
onClose?: Function;
|
||||
/** 动画关闭后的回调 */
|
||||
afterClose?: Function;
|
||||
/** 标签的色彩 */
|
||||
color?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
@@ -26,6 +25,7 @@ export default class Tag extends React.Component<TagProps, any> {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
warning(!('color' in props), '`Tag[color]` is deprecated, please override color by CSS instead.');
|
||||
|
||||
this.state = {
|
||||
closing: false,
|
||||
|
||||
@@ -19,4 +19,3 @@ title: Tag
|
||||
| closable | 标签是否可以关闭 | boolean | false |
|
||||
| onClose | 关闭时的回调 | function(event) | - |
|
||||
| afterClose | 关闭动画完成后的回调 | function(event) | - |
|
||||
| color | 标签的色彩:`blue` `green` `yellow` `red` | string | - |
|
||||
|
||||
29
components/time-picker/demo/addon.md
Normal file
29
components/time-picker/demo/addon.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 附加内容
|
||||
en-US: Addon
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
在 TimePicker 选择框底部显示自定义的内容。
|
||||
|
||||
## en-US
|
||||
|
||||
Render addon contents to timepicker panel's bottom.
|
||||
|
||||
|
||||
````jsx
|
||||
import { TimePicker, Button } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<TimePicker
|
||||
addon={panel => (
|
||||
<Button size="small" type="primary" onClick={() => panel.close()}>
|
||||
Ok
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
, mountNode);
|
||||
````
|
||||
@@ -34,5 +34,6 @@ import moment from 'moment';
|
||||
| disabledSeconds | to specify the seconds that cannot be selected | function(selectedHour, selectedMinute) | - |
|
||||
| hideDisabledOptions | hide the options that can not be selected | boolean | false |
|
||||
| getPopupContainer | to set the container of the floating layer, while the default is to create a div element in body | function(trigger) | - |
|
||||
| addon | called from timepicker panel to render some addon to its bottom | function | 无 |
|
||||
|
||||
<style>.code-box-demo .ant-time-picker { margin: 0 8px 12px 0; }</style>
|
||||
|
||||
@@ -29,9 +29,9 @@ export interface TimePickerProps {
|
||||
disabledMinutes?: Function;
|
||||
/** 禁止选择部分秒选项 */
|
||||
disabledSeconds?: Function;
|
||||
|
||||
style?: React.CSSProperties;
|
||||
getPopupContainer?: (trigger: any) => any;
|
||||
addon?: Function;
|
||||
}
|
||||
|
||||
export interface TimePickerContext {
|
||||
@@ -109,6 +109,11 @@ export default class TimePicker extends React.Component<TimePickerProps, any> {
|
||||
showHour={props.format.indexOf('HH') > -1}
|
||||
showSecond={props.format.indexOf('ss') > -1}
|
||||
onChange={this.handleChange}
|
||||
addon={(panel) => (
|
||||
props.addon ? <div className={`${props.prefixCls}-panel-addon`}>
|
||||
{props.addon(panel)}
|
||||
</div> : null
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,5 +35,6 @@ import moment from 'moment';
|
||||
| disabledSeconds | 禁止选择部分秒选项 | function(selectedHour, selectedMinute) | 无 |
|
||||
| hideDisabledOptions | 隐藏禁止选择的选项 | boolean | false |
|
||||
| getPopupContainer | 定义浮层的容器,默认为 body 上新建 div | function(trigger) | 无 |
|
||||
| addon | 选择框底部显示自定义的内容 | function | 无 |
|
||||
|
||||
<style>.code-box-demo .ant-time-picker { margin: 0 8px 12px 0; }</style>
|
||||
|
||||
@@ -80,9 +80,7 @@
|
||||
&-select {
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
border: 1px solid @border-color-split;
|
||||
border-width: 0 1px;
|
||||
margin-left: -1px;
|
||||
border-left: 1px solid @border-color-split;
|
||||
box-sizing: border-box;
|
||||
width: 56px;
|
||||
overflow: hidden;
|
||||
@@ -148,6 +146,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-combobox {
|
||||
.clearfix;
|
||||
}
|
||||
|
||||
&-addon {
|
||||
padding: 8px;
|
||||
border-top: 1px solid @border-color-split;
|
||||
}
|
||||
|
||||
&.slide-up-enter.slide-up-enter-active&-placement-topLeft,
|
||||
&.slide-up-enter.slide-up-enter-active&-placement-topRight,
|
||||
&.slide-up-appear.slide-up-appear-active&-placement-topLeft,
|
||||
|
||||
64
components/transfer/demo/large-data.md
Normal file
64
components/transfer/demo/large-data.md
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
order: 4
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 大数据性能测试
|
||||
en-US: Performance Test
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
2000 条数据。
|
||||
|
||||
## en-US
|
||||
|
||||
2000 items.
|
||||
|
||||
````jsx
|
||||
import { Transfer } from 'antd';
|
||||
|
||||
const App = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
mockData: [],
|
||||
targetKeys: [],
|
||||
};
|
||||
},
|
||||
componentDidMount() {
|
||||
this.getMock();
|
||||
},
|
||||
getMock() {
|
||||
const targetKeys = [];
|
||||
const mockData = [];
|
||||
for (let i = 0; i < 2000; i++) {
|
||||
const data = {
|
||||
key: i.toString(),
|
||||
title: `content${i + 1}`,
|
||||
description: `description of content${i + 1}`,
|
||||
chosen: Math.random() * 2 > 1,
|
||||
};
|
||||
if (data.chosen) {
|
||||
targetKeys.push(data.key);
|
||||
}
|
||||
mockData.push(data);
|
||||
}
|
||||
this.setState({ mockData, targetKeys });
|
||||
},
|
||||
handleChange(targetKeys, direction, moveKeys) {
|
||||
console.log(targetKeys, direction, moveKeys);
|
||||
this.setState({ targetKeys });
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Transfer
|
||||
dataSource={this.state.mockData}
|
||||
targetKeys={this.state.targetKeys}
|
||||
onChange={this.handleChange}
|
||||
render={item => item.title}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
````
|
||||
@@ -15,7 +15,6 @@ To transfer the elements between two columns in an intuitive and efficient way.
|
||||
|
||||
## API
|
||||
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|-----------|------------------------------------------|------------|--------|
|
||||
| dataSource | Used for setting the source data. The elements that are part of this array will be present the left column. Except the elements whose keys are included in `targetKeys` prop. | Array | [] |
|
||||
@@ -31,11 +30,11 @@ To transfer the elements between two columns in an intuitive and efficient way.
|
||||
| searchPlaceholder | The hint text of the search box. | String | 'Search here' |
|
||||
| notFoundContent | Text to display when a column is empty. | React.node | 'The list is empty' |
|
||||
| footer | A function used for rendering the footer. | Function(props) | |
|
||||
|
||||
| lazy | property of [react-lazy-load](https://github.com/loktar00/react-lazy-load) for lazy rendering items | Object | `{ height: 32, offset: 32 }` |
|
||||
|
||||
## Warning
|
||||
|
||||
According the [standard](http://facebook.github.io/react/docs/multiple-components.html#dynamic-children) of React, the key should always be supplied directly to the elements in the array. In Transfer, the keys should be set on the elements included in `dataSource` array. By default, `key` property is used as an unique identifier.
|
||||
According the [standard](http://facebook.github.io/react/docs/multiple-components.html#dynamic-children) of React, the key should always be supplied directly to the elements in the array. In Transfer, the keys should be set on the elements included in `dataSource` array. By default, `key` property is used as an unique identifier.
|
||||
|
||||
If there's no `key` in your data, you should use `rowKey` to specify the key that will be used for uniquely identify each element.
|
||||
```jsx
|
||||
|
||||
@@ -35,6 +35,7 @@ export interface TransferProps {
|
||||
filterOption: (inputValue: any, item: any) => boolean;
|
||||
body?: (props: any) => any;
|
||||
rowKey?: (record: any) => string;
|
||||
lazy?: {};
|
||||
}
|
||||
|
||||
export interface TransferContext {
|
||||
@@ -73,6 +74,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
body: PropTypes.func,
|
||||
footer: PropTypes.func,
|
||||
rowKey: PropTypes.func,
|
||||
lazy: PropTypes.object,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
@@ -255,7 +257,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
const {
|
||||
prefixCls = 'ant-transfer', operations = [], showSearch, notFoundContent,
|
||||
searchPlaceholder, body, footer, listStyle, className = '',
|
||||
filterOption, render,
|
||||
filterOption, render, lazy,
|
||||
} = this.props;
|
||||
const { leftFilter, rightFilter, leftCheckedKeys, rightCheckedKeys } = this.state;
|
||||
|
||||
@@ -271,7 +273,8 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
const titles = this.getTitles();
|
||||
return (
|
||||
<div className={cls}>
|
||||
<List titleText={titles[0]}
|
||||
<List
|
||||
titleText={titles[0]}
|
||||
dataSource={leftDataSource}
|
||||
filter={leftFilter}
|
||||
filterOption={filterOption}
|
||||
@@ -288,8 +291,10 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
body={body}
|
||||
footer={footer}
|
||||
prefixCls={`${prefixCls}-list`}
|
||||
lazy={lazy}
|
||||
/>
|
||||
<Operation rightActive={rightActive}
|
||||
<Operation
|
||||
rightActive={rightActive}
|
||||
rightArrowText={operations[0]}
|
||||
moveToRight={this.moveToRight}
|
||||
leftActive={leftActive}
|
||||
@@ -297,7 +302,8 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
moveToLeft={this.moveToLeft}
|
||||
className={`${prefixCls}-operation`}
|
||||
/>
|
||||
<List titleText={titles[1]}
|
||||
<List
|
||||
titleText={titles[1]}
|
||||
dataSource={rightDataSource}
|
||||
filter={rightFilter}
|
||||
filterOption={filterOption}
|
||||
@@ -314,6 +320,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
body={body}
|
||||
footer={footer}
|
||||
prefixCls={`${prefixCls}-list`}
|
||||
lazy={lazy}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -16,7 +16,6 @@ title: Transfer
|
||||
|
||||
## API
|
||||
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|-----------|------------------------------------------|------------|--------|
|
||||
| dataSource | 数据源,其中的数据将会被渲染到左边一栏中,`targetKeys` 中指定的除外。 | Array | [] |
|
||||
@@ -33,13 +32,14 @@ title: Transfer
|
||||
| searchPlaceholder | 搜索框的默认值 | String | '请输入搜索内容' |
|
||||
| notFoundContent | 当列表为空时显示的内容 | React.node | '列表为空' |
|
||||
| footer | 底部渲染函数 | Function(props) | |
|
||||
|
||||
| lazy | Transfer 使用了 [react-lazy-load](https://github.com/loktar00/react-lazy-load) 优化性能,这里可以设置相关参数 | Object | `{ height: 32, offset: 32 }` |
|
||||
|
||||
## 注意
|
||||
|
||||
按照 React 的[规范](http://facebook.github.io/react/docs/multiple-components.html#dynamic-children),所有的组件数组必须绑定 key。在 Transfer 中,`dataSource`里的数据值需要指定 `key` 值。对于 `dataSource` 默认将每列数据的 `key` 属性作为唯一的标识。
|
||||
|
||||
如果你的数据没有这个属性,务必使用 `rowKey` 来指定数据列的主键。
|
||||
|
||||
```jsx
|
||||
// 比如你的数据主键是 uid
|
||||
return <Transfer rowKey={record => record.uid} />;
|
||||
|
||||
66
components/transfer/item.tsx
Normal file
66
components/transfer/item.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import PureRenderMixin from 'rc-util/lib/PureRenderMixin';
|
||||
import assign from 'object-assign';
|
||||
import Lazyload from 'react-lazy-load';
|
||||
import Checkbox from '../checkbox';
|
||||
|
||||
function isRenderResultPlainObject(result) {
|
||||
return result && !React.isValidElement(result) &&
|
||||
Object.prototype.toString.call(result) === '[object Object]';
|
||||
}
|
||||
|
||||
export default class Item extends React.Component<any, any> {
|
||||
shouldComponentUpdate(...args) {
|
||||
return PureRenderMixin.shouldComponentUpdate.apply(this, args);
|
||||
}
|
||||
matchFilter = (text) => {
|
||||
const { filter, filterOption, item } = this.props;
|
||||
if (filterOption) {
|
||||
return filterOption(filter, item);
|
||||
}
|
||||
return text.indexOf(filter) >= 0;
|
||||
}
|
||||
render() {
|
||||
const { render, filter, item, lazy, checked, prefixCls, onClick } = this.props;
|
||||
const renderResult = render(item);
|
||||
let renderedText;
|
||||
let renderedEl;
|
||||
if (isRenderResultPlainObject(renderResult)) {
|
||||
renderedText = renderResult.value;
|
||||
renderedEl = renderResult.label;
|
||||
} else {
|
||||
renderedText = renderResult;
|
||||
renderedEl = renderResult;
|
||||
}
|
||||
|
||||
if (filter && filter.trim() && !this.matchFilter(renderedText)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const className = classNames({
|
||||
[`${prefixCls}-content-item`]: true,
|
||||
[`${prefixCls}-content-item-disabled`]: item.disabled,
|
||||
});
|
||||
|
||||
const lazyProps = assign({
|
||||
height: 32,
|
||||
offset: 500,
|
||||
throttle: 0,
|
||||
debounce: false,
|
||||
}, lazy);
|
||||
|
||||
return (
|
||||
<Lazyload {...lazyProps}>
|
||||
<li
|
||||
className={className}
|
||||
title={renderedText}
|
||||
onClick={item.disabled ? undefined : () => onClick(item)}
|
||||
>
|
||||
<Checkbox checked={checked} disabled={item.disabled} />
|
||||
<span>{renderedEl}</span>
|
||||
</li>
|
||||
</Lazyload>
|
||||
);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user