mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-09 10:59:19 +08:00
Compare commits
195 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5400cacd13 | ||
|
|
ee8ac670b9 | ||
|
|
449db1499b | ||
|
|
b0c7a714ad | ||
|
|
8457267dad | ||
|
|
24bd14d843 | ||
|
|
f93e2a8df0 | ||
|
|
3c9ccccf61 | ||
|
|
27232a8561 | ||
|
|
26c5c8e11c | ||
|
|
7dc0328c60 | ||
|
|
f703e00c0f | ||
|
|
f206cc4c90 | ||
|
|
c073e78074 | ||
|
|
ad808953fd | ||
|
|
ae8f3c5b56 | ||
|
|
88d428bcc4 | ||
|
|
7879421ec2 | ||
|
|
d4b5b701bd | ||
|
|
926425d8ec | ||
|
|
0e6ac6bc4c | ||
|
|
be9ed0388c | ||
|
|
d6288e5994 | ||
|
|
524a421d72 | ||
|
|
4da0ae4f42 | ||
|
|
02422417d6 | ||
|
|
01f5b61982 | ||
|
|
e7cf2a4f3f | ||
|
|
ed7d82f4cd | ||
|
|
8fa50cfddc | ||
|
|
751b597df1 | ||
|
|
850e713e7f | ||
|
|
e64f04cee5 | ||
|
|
8dcdd12bef | ||
|
|
cbec9c5db1 | ||
|
|
9cc05c530b | ||
|
|
b75201485d | ||
|
|
88d470220b | ||
|
|
51dae474cc | ||
|
|
5d2a2cc39b | ||
|
|
64e549be9d | ||
|
|
19be7db53f | ||
|
|
563f8120cd | ||
|
|
1903990315 | ||
|
|
733a4cdc40 | ||
|
|
45d2182137 | ||
|
|
0fa41ebfb9 | ||
|
|
451ef78778 | ||
|
|
d0f2ff83b6 | ||
|
|
9afec1a638 | ||
|
|
5aafe0d8de | ||
|
|
df4509bbda | ||
|
|
156242053f | ||
|
|
5c29fe41f7 | ||
|
|
db68af8e72 | ||
|
|
c04707d3e3 | ||
|
|
c32256c204 | ||
|
|
228b7328d3 | ||
|
|
3b08a6479c | ||
|
|
0baef0627e | ||
|
|
74932b5de9 | ||
|
|
ec3f20936e | ||
|
|
2df6476572 | ||
|
|
4d2bdfd93d | ||
|
|
a91a7208a6 | ||
|
|
2d0f532f73 | ||
|
|
0d013be7fa | ||
|
|
5aea5b24ef | ||
|
|
0ec4276eab | ||
|
|
4844d92709 | ||
|
|
e4974ac72a | ||
|
|
0a48c62dcb | ||
|
|
9b81fe86d9 | ||
|
|
64899c5da2 | ||
|
|
a7b384112e | ||
|
|
5782253a0f | ||
|
|
c72612435e | ||
|
|
8dd48e0e26 | ||
|
|
6bf9ac4e04 | ||
|
|
f98005a696 | ||
|
|
e6dd9a93d0 | ||
|
|
985d20ad80 | ||
|
|
6c16d738ee | ||
|
|
b9cba392c9 | ||
|
|
8f01552e0f | ||
|
|
b9863f044c | ||
|
|
0acbba9838 | ||
|
|
1fde7de404 | ||
|
|
52e649a9fb | ||
|
|
6d91290f95 | ||
|
|
7042e09a99 | ||
|
|
7af9a01a40 | ||
|
|
b39d96ec75 | ||
|
|
449a982f92 | ||
|
|
446315faf4 | ||
|
|
9360c02129 | ||
|
|
d8ea555ee8 | ||
|
|
e02d77b3df | ||
|
|
a3962d5869 | ||
|
|
03b4edee4a | ||
|
|
1e95ad9bad | ||
|
|
b08dd6d1f9 | ||
|
|
224281f425 | ||
|
|
8895776fad | ||
|
|
ebe2379a95 | ||
|
|
b64ea0edcc | ||
|
|
7f422c9e18 | ||
|
|
ba9949adcc | ||
|
|
af2cec65c5 | ||
|
|
63a15f0d92 | ||
|
|
d9dd3114c3 | ||
|
|
caf09cd99e | ||
|
|
e4b35e02d2 | ||
|
|
d3788034e5 | ||
|
|
d4e13e7616 | ||
|
|
952f8aabbc | ||
|
|
5cebea6b47 | ||
|
|
954c3a13f1 | ||
|
|
afb49f95d0 | ||
|
|
e253cce993 | ||
|
|
7373ce0758 | ||
|
|
6a1b1476be | ||
|
|
45b8a9b507 | ||
|
|
894a4ceb53 | ||
|
|
33a30ae927 | ||
|
|
7f974877bc | ||
|
|
ad88118373 | ||
|
|
b6f9ac4058 | ||
|
|
0a0e14d610 | ||
|
|
616ecf1980 | ||
|
|
ef720db420 | ||
|
|
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 |
@@ -39,6 +39,7 @@ const eslintrc = {
|
||||
'jsx-a11y/no-static-element-interactions': 0,
|
||||
'jsx-a11y/anchor-has-content': 0,
|
||||
'react/no-danger': 0,
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"newlineAfterBlock": false,
|
||||
"maxCharPerLine": false,
|
||||
"excludedFiles": [
|
||||
"components/layout/style/mixin.less",
|
||||
"components/grid/style/mixin.less",
|
||||
"components/style/core/base.less",
|
||||
"components/style/core/iconfont.less",
|
||||
"components/style/core/normalize.less",
|
||||
|
||||
@@ -9,6 +9,98 @@ If you want to read change logs before `2.0.0`, please visit [GitHub](https://gi
|
||||
|
||||
---
|
||||
|
||||
## 2.4.2
|
||||
|
||||
`2016-11-13`
|
||||
|
||||
* Fix `Dropdown.Button` cannot popup menu.[#3815](https://github.com/ant-design/ant-design/issues/3815)
|
||||
|
||||
## 2.4.1
|
||||
|
||||
`2016-11-11`
|
||||
|
||||
* Fix `2.4.0` missing index files.
|
||||
|
||||
## 2.4.0
|
||||
|
||||
`2016-11-11`
|
||||
|
||||
* Adjust components structure.
|
||||
* New [Anchor](https://ant.design/components/anchor) Component.
|
||||
* Fix less variables `@font-size-base` and `@text-color`, add `@font-size-lg` `@text-color-secondary`.
|
||||
* Add new props `selectedKeys` for `Transfer` component [#3729]. (https://github.com/ant-design/ant-design/issues/3729)
|
||||
* Add `Tag` selected status.
|
||||
* Fix `Dropdown.Button` not support `visible` and `onVisibleChange`. [#3779](https://github.com/ant-design/ant-design/issues/3779)
|
||||
* Fix `Now` button of `DatePicker[showTime]`. [#3748](https://github.com/ant-design/ant-design/issues/3748)
|
||||
* Fix style of `Steps` in vertical mode. [#3760](https://github.com/ant-design/ant-design/issues/3760)
|
||||
* Fix style compatibility of `Spin` in IE10+.[#3755](https://github.com/ant-design/ant-design/issues/3755)
|
||||
* Fix default style of `Carousel` component.
|
||||
* Fix focus logic of `Mention` component. [#3801](https://github.com/ant-design/ant-design/issues/3801)
|
||||
* Fix animate bug of `Progress` component. [#3784](https://github.com/ant-design/ant-design/issues/3784)
|
||||
* Fix focus bug of `Select` component. [#3778](https://github.com/ant-design/ant-design/issues/3778)
|
||||
* Fix `TimePicker` not support `format="HH"` bug. [#3793](https://github.com/ant-design/ant-design/issues/3793)
|
||||
* Improve perfermance of `Table` selection. [#3757](https://github.com/ant-design/ant-design/pull/3757)
|
||||
* Improve Carousel default UI style.
|
||||
* Improve style of `Checkbox` and `Radio`. [#3590](https://github.com/ant-design/ant-design/issues/3590)
|
||||
* Fix style of DatePickek, Form, Table.
|
||||
|
||||
## 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 +119,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,97 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 2.4.2
|
||||
|
||||
`2016-11-13`
|
||||
|
||||
* 修复 `Dropdown.Button` 不弹出的问题。[#3815](https://github.com/ant-design/ant-design/issues/3815)
|
||||
|
||||
## 2.4.1
|
||||
|
||||
`2016-11-11`
|
||||
|
||||
* 修复 `2.4.0` 组件 index 文件丢失的问题。
|
||||
|
||||
## 2.4.0
|
||||
|
||||
`2016-11-11`
|
||||
|
||||
* 调整了组件的导航结构。
|
||||
* 新增 [Anchor](https://ant.design/components/anchor) 锚点组件。
|
||||
* 整理了样式变量,修复 `@font-size-base` 和 `@text-color` 在部分组件无效的问题,新增 `@font-size-lg` `@text-color-secondary`,并移除了部分无用的变量。
|
||||
* `Transfer` 组件新增了受控属性 `selectedKeys`。[#3729](https://github.com/ant-design/ant-design/issues/3729)
|
||||
* `Tag` 新增选中状态。
|
||||
* 修复 `Dropdown.Button` 不支持 `visible` 和 `onVisibleChange` 的问题。[#3779](https://github.com/ant-design/ant-design/issues/3779)
|
||||
* 修复 `DatePicker[showTime]`` 的 `此刻` 按钮。[#3748](https://github.com/ant-design/ant-design/issues/3748)
|
||||
* 修复 `Steps` 竖直方向的样式。[#3760](https://github.com/ant-design/ant-design/issues/3760)
|
||||
* 修复 `Spin` 组件在 IE10+ 的样式问题。[#3755](https://github.com/ant-design/ant-design/issues/3755)
|
||||
* 修复 `Mention` 组件的 focus 逻辑. [#3801](https://github.com/ant-design/ant-design/issues/3801)
|
||||
* 修复 `Progress` 组件的动画问题。[#3784](https://github.com/ant-design/ant-design/issues/3784)
|
||||
* 修复 `Select` 搜索时的丢失焦点问题。[#3778](https://github.com/ant-design/ant-design/issues/3778)
|
||||
* 修复 `TimePicker` 不支持 `format="HH"` 等格式的问题。[#3793](https://github.com/ant-design/ant-design/issues/3793)
|
||||
* 优化了 `Table` 选择的性能。[#3757](https://github.com/ant-design/ant-design/pull/3757)
|
||||
* 优化 `Carousel` 的默认样式。
|
||||
* 优化 `Checkbox` 和 `Radio` 的样式。[#3590](https://github.com/ant-design/ant-design/issues/3590)
|
||||
* 修复 `DatePicker`、`Form`、`Table` 等组件的样式细节。
|
||||
|
||||
## 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 +118,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.
|
||||
@@ -97,6 +97,7 @@ tsconfig.json
|
||||
- [Development tool](http://ant-tool.github.io/)
|
||||
- [React components](http://react-component.github.io/)
|
||||
- [Mobile UI](http://mobile.ant.design)
|
||||
- [Motion](https://motion.ant.design)
|
||||
- [React style guide](https://github.com/react-component/react-component.github.io/blob/master/docs/zh-cn/component-code-style.md)
|
||||
- [React component design guide](https://github.com/react-component/react-component.github.io/blob/master/docs/zh-cn/component-design.md)
|
||||
- [Developer Instruction](https://github.com/ant-design/ant-design/wiki/Development)
|
||||
@@ -106,6 +107,7 @@ tsconfig.json
|
||||
- [CodePen boilerplate](http://codepen.io/benjycui/pen/KgPZrE?editors=001) for bug reports
|
||||
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome all contributions, please read our [CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) first. You can submit any ideas as [pull requests](https://github.com/ant-design/ant-design/pulls) or as a [GitHub issue](https://github.com/ant-design/ant-design/issues). If you'd like to improve code, check out the [Development Instruction](https://github.com/ant-design/ant-design/wiki/Development) and have a good time! :)
|
||||
|
||||
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>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Other
|
||||
type: Navigation
|
||||
title: Affix
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 固钉
|
||||
type: Other
|
||||
type: Navigation
|
||||
title: Affix
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Feedback
|
||||
title: Alert
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 警告提示
|
||||
type: Views
|
||||
type: Feedback
|
||||
title: Alert
|
||||
---
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
}
|
||||
|
||||
&-icon {
|
||||
font-size: 14px;
|
||||
font-size: @font-size-lg;
|
||||
top: 9px;
|
||||
left: 16px;
|
||||
position: absolute;
|
||||
@@ -71,7 +71,7 @@
|
||||
cursor: pointer;
|
||||
|
||||
.@{iconfont-css-prefix}-cross {
|
||||
color: @legend-color;
|
||||
color: @text-color-secondary;
|
||||
transition: color .3s ease;
|
||||
&:hover {
|
||||
color: #404040;
|
||||
@@ -113,7 +113,7 @@
|
||||
}
|
||||
|
||||
&-with-description &-message {
|
||||
font-size: 14px;
|
||||
font-size: @font-size-lg;
|
||||
color: @heading-color;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
|
||||
93
components/anchor/AnchorLink.tsx
Normal file
93
components/anchor/AnchorLink.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import AnchorHelper, { scrollTo } from './anchorHelper';
|
||||
|
||||
export interface AnchorLinkProps {
|
||||
href: string;
|
||||
onClick: (href: string) => void;
|
||||
active?: boolean;
|
||||
prefixCls?: string;
|
||||
children?: any;
|
||||
title?: Element;
|
||||
bounds: number;
|
||||
target?: () => HTMLElement | Window;
|
||||
affix?: boolean;
|
||||
}
|
||||
|
||||
export default class AnchorLink extends React.Component<AnchorLinkProps, any> {
|
||||
static contextTypes = {
|
||||
anchorHelper: React.PropTypes.any,
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
anchorHelper: React.PropTypes.any,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
href: '#',
|
||||
prefixCls: 'ant-anchor',
|
||||
};
|
||||
|
||||
context: {
|
||||
anchorHelper: AnchorHelper;
|
||||
};
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
}
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
anchorHelper: this.context.anchorHelper,
|
||||
};
|
||||
}
|
||||
|
||||
renderAnchorLink = (child) => {
|
||||
const { href } = child.props;
|
||||
if (href) {
|
||||
this.context.anchorHelper.addLink(href);
|
||||
return React.cloneElement(child, {
|
||||
onClick: this.context.anchorHelper.scrollTo,
|
||||
prefixCls: this.props.prefixCls,
|
||||
});
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
scrollTo = (e) => {
|
||||
const { onClick, href } = this.props;
|
||||
const { anchorHelper } = this.context;
|
||||
e.preventDefault();
|
||||
if (onClick) {
|
||||
onClick(href);
|
||||
} else {
|
||||
e.stopPreventDefault();
|
||||
const scrollToFn = anchorHelper ? anchorHelper.scrollTo : scrollTo;
|
||||
scrollToFn(href);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, href, children, title, bounds, affix } = this.props;
|
||||
const { anchorHelper } = this.context;
|
||||
const active = affix && anchorHelper && anchorHelper.getCurrentAnchor(bounds) === href;
|
||||
const cls = classNames({
|
||||
[`${prefixCls}-link`]: true,
|
||||
[`${prefixCls}-link-active`]: active,
|
||||
});
|
||||
return (
|
||||
<div className={cls}>
|
||||
<a
|
||||
ref={(component) => component && active && anchorHelper ? anchorHelper.setActiveAnchor(component) : null}
|
||||
className={`${prefixCls}-link-title`}
|
||||
onClick={this.scrollTo}
|
||||
href={href}
|
||||
title={typeof title === 'string' ? title : ''}
|
||||
>
|
||||
{title}
|
||||
</a>
|
||||
{React.Children.map(children, this.renderAnchorLink)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
107
components/anchor/anchorHelper.tsx
Normal file
107
components/anchor/anchorHelper.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import getScroll from '../_util/getScroll';
|
||||
import getRequestAnimationFrame from '../_util/getRequestAnimationFrame';
|
||||
|
||||
export const reqAnimFrame = getRequestAnimationFrame();
|
||||
|
||||
export const easeInOutCubic = (t, b, c, d) => {
|
||||
const cc = c - b;
|
||||
t /= d / 2;
|
||||
if (t < 1) {
|
||||
return cc / 2 * t * t * t + b;
|
||||
}
|
||||
return cc / 2 * ((t -= 2) * t * t + 2) + b;
|
||||
};
|
||||
|
||||
export function getDefaultTarget() {
|
||||
return typeof window !== 'undefined' ?
|
||||
window : null;
|
||||
}
|
||||
|
||||
export function getOffsetTop(element): number {
|
||||
if (!element) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!element.getClientRects().length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const rect = element.getBoundingClientRect();
|
||||
|
||||
if ( rect.width || rect.height ) {
|
||||
const doc = element.ownerDocument;
|
||||
const docElem = doc.documentElement;
|
||||
return rect.top - docElem.clientTop;
|
||||
}
|
||||
|
||||
return rect.top;
|
||||
}
|
||||
|
||||
export function scrollTo(href, target = getDefaultTarget) {
|
||||
const scrollTop = getScroll(target(), true);
|
||||
const targetElement = document.querySelector(href);
|
||||
if (!targetElement) {
|
||||
return;
|
||||
}
|
||||
const offsetTop = getOffsetTop(targetElement);
|
||||
const targetScrollTop = scrollTop + offsetTop;
|
||||
const startTime = Date.now();
|
||||
const frameFunc = () => {
|
||||
const timestamp = Date.now();
|
||||
const time = timestamp - startTime;
|
||||
window.scrollTo(window.pageXOffset, easeInOutCubic(time, scrollTop, targetScrollTop, 450));
|
||||
if (time < 450) {
|
||||
reqAnimFrame(frameFunc);
|
||||
}
|
||||
};
|
||||
reqAnimFrame(frameFunc);
|
||||
history.pushState(null, undefined, href);
|
||||
}
|
||||
|
||||
class AnchorHelper {
|
||||
private links: Array<string>;
|
||||
private currentAnchor: HTMLElement | null;
|
||||
private _activeAnchor: string;
|
||||
|
||||
constructor() {
|
||||
this.links = [];
|
||||
this.currentAnchor = null;
|
||||
this._activeAnchor = '';
|
||||
}
|
||||
|
||||
addLink(link) {
|
||||
if (this.links.indexOf(link) === -1) {
|
||||
this.links.push(link);
|
||||
}
|
||||
}
|
||||
|
||||
getCurrentActiveAnchor(): HTMLElement | null {
|
||||
return this.currentAnchor;
|
||||
}
|
||||
|
||||
setActiveAnchor(component) {
|
||||
this.currentAnchor = component;
|
||||
}
|
||||
|
||||
getCurrentAnchor(bounds = 5) {
|
||||
let activeAnchor = '';
|
||||
this.links.forEach(section => {
|
||||
const target = document.querySelector(section);
|
||||
if (target) {
|
||||
const top = getOffsetTop(target);
|
||||
const bottom = top + target.clientHeight;
|
||||
if ((top <= bounds) && (bottom >= -bounds)) {
|
||||
activeAnchor = section;
|
||||
}
|
||||
}
|
||||
});
|
||||
this._activeAnchor = activeAnchor || this._activeAnchor;
|
||||
return this._activeAnchor;
|
||||
}
|
||||
|
||||
scrollTo(href, target = getDefaultTarget) {
|
||||
scrollTo(href, target);
|
||||
}
|
||||
}
|
||||
|
||||
export default AnchorHelper;
|
||||
36
components/anchor/demo/basic.md
Normal file
36
components/anchor/demo/basic.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
order: 0
|
||||
title:
|
||||
zh-CN: 基本
|
||||
en-US: Basic
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法。
|
||||
|
||||
## en-US
|
||||
|
||||
The simplest usage.
|
||||
|
||||
```jsx
|
||||
import { Anchor } from 'antd';
|
||||
const { Link } = Anchor;
|
||||
|
||||
ReactDOM.render(
|
||||
<Anchor>
|
||||
<Link href="#components-anchor-demo-basic" title="Basic demo" />
|
||||
<Link href="#components-anchor-demo-fixed" title="Fixed demo" />
|
||||
<Link href="#API" title="API">
|
||||
<Link href="#Anchor-Props" title="Anchor Props" />
|
||||
<Link href="#Link-Props" title="Link Props" />
|
||||
</Link>
|
||||
</Anchor>
|
||||
, mountNode);
|
||||
```
|
||||
|
||||
<style>
|
||||
.code-box-demo .ant-affix {
|
||||
z-index: 11;
|
||||
}
|
||||
</style>
|
||||
30
components/anchor/demo/fixed.md
Normal file
30
components/anchor/demo/fixed.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 固定
|
||||
en-US: Fixed Anchor
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
不浮动,状态不随页面滚动变化。
|
||||
|
||||
## en-US
|
||||
|
||||
Do not change state when page is scrolling.
|
||||
|
||||
```jsx
|
||||
import { Anchor } from 'antd';
|
||||
const { Link } = Anchor;
|
||||
|
||||
ReactDOM.render(
|
||||
<Anchor affix={false}>
|
||||
<Link href="#components-anchor-demo-basic" title="Basic demo" />
|
||||
<Link href="#components-anchor-demo-fixed" title="Fixed demo" />
|
||||
<Link href="#API" title="API">
|
||||
<Link href="#Anchor-Props" title="Anchor Props" />
|
||||
<Link href="#Link-Props" title="Link Props" />
|
||||
</Link>
|
||||
</Anchor>
|
||||
, mountNode);
|
||||
```
|
||||
29
components/anchor/index.en-US.md
Normal file
29
components/anchor/index.en-US.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
category: Components
|
||||
type: Other
|
||||
cols: 1
|
||||
title: Anchor
|
||||
---
|
||||
|
||||
Hyperlinks to scroll on one page.
|
||||
|
||||
## When To Use
|
||||
|
||||
For displaying anchor hyperlinks on page, and jump between them.
|
||||
|
||||
## API
|
||||
|
||||
### Anchor Props
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|--------------|-----------------------|----------|--------------|
|
||||
| offsetTop | Pixels to offset from top when calculating position of scroll | Number | 0 |
|
||||
| offsetBottom | Pixels to offset from bottom when calculating position of scroll | Number | - |
|
||||
| bounds | Bounding distance of anchor area | Number | 5(px) |
|
||||
|
||||
### Link Props
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|-------------|----------------|--------------------|--------------|
|
||||
| href | target of hyperlink | String | |
|
||||
| title | content of hyperlink | React.Node | |
|
||||
130
components/anchor/index.tsx
Normal file
130
components/anchor/index.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import AnchorLink from './AnchorLink';
|
||||
import Affix from '../affix';
|
||||
import AnchorHelper, { getDefaultTarget } from './anchorHelper';
|
||||
|
||||
export interface AnchorProps {
|
||||
target: () => HTMLElement | Window;
|
||||
children: React.ReactNode;
|
||||
prefixCls?: string;
|
||||
offsetTop?: number;
|
||||
bounds?: number;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
affix?: boolean;
|
||||
}
|
||||
|
||||
export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
static Link = AnchorLink;
|
||||
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-anchor',
|
||||
affix: true,
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
anchorHelper: React.PropTypes.any,
|
||||
};
|
||||
|
||||
refs: {
|
||||
ink?: any;
|
||||
};
|
||||
|
||||
private scrollEvent: any;
|
||||
private anchorHelper: AnchorHelper;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
activeAnchor: null,
|
||||
};
|
||||
this.anchorHelper = new AnchorHelper();
|
||||
}
|
||||
|
||||
handleScroll = () => {
|
||||
this.setState({
|
||||
activeAnchor: this.anchorHelper.getCurrentAnchor(this.props.bounds),
|
||||
});
|
||||
}
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
anchorHelper: this.anchorHelper,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.handleScroll();
|
||||
this.updateInk();
|
||||
this.scrollEvent = addEventListener((this.props.target || getDefaultTarget)(), 'scroll', this.handleScroll);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.scrollEvent) {
|
||||
this.scrollEvent.remove();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.updateInk();
|
||||
}
|
||||
|
||||
updateInk = () => {
|
||||
const activeAnchor = this.anchorHelper.getCurrentActiveAnchor();
|
||||
if (activeAnchor) {
|
||||
this.refs.ink.style.top = `${activeAnchor.offsetTop + activeAnchor.clientHeight / 2 - 4.5}px`;
|
||||
}
|
||||
}
|
||||
|
||||
renderAnchorLink = (child) => {
|
||||
const { href } = child.props;
|
||||
if (href) {
|
||||
this.anchorHelper.addLink(href);
|
||||
return React.cloneElement(child, {
|
||||
onClick: this.anchorHelper.scrollTo,
|
||||
prefixCls: this.props.prefixCls,
|
||||
bounds: this.props.bounds,
|
||||
affix: this.props.affix,
|
||||
});
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, offsetTop, style, className = '', affix } = this.props;
|
||||
const { activeAnchor } = this.state;
|
||||
const inkClass = classNames({
|
||||
[`${prefixCls}-ink-ball`]: true,
|
||||
visible: !!activeAnchor,
|
||||
});
|
||||
|
||||
const wrapperClass = classNames({
|
||||
[`${prefixCls}-wrapper`]: true,
|
||||
[className]: !!className,
|
||||
});
|
||||
|
||||
const anchorClass = classNames({
|
||||
[`${prefixCls}`]: true,
|
||||
'fixed': !affix,
|
||||
});
|
||||
|
||||
const anchorContent = (
|
||||
<div className={wrapperClass} style={style}>
|
||||
<div className={anchorClass}>
|
||||
<div className={`${prefixCls}-ink`} >
|
||||
<span className={inkClass} ref="ink" />
|
||||
</div>
|
||||
{React.Children.map(this.props.children, this.renderAnchorLink)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return affix === false ? anchorContent : (
|
||||
<Affix offsetTop={offsetTop}>
|
||||
{anchorContent}
|
||||
</Affix>
|
||||
);
|
||||
}
|
||||
}
|
||||
30
components/anchor/index.zh-CN.md
Normal file
30
components/anchor/index.zh-CN.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 锚点
|
||||
cols: 1
|
||||
type: Other
|
||||
title: Anchor
|
||||
---
|
||||
|
||||
用于跳转到页面指定位置。
|
||||
|
||||
## 何时使用
|
||||
|
||||
需要展现当前页面上可供跳转的锚点链接,以及快速在锚点之间跳转。
|
||||
|
||||
## API
|
||||
|
||||
### Anchor Props
|
||||
|
||||
| 成员 | 说明 | 类型 | 默认值 |
|
||||
|-------------|----------------|--------------------|--------------|
|
||||
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | Number | |
|
||||
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | Number | |
|
||||
| bounds | 锚点区域边界 | Number | 5(px) |
|
||||
|
||||
### Link Props
|
||||
|
||||
| 成员 | 说明 | 类型 | 默认值 |
|
||||
|-------------|----------------|--------------------|--------------|
|
||||
| href | 锚点链接 | String | |
|
||||
| title | 文字内容 | React.Node | |
|
||||
70
components/anchor/style/index.less
Normal file
70
components/anchor/style/index.less
Normal file
@@ -0,0 +1,70 @@
|
||||
@import "../../style/themes/default";
|
||||
|
||||
.@{ant-prefix} {
|
||||
&-anchor {
|
||||
position: relative;
|
||||
&-wrapper {
|
||||
padding: 6px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
&-ink {
|
||||
position: absolute;
|
||||
width: 9px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
&:before {
|
||||
content: ' ';
|
||||
position: relative;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-color: @border-color-split;
|
||||
margin: 0 auto;
|
||||
}
|
||||
&-ball {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 9px;
|
||||
border: 3px solid @primary-color;
|
||||
background-color: white;
|
||||
transition: top .3s ease-in-out;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
&.visible {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.fixed &-ink &-ink-ball {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-anchor-link {
|
||||
padding: 4px 0 4px 16px;
|
||||
line-height: 1;
|
||||
|
||||
&-title {
|
||||
display: block;
|
||||
position: relative;
|
||||
transition: all .3s;
|
||||
color: @text-color;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&-active > &-title {
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
& > & {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
cols: 1
|
||||
title: AutoComplete
|
||||
---
|
||||
@@ -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 |
|
||||
|----------------|----------------------------------|------------|--------|
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 自动完成
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
cols: 1
|
||||
title: AutoComplete
|
||||
---
|
||||
@@ -18,7 +18,7 @@ title: AutoComplete
|
||||
const dataSource = ['12345', '23456', '34567'];
|
||||
<AutoComplete dataSource={dataSource} />
|
||||
```
|
||||
|
||||
因为 `AutoComplete` 是基于 `Select` 封装的,所以除了以下 API 外,`AutoComplete` 跟 `Select` 拥有一样的 API。
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|----------------|----------------------------------|------------|---------|
|
||||
|
||||
@@ -19,7 +19,10 @@ 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 style={{ color: 'rgba(64, 64, 64, 0.6)' }}> gray </strong>
|
||||
button.
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -17,23 +17,31 @@ 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 style={{ color: '#57c5f7' }}> 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;
|
||||
}
|
||||
````
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Other
|
||||
type: Navigation
|
||||
title: BackTop
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Other
|
||||
type: Navigation
|
||||
subtitle: 回到顶部
|
||||
title: BackTop
|
||||
---
|
||||
|
||||
@@ -67,7 +67,5 @@ const Test = React.createClass({
|
||||
},
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<Test />
|
||||
, mountNode);
|
||||
ReactDOM.render(<Test />, mountNode);
|
||||
````
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Badge
|
||||
---
|
||||
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 徽标数
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Badge
|
||||
---
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
height: 20px;
|
||||
border-radius: 10px;
|
||||
min-width: 20px;
|
||||
background: @error-color;
|
||||
background: @highlight-color;
|
||||
border: 1px solid transparent;
|
||||
color: #fff;
|
||||
line-height: 18px;
|
||||
text-align: center;
|
||||
padding: 0 6px;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
white-space: nowrap;
|
||||
transform-origin: -10% center;
|
||||
z-index: 10;
|
||||
@@ -42,7 +42,7 @@
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
border-radius: 100%;
|
||||
background: @error-color;
|
||||
background: @highlight-color;
|
||||
z-index: 10;
|
||||
box-shadow: 0 0 0 1px #fff;
|
||||
}
|
||||
@@ -109,15 +109,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
a & {
|
||||
&-count:hover {
|
||||
background: tint(@error-color, 20%);
|
||||
}
|
||||
&-count:active {
|
||||
background: shade(@error-color, 5%);
|
||||
}
|
||||
}
|
||||
|
||||
.@{number-prefix-cls} {
|
||||
overflow: hidden;
|
||||
&-only {
|
||||
|
||||
@@ -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.'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@breadcrumb-prefix-cls: ~"@{ant-prefix}-breadcrumb";
|
||||
|
||||
.@{breadcrumb-prefix-cls} {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
font-size: @font-size-base;
|
||||
|
||||
a {
|
||||
|
||||
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
|
||||
);
|
||||
````
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Basic
|
||||
type: General
|
||||
title: Button
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Basic
|
||||
type: General
|
||||
title: Button
|
||||
subtitle: 按钮
|
||||
---
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
|
||||
&.disabled,
|
||||
&[disabled] {
|
||||
cursor: @cursor-disabled;
|
||||
cursor: not-allowed;
|
||||
> * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
cols: 1
|
||||
title: Calendar
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
subtitle: 日历
|
||||
cols: 1
|
||||
title: Calendar
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
.@{full-calendar-prefix-cls} {
|
||||
font-size: @font-size-base;
|
||||
line-height: 1.5;
|
||||
line-height: @line-height-base;
|
||||
outline: none;
|
||||
border-top: 1px solid @border-color-base;
|
||||
|
||||
&-month-select {
|
||||
margin-left: 5px;
|
||||
@@ -30,8 +32,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
outline: none;
|
||||
border-top: 1px solid @legend-border-color;
|
||||
&-date-panel {
|
||||
position: relative;
|
||||
outline: none;
|
||||
@@ -201,7 +201,7 @@
|
||||
}
|
||||
|
||||
&-fullscreen &-today &-value {
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Card
|
||||
cols: 1
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Card
|
||||
subtitle: 卡片
|
||||
cols: 1
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
&:hover {
|
||||
box-shadow: @box-shadow-base;
|
||||
border-color: #eee;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
&-bordered {
|
||||
@@ -26,7 +26,7 @@
|
||||
padding: 0 24px;
|
||||
|
||||
&-title {
|
||||
font-size: 14px;
|
||||
font-size: @font-size-lg;
|
||||
display: inline-block;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Carousel
|
||||
---
|
||||
|
||||
@@ -29,13 +29,10 @@ For more info on the parameters, refer to the https://github.com/akiran/react-sl
|
||||
<style>
|
||||
.ant-carousel .slick-slide {
|
||||
text-align: center;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
background: #71B5DE;
|
||||
height: 160px;
|
||||
line-height: 160px;
|
||||
background: #364d79;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
#components-carousel-demo-vertical .ant-carousel {
|
||||
margin-right: 35px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Carousel
|
||||
subtitle: 走马灯
|
||||
---
|
||||
@@ -30,13 +30,10 @@ subtitle: 走马灯
|
||||
<style>
|
||||
.ant-carousel .slick-slide {
|
||||
text-align: center;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
background: #71B5DE;
|
||||
height: 160px;
|
||||
line-height: 130px;
|
||||
background: #506b9e;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
#components-carousel-demo-vertical .ant-carousel {
|
||||
margin-right: 35px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -138,14 +138,9 @@
|
||||
}
|
||||
|
||||
// Dots
|
||||
|
||||
.slick-slider {
|
||||
padding-bottom: 45px;
|
||||
}
|
||||
|
||||
.slick-dots {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
bottom: 6px;
|
||||
list-style: none;
|
||||
display: block;
|
||||
text-align: center;
|
||||
@@ -156,62 +151,48 @@
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin: 0 5px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
margin: 0 2px;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
button {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
display: block;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
cursor: pointer;
|
||||
background: #000;
|
||||
opacity: 0.3;
|
||||
display: inline-block;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 7px;
|
||||
outline: none;
|
||||
line-height: 0;
|
||||
font-size: 0;
|
||||
color: transparent;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
transition: all .3s;
|
||||
&:hover,
|
||||
&:focus {
|
||||
outline: none;
|
||||
&:before {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
content: "•";
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 18px;
|
||||
font-family: arial, sans-serif;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
color: gray;
|
||||
transition: all .3s;
|
||||
opacity: 0.25;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
&.slick-active button:before {
|
||||
color: black;
|
||||
opacity: 0.75;
|
||||
&.slick-active button {
|
||||
background: #fff;
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 3px rgba(0, 0, 0, .25);
|
||||
&:hover,
|
||||
&:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{ant-prefix}-carousel-vertical {
|
||||
.slick-slider {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.slick-dots {
|
||||
width: 20px;
|
||||
bottom: auto;
|
||||
right: -35px;
|
||||
top: 0;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: Cascader
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: Cascader
|
||||
subtitle: 级联选择
|
||||
---
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
z-index: 2;
|
||||
background: #fff;
|
||||
top: 50%;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
color: #ccc;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
@@ -63,7 +63,7 @@
|
||||
cursor: pointer;
|
||||
transition: color 0.3s ease, opacity 0.15s ease;
|
||||
&:hover {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
height: 12px;
|
||||
margin-top: -6px;
|
||||
line-height: 12px;
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
.iconfont-size-under-12px(9px);
|
||||
&:before {
|
||||
transition: transform 0.2s ease;
|
||||
@@ -95,7 +95,7 @@
|
||||
}
|
||||
}
|
||||
&-menus {
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
background: #fff;
|
||||
position: absolute;
|
||||
z-index: @zindex-dropdown;
|
||||
@@ -173,14 +173,14 @@
|
||||
&:after {
|
||||
.iconfont-font("\e61f");
|
||||
.iconfont-size-under-12px(8px);
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
& &-keyword {
|
||||
color: @error-color;
|
||||
color: @highlight-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: Checkbox
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 多选框
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: Checkbox
|
||||
---
|
||||
|
||||
|
||||
@@ -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: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-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,50 @@
|
||||
}
|
||||
|
||||
// 半选状态
|
||||
.@{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;
|
||||
}
|
||||
}
|
||||
&: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,13 +114,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
.@{checkbox-inner-prefix-cls}-input {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
& + span {
|
||||
color: #ccc;
|
||||
cursor: @cursor-disabled;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,8 +131,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 {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
import { Col } from '../layout';
|
||||
import { Col } from '../grid';
|
||||
export default Col;
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
import '../../style/index.less';
|
||||
import '../../layout/style/index.less';
|
||||
import '../../grid/style/index.less';
|
||||
|
||||
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">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
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} />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Collapse
|
||||
subtitle: 折叠面板
|
||||
cols: 1
|
||||
---
|
||||
|
||||
可以折叠/展开的内容区域。
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
padding-left: 32px;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
.collapse-close();
|
||||
.iconfont-mixin();
|
||||
position: absolute;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
line-height: 40px;
|
||||
@@ -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,36 @@ 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
|
||||
// Clear temp value and trigger onChange when hide DatePicker[showTime] panel
|
||||
handleOpenChange(open) {
|
||||
const { showTime, onOpenChange } = this.props;
|
||||
if (!open) {
|
||||
this.setState({
|
||||
tempValue: undefined,
|
||||
// tricky code to avoid triggering onChange multiple times
|
||||
// when click `Now` button
|
||||
let tempValue;
|
||||
this.setState(prevState => {
|
||||
tempValue = prevState.tempValue;
|
||||
return {
|
||||
tempValue: undefined,
|
||||
};
|
||||
}, () => {
|
||||
if (showTime && tempValue) {
|
||||
this.handleChange(tempValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this.props.onOpenChange) {
|
||||
this.props.onOpenChange(open);
|
||||
if (onOpenChange) {
|
||||
onOpenChange(open);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -91,14 +100,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 +127,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}
|
||||
|
||||
@@ -7,18 +7,26 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法。
|
||||
最简单的用法,在浮层中可以选择或者输入日期。
|
||||
|
||||
## en-US
|
||||
|
||||
The most basic usage.
|
||||
Basic use case. Users can select or input a date in panel.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
function onChange(date, dateString) {
|
||||
console.log(date, dateString);
|
||||
}
|
||||
|
||||
ReactDOM.render(<DatePicker onChange={onChange} />, mountNode);
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker onChange={onChange} /><br />
|
||||
<MonthPicker onChange={onChange} /><br />
|
||||
<RangePicker onChange={onChange} />
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -1,28 +1,23 @@
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 指定不可选择日期
|
||||
en-US: Specify the date that cannot be selected
|
||||
zh-CN: 不可选择日期和时间
|
||||
en-US: Disabled Date & Time
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
设置 `disabledDate` 方法,来确定不可选时段。
|
||||
设置 `disabledTime` 方法,来确定 showTime 的 RangePicker 的不可选时间段。
|
||||
|
||||
如上例:不可选择今天之后的日期。
|
||||
可用 `disabledDate` 和 `disabledTime` 分别禁止选择部分日期和时间,其中 `disabledTime` 需要和 `showTime` 一起使用。
|
||||
|
||||
## en-US
|
||||
|
||||
Specify unselectable period by `disabledDate`.
|
||||
|
||||
As in the example above: you can't select a date later than today.
|
||||
Disabled part of dates and time by `disabledDate` and `disabledTime` respectively, and `disabledTime` only works with `showTime`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
function newArray(start, end) {
|
||||
function range(start, end) {
|
||||
const result = [];
|
||||
for (let i = start; i < end; i++) {
|
||||
result.push(i);
|
||||
@@ -31,20 +26,33 @@ function newArray(start, end) {
|
||||
}
|
||||
|
||||
|
||||
const disabledDate = function (current) {
|
||||
// can not select days after today
|
||||
return current && current.valueOf() > Date.now();
|
||||
};
|
||||
function disabledDate(current) {
|
||||
// can not select days before today and today
|
||||
return current && current.valueOf() < Date.now();
|
||||
}
|
||||
|
||||
function disabledTime(time, type) {
|
||||
console.log('disabledTime', time, type);
|
||||
function disabledDateTime() {
|
||||
return {
|
||||
disabledHours() {
|
||||
return range(0, 60).splice(4, 20);
|
||||
},
|
||||
disabledMinutes() {
|
||||
return range(30, 60);
|
||||
},
|
||||
disabledSeconds() {
|
||||
return [55, 56];
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function disabledRangeTime(_, type) {
|
||||
if (type === 'start') {
|
||||
return {
|
||||
disabledHours() {
|
||||
return newArray(0, 60).splice(4, 20);
|
||||
return range(0, 60).splice(4, 20);
|
||||
},
|
||||
disabledMinutes() {
|
||||
return newArray(30, 60);
|
||||
return range(30, 60);
|
||||
},
|
||||
disabledSeconds() {
|
||||
return [55, 56];
|
||||
@@ -53,10 +61,10 @@ function disabledTime(time, type) {
|
||||
}
|
||||
return {
|
||||
disabledHours() {
|
||||
return newArray(0, 60).splice(20, 4);
|
||||
return range(0, 60).splice(20, 4);
|
||||
},
|
||||
disabledMinutes() {
|
||||
return newArray(0, 31);
|
||||
return range(0, 31);
|
||||
},
|
||||
disabledSeconds() {
|
||||
return [55, 56];
|
||||
@@ -64,10 +72,12 @@ function disabledTime(time, type) {
|
||||
};
|
||||
}
|
||||
|
||||
ReactDOM.render(<div>
|
||||
<DatePicker disabledDate={disabledDate} />
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker disabledDate={disabledDate} disabledTime={disabledDateTime} showTime />
|
||||
<br />
|
||||
<RangePicker showTime disabledDate={disabledDate} disabledTime={disabledTime} />
|
||||
</div>
|
||||
, mountNode);
|
||||
<RangePicker disabledDate={disabledDate} disabledTime={disabledRangeTime} showTime />
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 5
|
||||
order: 4
|
||||
title:
|
||||
zh-CN: 禁用
|
||||
en-US: Disabled
|
||||
@@ -16,8 +16,18 @@ A disabled state of the `DatePicker`.
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
const dateFormat = 'YYYY-MM-DD';
|
||||
ReactDOM.render(
|
||||
<DatePicker defaultValue={moment('2015-06-06', 'YYYY-MM-DD')} disabled />
|
||||
, mountNode);
|
||||
<div>
|
||||
<DatePicker defaultValue={moment('2015-06-06', dateFormat)} disabled /><br />
|
||||
<MonthPicker defaultValue={moment('2015-06', 'YYYY-MM')} disabled /><br />
|
||||
<RangePicker
|
||||
defaultValue={[moment('2015-06-06', dateFormat), moment('2015-06-06', dateFormat)]}
|
||||
disabled
|
||||
/>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
34
components/date-picker/demo/format.md
Normal file
34
components/date-picker/demo/format.md
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 日期格式
|
||||
en-US: Date Format
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `format` 属性,可以自定义日期显示格式。
|
||||
|
||||
## en-US
|
||||
|
||||
We can set the date format by `format`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
const dateFormat = 'YYYY/MM/DD';
|
||||
const monthFormat = 'YYYY/MM';
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker defaultValue={moment('2015/01/01', dateFormat)} format={dateFormat} /><br />
|
||||
<MonthPicker defaultValue={moment('2015/01', monthFormat)} format={monthFormat} /><br />
|
||||
<RangePicker
|
||||
defaultValue={[moment('2015/01/01', dateFormat), moment('2015/01/01', dateFormat)]}
|
||||
format={dateFormat}
|
||||
/><br />
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 日期格式
|
||||
en-US: Date format
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `format` 属性,可以自定义你需要的日期显示格式,如 `YYYY/MM/DD`。
|
||||
|
||||
## en-US
|
||||
|
||||
By using `format`, you can customize the format(such as `YYYY/MM/DD`) the date is displayed in.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
const format = 'YYYY/MM/DD';
|
||||
ReactDOM.render(
|
||||
<DatePicker defaultValue={moment('2015/01/01', format)} format={format} />
|
||||
, mountNode);
|
||||
````
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 10
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 国际化
|
||||
en-US: Locale
|
||||
@@ -7,24 +7,26 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
通过 `locale` 语言, 默认支持 `en_US`,`zh_CN`。
|
||||
通过 `locale` 设置语言, 默认支持 `en_US`,`zh_CN`。
|
||||
|
||||
moment 会自动使用当前时区,如果需要使用别的时区,则需要自行设置,设置方法请参考 [下面的文档](/components/date-picker/#DatePicker)。
|
||||
moment 会自动使用当前时区,如果需要使用别的时区,则需要自行设置,设置方法请参考示例代码中的注释。
|
||||
|
||||
## en-US
|
||||
|
||||
Use locale to set the language. `en_US`, `zh_CN` are supported by default.
|
||||
|
||||
moment will use your time zone automatically. If you want to set other time zone, please set it by yourself. [More](/components/date-picker/#DatePicker)
|
||||
moment will use your time zone automatically. If you want to set other time zone, please set it by yourself.
|
||||
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import enUS from 'antd/lib/date-picker/locale/en_US';
|
||||
import moment from 'moment-timezone/moment-timezone';
|
||||
|
||||
// It's recommended to set moment locale and time zone globally in entry file,
|
||||
// otherwise, you need to set it by `value` or `defaultValue`.
|
||||
// moment.locale('en');
|
||||
|
||||
// The following data is copied from https://github.com/moment/moment-timezone/blob/develop/data/packed/latest.json
|
||||
// moment.tz.add('Europe/London|GMT BST BDST|0 -10 -20|0101010101010101010101010101010101010101010101010121212121210101210101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2axa0 Rc0 1fA0 14M0 1fc0 1g00 1co0 1dc0 1co0 1oo0 1400 1dc0 19A0 1io0 1io0 WM0 1o00 14o0 1o00 17c0 1io0 17c0 1fA0 1a00 1lc0 17c0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1cM0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1io0 1qM0 Dc0 2Rz0 Dc0 1zc0 Oo0 1zc0 Rc0 1wo0 17c0 1iM0 FA0 xB0 1fA0 1a00 14o0 bb0 LA0 xB0 Rc0 1wo0 11A0 1o00 17c0 1fA0 1a00 1fA0 1cM0 1fA0 1a00 17c0 1fA0 1a00 1io0 17c0 1lc0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1a00 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1tA0 IM0 90o0 U00 1tA0 U00 1tA0 U00 1tA0 U00 1tA0 WM0 1qM0 WM0 1qM0 WM0 1tA0 U00 1tA0 U00 1tA0 11z0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 14o0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|10e6');
|
||||
// moment.tz.setDefault('Europe/London')
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
order: 9
|
||||
title:
|
||||
zh-CN: 月选择器
|
||||
en-US: MonthPicker
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `MonthPicker` 实现月选择器。
|
||||
|
||||
## en-US
|
||||
|
||||
You can get a month selector by using `MonthPicker`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
const MonthPicker = DatePicker.MonthPicker;
|
||||
ReactDOM.render(
|
||||
<MonthPicker defaultValue={moment('2015-12', 'YYYY-MM')} />
|
||||
, mountNode);
|
||||
````
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 日期范围二
|
||||
en-US: Date range, case 2
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `RangePicker` 实现日期范围选择有更好的交互体验。
|
||||
|
||||
## en-US
|
||||
|
||||
By using `RangePicker` to specify a date range, you can achieve a better interactive experience.
|
||||
|
||||
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
function onChange(dates, dateStrings) {
|
||||
console.log('From: ', dates[0], ', to: ', dates[1]);
|
||||
console.log('From: ', dateStrings[0], ', to: ', dateStrings[1]);
|
||||
}
|
||||
ReactDOM.render(<div>
|
||||
<RangePicker style={{ width: 200 }} onChange={onChange} />
|
||||
<br />
|
||||
<RangePicker showTime format="YYYY/MM/DD HH:mm:ss" onChange={onChange} />
|
||||
</div>, mountNode);
|
||||
````
|
||||
@@ -1,27 +1,48 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 三种大小
|
||||
en-US: Three sizes
|
||||
en-US: Three Sizes
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
三种大小的输入框,大的用在表单中,中的为默认。
|
||||
三种大小的输入框,若不设置,则为 `default`。
|
||||
|
||||
## en-US
|
||||
|
||||
The input box comes in three sizes. `large` is used in the form, while the medium size is the default.
|
||||
The input box comes in three sizes. `default` will be used if `size` is omitted.
|
||||
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import { DatePicker, Radio } from 'antd';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker size="large" />
|
||||
<DatePicker />
|
||||
<DatePicker size="small" />
|
||||
</div>
|
||||
, mountNode);
|
||||
class PickerSizesDemo extends React.Component {
|
||||
state = {
|
||||
size: 'default',
|
||||
};
|
||||
|
||||
handleSizeChange = (e) => {
|
||||
this.setState({ size: e.target.value });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { size } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Radio.Group value={size} onChange={this.handleSizeChange}>
|
||||
<Radio.Button value="large">Large</Radio.Button>
|
||||
<Radio.Button value="default">Default</Radio.Button>
|
||||
<Radio.Button value="small">Small</Radio.Button>
|
||||
</Radio.Group><br /><br />
|
||||
<DatePicker size={size} /><br />
|
||||
<MonthPicker size={size} /><br />
|
||||
<RangePicker size={size} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<PickerSizesDemo />, mountNode);
|
||||
````
|
||||
|
||||
@@ -1,69 +1,81 @@
|
||||
---
|
||||
order: 7
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 日期范围一
|
||||
en-US: Date range, case 1
|
||||
zh-CN: 自定义日期范围选择
|
||||
en-US: Customized Range Picker
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以设置 `disabledDate` 方法,来约束开始和结束日期。
|
||||
当 `RangePicker` 无法满足业务需求时,可以使用两个 `DatePicker` 实现类似的功能。
|
||||
> * 通过设置 `disabledDate` 方法,来约束开始和结束日期。
|
||||
> * 通过 `open` `onOpenChange` 来优化交互。
|
||||
|
||||
## en-US
|
||||
|
||||
You can use the `disabledDate` property to limit the start and end dates.
|
||||
|
||||
When `RangePicker` is not satisfied your requirements, try to implement similar functionality with two `DatePicker`.
|
||||
> * Use the `disabledDate` property to limit the start and end dates.
|
||||
> * Imporve user experience with `open` `onOpenChange`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
|
||||
const DateRange = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
startValue: null,
|
||||
endValue: null,
|
||||
endOpen: false,
|
||||
};
|
||||
},
|
||||
disabledStartDate(startValue) {
|
||||
if (!startValue || !this.state.endValue) {
|
||||
class DateRange extends React.Component {
|
||||
state = {
|
||||
startValue: null,
|
||||
endValue: null,
|
||||
endOpen: false,
|
||||
};
|
||||
|
||||
disabledStartDate = (startValue) => {
|
||||
const endValue = this.state.endValue;
|
||||
if (!startValue || !endValue) {
|
||||
return false;
|
||||
}
|
||||
return startValue.valueOf() > this.state.endValue.valueOf();
|
||||
},
|
||||
disabledEndDate(endValue) {
|
||||
if (!endValue || !this.state.startValue) {
|
||||
return startValue.valueOf() > endValue.valueOf();
|
||||
}
|
||||
|
||||
disabledEndDate = (endValue) => {
|
||||
const startValue = this.state.startValue;
|
||||
if (!endValue || !startValue) {
|
||||
return false;
|
||||
}
|
||||
return endValue.valueOf() <= this.state.startValue.valueOf();
|
||||
},
|
||||
onChange(field, value) {
|
||||
return endValue.valueOf() <= startValue.valueOf();
|
||||
}
|
||||
|
||||
onChange = (field, value) => {
|
||||
this.setState({
|
||||
[field]: value,
|
||||
});
|
||||
},
|
||||
onStartChange(value) {
|
||||
}
|
||||
|
||||
onStartChange = (value) => {
|
||||
this.onChange('startValue', value);
|
||||
},
|
||||
onEndChange(value) {
|
||||
}
|
||||
|
||||
onEndChange = (value) => {
|
||||
this.onChange('endValue', value);
|
||||
},
|
||||
handleStartOpenChange(open) {
|
||||
}
|
||||
|
||||
handleStartOpenChange = (open) => {
|
||||
if (!open) {
|
||||
this.setState({ endOpen: true });
|
||||
}
|
||||
},
|
||||
handleEndOpenChange(open) {
|
||||
}
|
||||
|
||||
handleEndOpenChange = (open) => {
|
||||
this.setState({ endOpen: open });
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
const { startValue, endValue, endOpen } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<DatePicker
|
||||
disabledDate={this.disabledStartDate}
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value={this.state.startValue}
|
||||
value={startValue}
|
||||
placeholder="Start"
|
||||
onChange={this.onStartChange}
|
||||
onOpenChange={this.handleStartOpenChange}
|
||||
@@ -72,18 +84,16 @@ const DateRange = React.createClass({
|
||||
disabledDate={this.disabledEndDate}
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value={this.state.endValue}
|
||||
value={endValue}
|
||||
placeholder="End"
|
||||
onChange={this.onEndChange}
|
||||
open={this.state.endOpen}
|
||||
open={endOpen}
|
||||
onOpenChange={this.handleEndOpenChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<DateRange />
|
||||
, mountNode);
|
||||
ReactDOM.render(<DateRange />, mountNode);
|
||||
````
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
order: 4
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 日期时间选择
|
||||
en-US: To choose time
|
||||
en-US: Choose Time
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
@@ -11,10 +11,11 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
This property provide an additional time selection. When `showTime` is an Object, its properties will be passed on to `TimePicker`, which is a built-in function.
|
||||
This property provide an additional time selection. When `showTime` is an Object, its properties will be passed on to built-in `TimePicker`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
function onChange(value, dateString) {
|
||||
console.log('Selected Time: ', value);
|
||||
@@ -22,6 +23,16 @@ function onChange(value, dateString) {
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<DatePicker showTime format="YYYY-MM-DD HH:mm:ss" placeholder="Select Time" onChange={onChange} />
|
||||
, mountNode);
|
||||
<div>
|
||||
<DatePicker
|
||||
showTime={{ format: 'HH:mm' }} format="YYYY-MM-DD HH:mm"
|
||||
placeholder="Select Time" onChange={onChange}
|
||||
/><br />
|
||||
<RangePicker
|
||||
showTime={{ format: 'HH:mm' }} format="YYYY-MM-DD HH:mm"
|
||||
placeholder={['Start Time', 'End Time']} onChange={onChange}
|
||||
/>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: DatePicker
|
||||
---
|
||||
|
||||
To select/input a date.
|
||||
To select or input a date. There are three kinds of picker:
|
||||
* DatePicker
|
||||
* MonthPicker
|
||||
* RangePicker
|
||||
|
||||
## When To Use
|
||||
|
||||
@@ -12,17 +15,14 @@ By clicking the input box, you can select a date from a popup calendar.
|
||||
|
||||
## API
|
||||
|
||||
Note: Part of locale of DatePicker, MonthPicker, RangePicker is read from value. So, please set the locale of moment correctly.
|
||||
**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')} />
|
||||
```
|
||||
@@ -53,6 +53,7 @@ The following APIs are shared by DatePicker, MonthPicker, RangePicker.
|
||||
| open | open state of picker | bool | - |
|
||||
| onOpenChange | a callback function, can be executed whether the popup calendar is popped up or closed | function(status) | - |
|
||||
| showTime | to provide an additional time selection | Object/Boolean | [TimePicker Options](/components/time-picker/#api) |
|
||||
| disabledTime | to specify the time that cannot be selected | function(date) | - |
|
||||
|
||||
### MonthPicker
|
||||
|
||||
@@ -62,6 +63,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
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: DatePicker
|
||||
subtitle: 日期选择框
|
||||
---
|
||||
|
||||
输入或选择日期的控件。
|
||||
输入或选择日期的控件,包括以下三种形式。
|
||||
* DatePicker
|
||||
* MonthPicker
|
||||
* RangePicker
|
||||
|
||||
## 何时使用
|
||||
|
||||
@@ -13,17 +16,14 @@ subtitle: 日期选择框
|
||||
|
||||
## API
|
||||
|
||||
注意:DatePicker、MonthPicker、RangePicker 部分 locale 是从 value 中读取,所以请先正确设置 moment 的 locale。
|
||||
**注意:**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')} />
|
||||
```
|
||||
@@ -54,6 +54,7 @@ moment.tz.setDefault('Asia/Shanghai')
|
||||
| open | 控制弹层是否展开 | bool | - |
|
||||
| onOpenChange | 弹出日历和关闭日历的回调 | function(status) | 无 |
|
||||
| showTime | 增加时间选择功能 | Object or Boolean | [TimePicker Options](/components/time-picker/#api) |
|
||||
| disabledTime | 不可选择的时间 | function(date) | 无 |
|
||||
|
||||
### MonthPicker
|
||||
|
||||
@@ -63,6 +64,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
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
padding: 0 2px;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
.@{calendar-prefix-cls}-next-year-btn {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
font-family: Arial, "Hiragino Sans GB", "Microsoft Yahei", "Microsoft Sans Serif", sans-serif;
|
||||
padding: 0 5px;
|
||||
font-size: 16px;
|
||||
@@ -168,7 +168,7 @@
|
||||
&-date {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
border-radius: @border-radius-sm;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@@ -281,7 +281,7 @@
|
||||
|
||||
.@{calendar-prefix-cls}-clear-btn:after {
|
||||
.iconfont-font("\e62e");
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
color: #ccc;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
@@ -291,7 +291,7 @@
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-clear-btn:hover:after {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-ok-btn {
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
.@{calendar-prefix-cls}-decade-panel-decade {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
.@{calendar-prefix-cls}-month-panel-month {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
right: 7px;
|
||||
background: #fff;
|
||||
top: 50%;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
color: #ccc;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
@@ -53,7 +53,7 @@
|
||||
cursor: pointer;
|
||||
transition: color 0.3s ease, opacity 0.15s ease;
|
||||
&:hover {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,14 +69,14 @@
|
||||
height: 12px;
|
||||
line-height: 12px;
|
||||
right: 8px;
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
top: 50%;
|
||||
margin-top: -6px;
|
||||
&:after {
|
||||
content: "\e6bb";
|
||||
font-family: "anticon";
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
font-size: @font-size-base;
|
||||
color: @text-color-secondary;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
vertical-align: bottom;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-range-picker-separator {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-range {
|
||||
@@ -53,7 +53,7 @@
|
||||
float: right;
|
||||
.@{calendar-prefix-cls} {
|
||||
&-time-picker-inner {
|
||||
margin-left: 21px;
|
||||
margin-left: 3%;
|
||||
border-left: 1px solid @border-color-split;
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@
|
||||
text-align: center;
|
||||
height: @input-box-height;
|
||||
line-height: @input-box-height;
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
&-right .@{calendar-prefix-cls}-date-input-wrap {
|
||||
@@ -164,6 +164,7 @@
|
||||
&.@{calendar-prefix-cls}-time {
|
||||
.@{calendar-timepicker-prefix-cls} {
|
||||
height: 207px;
|
||||
width: 97%;
|
||||
top: 68px;
|
||||
z-index: 2; // cover .ant-calendar-range .ant-calendar-in-range-cell > div (z-index: 1)
|
||||
&-panel {
|
||||
@@ -183,8 +184,6 @@
|
||||
border-top: 1px solid @border-color-split;
|
||||
}
|
||||
&-select {
|
||||
width: 71px;
|
||||
|
||||
ul {
|
||||
max-height: 206px;
|
||||
}
|
||||
@@ -209,3 +208,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-range.@{calendar-prefix-cls}-show-time-picker {
|
||||
.@{calendar-prefix-cls}-body {
|
||||
border-top-color: transparent;
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,16 @@
|
||||
position: relative;
|
||||
outline: none;
|
||||
list-style: none;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
text-align: left;
|
||||
background-color: #fff;
|
||||
background-clip: padding-box;
|
||||
line-height: 1.5;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
&-combobox {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-1-column,
|
||||
@@ -29,7 +33,7 @@
|
||||
width: 100%;
|
||||
}
|
||||
&-2-columns &-select {
|
||||
width: 115px;
|
||||
width: 50%;
|
||||
}
|
||||
&-1-column &-select,
|
||||
&-2-columns &-select {
|
||||
@@ -45,12 +49,12 @@
|
||||
|
||||
&-select {
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
border: 1px solid @border-color-split;
|
||||
border-width: 0 1px;
|
||||
margin-left: -1px;
|
||||
box-sizing: border-box;
|
||||
width: 77px;
|
||||
width: 33.6%;
|
||||
overflow: hidden;
|
||||
position: relative; // Fix chrome weird render bug
|
||||
|
||||
@@ -108,7 +112,7 @@
|
||||
color: @btn-disable-color;
|
||||
&:hover {
|
||||
background: transparent;
|
||||
cursor: @cursor-disabled;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,7 +123,7 @@
|
||||
padding: 0 2px;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
.@{calendar-prefix-cls}-year-panel-year {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
|
||||
@@ -2,10 +2,24 @@ 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;
|
||||
|
||||
function getColumns({ showHour, showMinute, showSecond }) {
|
||||
let column = 0;
|
||||
if (showHour) {
|
||||
column += 1;
|
||||
}
|
||||
if (showMinute) {
|
||||
column += 1;
|
||||
}
|
||||
if (showSecond) {
|
||||
column += 1;
|
||||
}
|
||||
return column;
|
||||
}
|
||||
|
||||
export default function wrapPicker(Picker, defaultFormat?) {
|
||||
const PickerWrapper = React.createClass({
|
||||
getDefaultProps() {
|
||||
@@ -68,11 +82,13 @@ export default function wrapPicker(Picker, defaultFormat?) {
|
||||
const rcTimePickerProps = {
|
||||
format: timeFormat,
|
||||
showSecond: timeFormat.indexOf('ss') >= 0,
|
||||
showMinute: timeFormat.indexOf('mm') >= 0,
|
||||
showHour: timeFormat.indexOf('HH') >= 0,
|
||||
};
|
||||
const columns = getColumns(rcTimePickerProps);
|
||||
const timePickerCls = classNames({
|
||||
[`${prefixCls}-time-picker-1-column`]: !(rcTimePickerProps.showSecond || rcTimePickerProps.showHour),
|
||||
[`${prefixCls}-time-picker-2-columns`]: rcTimePickerProps.showSecond !== rcTimePickerProps.showHour,
|
||||
[`${prefixCls}-time-picker-1-column`]: columns === 1,
|
||||
[`${prefixCls}-time-picker-2-columns`]: columns === 2,
|
||||
});
|
||||
const timePicker = props.showTime ? (
|
||||
<TimePickerPanel
|
||||
|
||||
@@ -34,17 +34,30 @@ export default class DropdownButton extends React.Component<DropdownButtonProps,
|
||||
};
|
||||
|
||||
render() {
|
||||
const [{ type, overlay, trigger, align, children, className, onClick, prefixCls, disabled }, restProps] =
|
||||
splitObject(this.props,
|
||||
['type', 'overlay', 'trigger', 'align', 'children', 'className', 'onClick', 'prefixCls', 'disabled']);
|
||||
const [{ type, overlay, trigger, align, children, className, onClick, prefixCls,
|
||||
disabled, visible, onVisibleChange }, restProps] = splitObject(this.props,
|
||||
['type', 'overlay', 'trigger', 'align', 'children', 'className', 'onClick',
|
||||
'prefixCls', 'disabled', 'visible', 'onVisibleChange']);
|
||||
const cls = classNames({
|
||||
[prefixCls]: true,
|
||||
[className]: !!className,
|
||||
});
|
||||
|
||||
const dropdownProps = {
|
||||
align,
|
||||
overlay,
|
||||
trigger: disabled ? [] : trigger,
|
||||
onVisibleChange,
|
||||
};
|
||||
|
||||
if ('visible' in this.props) {
|
||||
(dropdownProps as any).visible = visible;
|
||||
}
|
||||
|
||||
return (
|
||||
<ButtonGroup {...restProps} className={cls}>
|
||||
<Button type={type} onClick={onClick} disabled={disabled}>{children}</Button>
|
||||
<Dropdown align={align} overlay={overlay} trigger={disabled ? [] : trigger}>
|
||||
<Dropdown {...dropdownProps}>
|
||||
<Button type={type} disabled={disabled}>
|
||||
<Icon type="down" />
|
||||
</Button>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Navigation
|
||||
title: Dropdown
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 下拉菜单
|
||||
type: Views
|
||||
type: Navigation
|
||||
title: Dropdown
|
||||
---
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
top: -9999px;
|
||||
z-index: @zindex-dropdown;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
font-weight: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
@@ -53,15 +53,15 @@
|
||||
padding: 7px 16px;
|
||||
margin: 0;
|
||||
clear: both;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
font-weight: normal;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
> a {
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
display: block;
|
||||
padding: 7px 16px;
|
||||
margin: -7px -16px;
|
||||
@@ -108,7 +108,7 @@
|
||||
position: absolute;
|
||||
content: "\e61f";
|
||||
right: 16px;
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
.iconfont-size-under-12px(9px);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
}
|
||||
|
||||
.@{dropdown-prefix-cls}-link {
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
.@{iconfont-css-prefix}-down {
|
||||
.iconfont-size-under-12px(9px);
|
||||
}
|
||||
|
||||
@@ -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,30 +22,27 @@ 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 {
|
||||
expand: false,
|
||||
};
|
||||
},
|
||||
handleSearch(e) {
|
||||
class AdvancedSearchForm extends React.Component {
|
||||
state = {
|
||||
expand: false,
|
||||
};
|
||||
|
||||
handleSearch = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Received values of form: ', values);
|
||||
});
|
||||
},
|
||||
handleReset() {
|
||||
}
|
||||
|
||||
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;
|
||||
const formItemLayout = {
|
||||
@@ -58,10 +55,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 +65,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,50 +73,54 @@ 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>
|
||||
);
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<AdvancedSearchForm />, mountNode);
|
||||
const WrappedAdvancedSearchForm = Form.create()(AdvancedSearchForm);
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<WrappedAdvancedSearchForm />
|
||||
<div className="search-result-list">Search Result List</div>
|
||||
</div>,
|
||||
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>
|
||||
#components-form-demo-advanced-search .ant-form-horizontal {
|
||||
max-width: none;
|
||||
}
|
||||
#components-form-demo-advanced-search .search-result-list {
|
||||
margin-top: 16px;
|
||||
border: 1px dashed #e9e9e9;
|
||||
border-radius: 6px;
|
||||
background-color: #fafafa;
|
||||
min-height: 200px;
|
||||
text-align: center;
|
||||
padding-top: 80px;
|
||||
}
|
||||
</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
|
||||
@@ -14,85 +14,109 @@ title:
|
||||
Add or remove form items dynamically.
|
||||
|
||||
````jsx
|
||||
import { Form, Input, Button } from 'antd';
|
||||
import { Form, Input, Icon, Button } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
|
||||
let uuid = 0;
|
||||
let Demo = React.createClass({
|
||||
class DynamicFieldSet extends React.Component {
|
||||
componentWillMount() {
|
||||
this.props.form.setFieldsValue({
|
||||
keys: [0],
|
||||
});
|
||||
},
|
||||
remove(k) {
|
||||
}
|
||||
|
||||
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');
|
||||
// We need at least one passenger
|
||||
if (keys.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// can use data-binding to set
|
||||
form.setFieldsValue({
|
||||
keys,
|
||||
keys: keys.filter(key => key !== k),
|
||||
});
|
||||
},
|
||||
add() {
|
||||
}
|
||||
|
||||
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) {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((errors, values) => {
|
||||
if (errors) {
|
||||
console.log(errors);
|
||||
}
|
||||
console.log(values);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator, getFieldValue } = this.props.form;
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 18 },
|
||||
labelCol: { span: 4 },
|
||||
wrapperCol: { span: 20 },
|
||||
};
|
||||
const formItemLayoutWithOutLabel = {
|
||||
wrapperCol: { span: 20, offset: 4 },
|
||||
};
|
||||
|
||||
const formItems = getFieldValue('keys').map((k) => {
|
||||
const keys = getFieldValue('keys');
|
||||
const formItems = keys.map((k, index) => {
|
||||
return (
|
||||
<Form.Item {...formItemLayout} label={`good friend${k}:`} key={k}>
|
||||
{getFieldDecorator(`name${k}`, {
|
||||
<FormItem
|
||||
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
|
||||
label={index === 0 ? 'Passengers' : ''}
|
||||
required={false}
|
||||
key={k}
|
||||
>
|
||||
{getFieldDecorator(`names-${k}`, {
|
||||
validateTrigger: ['onChange', 'onBlur'],
|
||||
rules: [{
|
||||
required: true,
|
||||
whitespace: true,
|
||||
message: "Your good friend's name",
|
||||
message: "Please input passenger's name or delete this field.",
|
||||
}],
|
||||
})(
|
||||
<Input style={{ width: '60%', marginRight: 8 }} />
|
||||
)}
|
||||
<Button onClick={() => this.remove(k)}>remove</Button>
|
||||
</Form.Item>
|
||||
<Icon
|
||||
className="delete-button"
|
||||
type="minus-circle-o"
|
||||
disabled={keys.length === 1}
|
||||
onClick={() => this.remove(k)}
|
||||
/>
|
||||
</FormItem>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<Form horizontal>
|
||||
{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>
|
||||
</Form.Item>
|
||||
<FormItem {...formItemLayoutWithOutLabel}>
|
||||
<Button type="dashed" onClick={this.add} style={{ width: '60%' }}>
|
||||
<Icon type="plus" /> Add
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Demo = Form.create()(Demo);
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
const WrappedDynamicFieldSet = Form.create()(DynamicFieldSet);
|
||||
ReactDOM.render(<WrappedDynamicFieldSet />, mountNode);
|
||||
````
|
||||
|
||||
````css
|
||||
#components-form-demo-dynamic-form-item .delete-button {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
font-size: 24px;
|
||||
color: #999;
|
||||
}
|
||||
#components-form-demo-dynamic-form-item .delete-button[disabled] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
````
|
||||
|
||||
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);
|
||||
````
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user