mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-09 10:59:19 +08:00
Compare commits
309 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6ee287924 | ||
|
|
919e25d6d9 | ||
|
|
39b4ff438f | ||
|
|
be8520de3c | ||
|
|
8e8b991ba7 | ||
|
|
b1d60f5ce1 | ||
|
|
5903fdb19f | ||
|
|
4b5d54671a | ||
|
|
5ab265a009 | ||
|
|
c540ceb8eb | ||
|
|
450a497412 | ||
|
|
a5ff8e5de0 | ||
|
|
07e06709f8 | ||
|
|
980e2b1427 | ||
|
|
713a0bcdc5 | ||
|
|
37ec04b21a | ||
|
|
01460c0297 | ||
|
|
f44584845b | ||
|
|
f883a6f351 | ||
|
|
b3ed289904 | ||
|
|
f36c6195b8 | ||
|
|
ee0a7ce3bb | ||
|
|
619b0ed628 | ||
|
|
99cad890ef | ||
|
|
7e2ba7e6d3 | ||
|
|
c3769e3b96 | ||
|
|
f597c32aa6 | ||
|
|
4d6f8e96b9 | ||
|
|
ae6de361e2 | ||
|
|
1a9456f03a | ||
|
|
05c5115991 | ||
|
|
8e26b6823a | ||
|
|
5174801b95 | ||
|
|
ac0b4bacc5 | ||
|
|
e7cd474894 | ||
|
|
789b54905c | ||
|
|
71d2a991ed | ||
|
|
8610eb054f | ||
|
|
71d3af310a | ||
|
|
89228118af | ||
|
|
0ca1a990be | ||
|
|
74755fef99 | ||
|
|
396f81dbab | ||
|
|
a4a3b5e12d | ||
|
|
78adc05973 | ||
|
|
b524e1fe7e | ||
|
|
8444ad209d | ||
|
|
ad52250256 | ||
|
|
e1ba74e5fc | ||
|
|
6602df16e6 | ||
|
|
17b158c091 | ||
|
|
c2d94ad84d | ||
|
|
57a01e1b9f | ||
|
|
cdc571b17e | ||
|
|
d69610a17f | ||
|
|
e13c1a678d | ||
|
|
248dbc2429 | ||
|
|
37d5f895d2 | ||
|
|
70ca0281ed | ||
|
|
bbf5cb75c3 | ||
|
|
30eacdfb1b | ||
|
|
f8314a6b1e | ||
|
|
0ea890a0a4 | ||
|
|
0fdd13e5d6 | ||
|
|
15637c885b | ||
|
|
163ec46cbb | ||
|
|
2b5abd6dec | ||
|
|
e25323882a | ||
|
|
e124cabc5b | ||
|
|
7149d1fdff | ||
|
|
5be1b9c33c | ||
|
|
7c273912fd | ||
|
|
87163dfcd6 | ||
|
|
05251682f1 | ||
|
|
31be3717ad | ||
|
|
ca7ed4c07d | ||
|
|
64a29dfd1a | ||
|
|
b5c5f0b5d4 | ||
|
|
4f91fe61bf | ||
|
|
7f16ded760 | ||
|
|
9bc98b6471 | ||
|
|
e8351b8104 | ||
|
|
6d610de157 | ||
|
|
be7f540fba | ||
|
|
814ee7365a | ||
|
|
5fd4139661 | ||
|
|
e14928b4f9 | ||
|
|
19a04e52f4 | ||
|
|
21ca50fca1 | ||
|
|
38f94990f8 | ||
|
|
d18f100721 | ||
|
|
b10e7c4e82 | ||
|
|
9552f80cde | ||
|
|
ad0108dfd5 | ||
|
|
a6e2037c06 | ||
|
|
ac4a9086a0 | ||
|
|
12d0aedeca | ||
|
|
36ffe7e1dc | ||
|
|
b86f4eeaad | ||
|
|
3ceb619b92 | ||
|
|
baa78bfa5f | ||
|
|
8c2f99fd3e | ||
|
|
50057739bf | ||
|
|
3a445f3e75 | ||
|
|
be13326a1b | ||
|
|
93b14da4a6 | ||
|
|
21db29bd53 | ||
|
|
d58c0780f9 | ||
|
|
042c014a38 | ||
|
|
aff9d8fc62 | ||
|
|
b7b12b657c | ||
|
|
0feaf95629 | ||
|
|
076540c83e | ||
|
|
3db0610d52 | ||
|
|
7222944347 | ||
|
|
322ebf0039 | ||
|
|
c2519e776b | ||
|
|
33b604f7a8 | ||
|
|
4c101275a5 | ||
|
|
4c1b2369d7 | ||
|
|
cbff10db15 | ||
|
|
b7cf33d1eb | ||
|
|
b828a599fb | ||
|
|
f3869270ae | ||
|
|
2989e8dba0 | ||
|
|
6d8df2ac25 | ||
|
|
fd96b4a784 | ||
|
|
af8f4dc5c3 | ||
|
|
8da79f4b34 | ||
|
|
247d78990e | ||
|
|
acb56281f8 | ||
|
|
fafd83cadc | ||
|
|
7e96ae1a6a | ||
|
|
3c381c6dd1 | ||
|
|
292a91a777 | ||
|
|
89ed0dcb35 | ||
|
|
77301c378f | ||
|
|
22d2f9eb01 | ||
|
|
3078819535 | ||
|
|
6471e5d4f0 | ||
|
|
1e585135aa | ||
|
|
6057821f39 | ||
|
|
33c58a8ef6 | ||
|
|
b09e03d82a | ||
|
|
a2e0e40caa | ||
|
|
f409df8d84 | ||
|
|
a148bc7b79 | ||
|
|
4077ffb58c | ||
|
|
bb4bc61556 | ||
|
|
0fc5a0ece5 | ||
|
|
6458280cb3 | ||
|
|
0f73b5d3f7 | ||
|
|
14beee1fe1 | ||
|
|
e0312f65ee | ||
|
|
389c7c4f10 | ||
|
|
59fe98a194 | ||
|
|
2955600642 | ||
|
|
d4ed303bcd | ||
|
|
ff458a2c3f | ||
|
|
06ffd9ca04 | ||
|
|
251d882101 | ||
|
|
129baddc44 | ||
|
|
968488a2fa | ||
|
|
00d710cef0 | ||
|
|
ddc242a9cb | ||
|
|
d6a554823f | ||
|
|
fd1d9661c0 | ||
|
|
07b24f4edd | ||
|
|
dbd2bd1866 | ||
|
|
8b420c41bb | ||
|
|
96d53aefb8 | ||
|
|
8e2f72ffe0 | ||
|
|
29229ebee7 | ||
|
|
e1ad91119a | ||
|
|
76bf36a79b | ||
|
|
aa87fcb01e | ||
|
|
1ed9fed2cf | ||
|
|
7c4f6e8b2a | ||
|
|
df7ef9a833 | ||
|
|
9b17a943f5 | ||
|
|
7404b7f36c | ||
|
|
963120f702 | ||
|
|
b7d508e166 | ||
|
|
cafeb8e3eb | ||
|
|
99dca86904 | ||
|
|
09d5e36cfa | ||
|
|
6e0865f691 | ||
|
|
eb17aae25c | ||
|
|
593435ce65 | ||
|
|
c4f58e7027 | ||
|
|
b76910f63f | ||
|
|
12d3046687 | ||
|
|
d5d0501ac7 | ||
|
|
c7c85e3d5d | ||
|
|
78af67a057 | ||
|
|
604584931e | ||
|
|
77e21d33ea | ||
|
|
bdb4483ef5 | ||
|
|
97c2d58d15 | ||
|
|
f09c799bba | ||
|
|
bc8353729c | ||
|
|
bf03d954d4 | ||
|
|
413479a5b9 | ||
|
|
5e0b8df412 | ||
|
|
3413774ae5 | ||
|
|
41b9a79edb | ||
|
|
35b751da15 | ||
|
|
f3545ccdc7 | ||
|
|
71abb96de7 | ||
|
|
dd7fb9d351 | ||
|
|
4adf0b2571 | ||
|
|
9e01b24272 | ||
|
|
1b8030ec59 | ||
|
|
2747aa341d | ||
|
|
030c745e1b | ||
|
|
dd0d4214d1 | ||
|
|
6eef4d0a42 | ||
|
|
6e6b1ccdec | ||
|
|
832c524b32 | ||
|
|
bc4143f8a3 | ||
|
|
be31f17bca | ||
|
|
dcb75a789d | ||
|
|
ffc182f4eb | ||
|
|
fbf09e86af | ||
|
|
7f2159e928 | ||
|
|
04ee8526ab | ||
|
|
6c0d6d302a | ||
|
|
06f205874f | ||
|
|
20495dd5ba | ||
|
|
d5c5219111 | ||
|
|
5e99a93930 | ||
|
|
bd81877cf8 | ||
|
|
8a6d9b92b7 | ||
|
|
d93cfdef09 | ||
|
|
e86f17186b | ||
|
|
6d91a3eb4a | ||
|
|
d95379cfa5 | ||
|
|
dbde26e560 | ||
|
|
1479726932 | ||
|
|
9368e2df87 | ||
|
|
7f8cb838e3 | ||
|
|
0f7794946f | ||
|
|
f4b8a58480 | ||
|
|
6019245365 | ||
|
|
3fd9397174 | ||
|
|
f1e38a1573 | ||
|
|
013df45a70 | ||
|
|
5ee4d20e2a | ||
|
|
c9017b6c6c | ||
|
|
05e702a2b4 | ||
|
|
8e166915a9 | ||
|
|
9c6fef0604 | ||
|
|
b6f8ab89c7 | ||
|
|
56e3384c6b | ||
|
|
b5a52d26f2 | ||
|
|
70a42545e3 | ||
|
|
fb38e55cc0 | ||
|
|
c7471a4653 | ||
|
|
726f0466bc | ||
|
|
a4261f9344 | ||
|
|
0616b05583 | ||
|
|
d0c3752a4e | ||
|
|
3a5fce7256 | ||
|
|
74e36325a2 | ||
|
|
3a3d550b54 | ||
|
|
013932e6d3 | ||
|
|
cd6ad64cab | ||
|
|
81dd432e31 | ||
|
|
4535e9d4f1 | ||
|
|
4956dd8042 | ||
|
|
548d8c9c51 | ||
|
|
8b64882562 | ||
|
|
6682a56922 | ||
|
|
e97977b891 | ||
|
|
b45146486a | ||
|
|
8b02a21d36 | ||
|
|
be43e56835 | ||
|
|
7f8f89cbff | ||
|
|
a1e186b8a3 | ||
|
|
3d079af7cd | ||
|
|
1f6107e94a | ||
|
|
e40c2a7f45 | ||
|
|
d9053a2526 | ||
|
|
4b1857d587 | ||
|
|
b1c41c665e | ||
|
|
c85758fd01 | ||
|
|
52c8f34a73 | ||
|
|
4ea20e696c | ||
|
|
a268dc8d62 | ||
|
|
262ed8eec3 | ||
|
|
4bc28ac471 | ||
|
|
4101d182e0 | ||
|
|
14dbcb95ed | ||
|
|
14fa376dff | ||
|
|
6a3e6f55cf | ||
|
|
fa5491a390 | ||
|
|
4ad5985df7 | ||
|
|
bb720aaab9 | ||
|
|
8ab4aeb9c4 | ||
|
|
e444dc5e39 | ||
|
|
b9d94971e4 | ||
|
|
d50ec436d5 | ||
|
|
e1c74eb799 | ||
|
|
d016471638 | ||
|
|
754c94c447 | ||
|
|
74d1c5e6b6 | ||
|
|
04a5cc2a8b | ||
|
|
b52053051c | ||
|
|
74d81c2d07 |
14
.github/lock.yml
vendored
Normal file
14
.github/lock.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Configuration for lock-threads - https://github.com/dessant/lock-threads
|
||||
|
||||
# Number of days of inactivity before a closed issue or pull request is locked
|
||||
daysUntilLock: 365
|
||||
# Comment to post before locking. Set to `false` to disable
|
||||
lockComment: >
|
||||
This thread has been automatically locked because it has not had recent
|
||||
activity. Please open a new issue for related bugs and link to relevant
|
||||
comments in this thread.
|
||||
# Issues or pull requests with these labels will not be locked
|
||||
# exemptLabels:
|
||||
# - no-locking
|
||||
# Limit to only `issues` or `pulls`
|
||||
only: issues
|
||||
@@ -15,6 +15,165 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 3.6.3
|
||||
|
||||
`2018-06-17`
|
||||
|
||||
- 🐞 Fixed that capitalized extension of Upload image url couldn't be recognaized. [#10928](https://github.com/ant-design/ant-design/pull/10928) [@sliwey](https://github.com/sliwey)
|
||||
- 🐞 Fixed missing border of InputNumber when browser is zoomed in. [#10562](https://github.com/ant-design/ant-design/issues/10562)
|
||||
- 🐞 Fixed that fixed element inside Spin cannot be fixed. [#10196](https://github.com/ant-design/ant-design/issues/10196)
|
||||
- 🐞 Fixed broken border style of small table. [#9754](https://github.com/ant-design/ant-design/issues/9754)
|
||||
- 🐞 Fixed missing `className` prop of Table's `filterIcon`. [#10937](https://github.com/ant-design/ant-design/issues/10937)
|
||||
- 🐞 Fixed that Affix `offsetTop` and `offsetBottom` cannot be updated. [#10874](https://github.com/ant-design/ant-design/issues/10874)
|
||||
- TypeScript
|
||||
- 🐞 Fixed TreeSelect `TS2339` error. [#10868](https://github.com/ant-design/ant-design/issues/10868)
|
||||
- 🌟 Added Form arguments definitions of `validateMessages` and `onFieldsChange`.
|
||||
- 🌟 Improved Button prop definitions. [#10877](https://github.com/ant-design/ant-design/pull/10877) [@zheeeng](https://github.com/zheeeng)
|
||||
- 🌟 Added `backfill` prop for AutoComplete. [#10909](https://github.com/ant-design/ant-design/pull/10909) [@zhanba](https://github.com/zhanba)
|
||||
|
||||
## 3.6.2
|
||||
|
||||
`2018-06-09`
|
||||
|
||||
- 🐞 Fix the wrong status of check all checkbox in Table when data change. [#10629](https://github.com/ant-design/ant-design/issues/10629)
|
||||
- 🐞 Fix border style of Button.Group.
|
||||
- 🐞 Fix file list being reversed when `beforeUpload` returns `false` in Upload component. [#10681](https://github.com/ant-design/ant-design/issues/10681)
|
||||
- 🐞 Fix overflow of cell content in Calendar. [#10808](https://github.com/ant-design/ant-design/pull/10808) [@Yangzhedi](https://github.com/ant-design/Yangzhedi)
|
||||
- 🐞 Fix the processing color of Badge not follows the `primary-color`.
|
||||
- Spin
|
||||
- 🐞 Fix custom icon does not follow the value of `size`. [#10786](https://github.com/ant-design/ant-design/issues/10786)
|
||||
- 🐞 Fix no `delay` issue when sets `spinning` to `true` as default.[#10727](https://github.com/ant-design/ant-design/pull/10727) [@dreamerblue](https://github.com/dreamerblue)
|
||||
- TypeScript
|
||||
- 🐞 Fix Menu type definition. [#10773](https://github.com/ant-design/ant-design/issues/10773)
|
||||
- 🐞 Fix AutoComplete type definition. [#10745](https://github.com/ant-design/ant-design/issues/10745) [#10619](https://github.com/ant-design/ant-design/issues/10619)
|
||||
- 🐞 Fix Tree type definition. [#10841](https://github.com/ant-design/ant-design/pull/10841) [@Voronar](https://github.com/Voronar)
|
||||
- 🐞 Fix Checkbox.Group definition. [#10677](https://github.com/ant-design/ant-design/pull/10677)
|
||||
|
||||
## 3.6.0
|
||||
|
||||
`2018-06-02`
|
||||
|
||||
* 🌟 `Form`'s error message now can be customized with ReactNode. [#10136](https://github.com/ant-design/ant-design/issues/10136) [@lovekonakona](https://github.com/lovekonakona)
|
||||
* 🌟 `List` support customized configuration for position of pagination. [#10581](https://github.com/ant-design/ant-design/pull/10581) [@zheeeng](https://github.com/zheeeng)
|
||||
* 🌟 `Layout.Sider` now can be configured with `light` or `dark` theme. [#10142](https://github.com/ant-design/ant-design/issues/10142) [@pd4d10](https://github.com/pd4d10)
|
||||
* 🌟 Ant Design official site now supports offline mode. [#10625](https://github.com/ant-design/ant-design/issues/10625)
|
||||
* 🌟 `Transfer` adding `style` and `operationStyle` props for further customization. [@eduludi](https://github.com/eduludi)
|
||||
* 🌟 `Message` adds a promisfied interface to handle callback. [#10421](https://github.com/ant-design/ant-design/issues/10421) [@zhujinxuan](https://github.com/zhujinxuan)
|
||||
* 🐞 Fix compilation issue with typescript@v2.9.1 . [#10729](https://github.com/ant-design/ant-design/issues/10729) [@karol-majewski](https://github.com/karol-majewski)
|
||||
* 🐞 Fix a bug in `Menu` where outer menu item not highlighting while inner item is selected. [#8666](https://github.com/ant-design/ant-design/issues/8666) [@stonehank](https://github.com/stonehank)
|
||||
* 🐞 Affix `offsetBottom` not working. [#10674](https://github.com/ant-design/ant-design/issues/10674)
|
||||
|
||||
## 3.5.4
|
||||
|
||||
`2018-05-26`
|
||||
|
||||
- 🐞 Fix `showSearch` on `Cascader` not working.[968488a2](https://github.com/ant-design/ant-design/commit/968488a2fac9bcb16bee9f0c248f49bca00dbec6)
|
||||
- 🐞 `Badge[status]` support `Tooltip`.[#10626](https://github.com/ant-design/ant-design/issues/10626)
|
||||
- 🐞 Fix `text-align` on parent element affects `Spin`.[#10643](https://github.com/ant-design/ant-design/pull/10643) [@wmzhong](https://github.com/wmzhong)
|
||||
- 💄 `Table` break line style change from `break-all` to `break-word`.[#10655](https://github.com/ant-design/ant-design/pull/10655) [@clinyong](https://github.com/clinyong)
|
||||
- 🌟 When `Search` not define `enterButton`, click search icon will trigger `onSearch`. [36ffe7e1](https://github.com/ant-design/ant-design/commit/36ffe7e1dc9d9473c8c68168ab79b7a03a604702)
|
||||
|
||||
## 3.5.3
|
||||
|
||||
`2018-05-20`
|
||||
|
||||
- 🐞 Fix `Affix` with offsetTop === 0, value becomes `undefined` problem [#10566](https://github.com/ant-design/ant-design/pull/10566)
|
||||
- 🐞 Fixed issue with shaded `Input.Group` component shadows[#10230](https://github.com/ant-design/ant-design/issues/10230)
|
||||
- 🐞 Fixed issue where the `Transfer` component checkbox event fired twice [#10480](https://github.com/ant-design/ant-design/issues/10480)
|
||||
- 💄 Unifying the name of the variable [12d3046](https://github.com/ant-design/ant-design/commit/12d3046687a0dcdb51fece08dd2bea64f185cc40)
|
||||
- 💄 Fine-tuned the style of `Dropdown` [8e2f72f](https://github.com/ant-design/ant-design/commit/8e2f72ffe0eb300f5997296726b02246bf990c8f)
|
||||
- 💄 The components of the Chinese document will now be demonstrated using Chinese language packages. [9b17a94](https://github.com/ant-design/ant-design/commit/9b17a943f5d57d40d65041b7b0c247add09d2851)
|
||||
- 💄 The main theme switch was changed to `antd-theme-generato`, thanks to the work of [@mzohaibqc](https://github.com/mzohaibqc).
|
||||
- TypeScript
|
||||
- 🐞 Fixed an issue with the type of gutter attribute in `Row` [b7d508e](https://github.com/ant-design/ant-design/commit/b7d508e1662bf20a0cacbe6440a2ce31a65a8a59)
|
||||
- 💄 Improved the `Form` component type [#10564](https://github.com/ant-design/ant-design/pull/10564)
|
||||
- 💄 Improved the `Button` and `Tag` types[1ed9fed](https://github.com/ant-design/ant-design/commit/1ed9fed2cf1c99b947359fafb101b2e58213cb48)
|
||||
|
||||
## 3.5.2
|
||||
|
||||
`2018-05-13`
|
||||
|
||||
- 🐞 Fixed `Table` filter doesn't work when click checkbox. [#10452](https://github.com/ant-design/ant-design/issues/10452)
|
||||
- 🐞 Fixed `Cascader` displayRender z-index issue. [#10433](https://github.com/ant-design/ant-design/issues/10433)
|
||||
- 🐞 Fixed `Button` Types of property 'ref' are incompatible. [#10405](https://github.com/ant-design/ant-design/issues/10405)
|
||||
- 🐞 Fixed the height of `Form` item when checks position is dithered. [#10445](https://github.com/ant-design/ant-design/issues/10445)
|
||||
- 🌟 Allow to use any CSS units for `Layout` width. [#10479](https://github.com/ant-design/ant-design/pull/10479)
|
||||
|
||||
## 3.5.1
|
||||
|
||||
`2018-05-09`
|
||||
|
||||
- 🐞 Fixed broken style of Input.Group under Form. [#10371](https://github.com/ant-design/ant-design/issues/10371)
|
||||
- 🐞 Fixed overlay style of Select. [#10383](https://github.com/ant-design/ant-design/issues/10383)
|
||||
- 🐞 Remove focused style of Collapse.
|
||||
- 🐞 Remove unnecessary `z-index` of Input.Group and Checkbox. [#9840](https://github.com/ant-design/ant-design/issues/9840) [#10385](https://github.com/ant-design/ant-design/issues/10385)
|
||||
- 🐞 Fixed that monospaced font family can't be bold.
|
||||
- Table
|
||||
- 💄 Rewrited the editable table demo. [#10119](https://github.com/ant-design/ant-design/pull/10119)
|
||||
- 🐞 Fixed that table column overlay each other. [#9822](https://github.com/ant-design/ant-design/issues/9822)
|
||||
- TypeScript
|
||||
- 🐞 Fixed Breadcrumb.Item type. [#10372](https://github.com/ant-design/ant-design/pull/10372) [@karol-majewski](https://github.com/karol-majewski)
|
||||
- 🐞 Fixed Table `rowSelection` type。[#10374](https://github.com/ant-design/ant-design/issues/10374)
|
||||
|
||||
## 3.5.0
|
||||
|
||||
`2018-05-04`
|
||||
|
||||
- 🌟 Add `title` prop to `Badge` that shows when hovering it. [74d81c2](https://github.com/ant-design/ant-design/commit/74d81c2d078a3c84b3e44cbfbdd99b8f479ea71d) [@ludwigbacklund](https://github.com/ludwigbacklund)
|
||||
- 🌟 Add `successPercent` as `Progress[format]` argument. [#10096](https://github.com/ant-design/ant-design/issues/10096)
|
||||
- 🌟 Update `rc-notification` to 3.1.0 so that `Notification` support set `maxCount`. [#10161](https://github.com/ant-design/ant-design/pull/10161) [@jzhangs](https://github.com/jzhangs)
|
||||
- 🌟 Update `rc-cascader` to 1.13.0 so that `Cascader` support set `filedNames`. [react-component/cascader#23](https://github.com/react-component/cascader/pull/23) [@405go](https://github.com/405go)
|
||||
- 🌟 Add ability to update `Notification` props by key. [react-component/notification#40](https://github.com/react-component/notification/pull/40) [@yevhen-hryhorevskyi](https://github.com/yevhen-hryhorevskyi)
|
||||
- 🌟 `List` support pagination by default. [#10135](https://github.com/ant-design/ant-design/pull/10135)
|
||||
- Table
|
||||
- 🌟 Column `sorter` function is passed `sortOrder` as param. [#10306](https://github.com/ant-design/ant-design/pull/10306) [@kumarashwin](https://github.com/kumarashwin)
|
||||
- 🐞 Fix merged header cell border. [#10359](https://github.com/ant-design/ant-design/issues/10359)
|
||||
- 🐞 Fix lost of user selection on data updates. [#10332](https://github.com/ant-design/ant-design/pull/10332) [@chrvadala](https://github.com/chrvadala)
|
||||
- `Menu` upgrade `rc-menu` to `7.x` [#10305](https://github.com/ant-design/ant-design/pull/10305)
|
||||
- 🌟 Better aria-* attributes support. [react-component/menu#137](https://github.com/react-component/menu/pull/137)
|
||||
- 🌟 Improve Menu performance by avoiding unnecessary updates. [react-component/menu#133](https://github.com/react-component/menu/pull/133)
|
||||
- 🌟 Support passing props through to MenuItem list item. [react-component/menu#135](https://github.com/react-component/menu/pull/135)
|
||||
- 🐞 Minor key shortcut bug fixes. [react-component/menu#132](https://github.com/react-component/menu/pull/132)
|
||||
- Collapse
|
||||
- 🌟 Support custom `Collapse` styles with less. [#9943](https://github.com/ant-design/ant-design/pull/9943) [@davidhatten](https://github.com/davidhatten)
|
||||
- 🌟 Update `rc-collapse` to 1.9.0 to add `Collapse` keyboard support. [react-component/collapse#84](https://github.com/react-component/collapse/pull/84/) [@kossel](https://github.com/kossel)
|
||||
- Select
|
||||
- 🐞 Fix type for `placeholder`. [#10282](https://github.com/ant-design/ant-design/pull/10282) [@thomasthiebaud](https://github.com/thomasthiebaud)
|
||||
- 🐞 Fix extra space taken up when arrow disabled. [#10296](https://github.com/ant-design/ant-design/pull/10296)
|
||||
- 🐞 Fix property `value` typescript type. [#10336](https://github.com/ant-design/ant-design/pull/10336) [@paranoidjk](https://github.com/paranoidjk)
|
||||
- Input
|
||||
- 🐞 Fix `Input.Search` not disable enter button when disabled prop is true. [#10040](https://github.com/ant-design/ant-design/issues/10040)
|
||||
- 🐞 Fix `Input.Group` align issue in Form. [#10281](https://github.com/ant-design/ant-design/issues/10281)
|
||||
- Form
|
||||
- 🐞 Fix typing for `Form.onValuesChange`. [#10231](https://github.com/ant-design/ant-design/pull/10231) [@whtsky](https://github.com/whtsky)
|
||||
- 🐞 Fix typescript interface `ComponentDecorator`. [#10324](https://github.com/ant-design/ant-design/pull/10324) [@paranoidjk](https://github.com/paranoidjk)
|
||||
- 🐞 Fix dashed `Divider`. [#10216](https://github.com/ant-design/ant-design/issues/10216)
|
||||
- 🐞 Fix `Spin` container interaction. [#10227](https://github.com/ant-design/ant-design/issues/10227)
|
||||
- 🐞 Fix `Notification` icon hover color. [#10272](https://github.com/ant-design/ant-design/issues/10272)
|
||||
- 🐞 Fix `Upload` property `lastModifiedDate` name. [#10315](https://github.com/ant-design/ant-design/pull/10315) [@danielg2002](https://github.com/danielg2002)
|
||||
- 🐞 Fix `Button` props type, use `React.HTMLProps`. [#10229](https://github.com/ant-design/ant-design/pull/10229) [@whtsky](https://github.com/whtsky)
|
||||
- 🐞 Fix less var naming convention. [#10275](https://github.com/ant-design/ant-design/issues/10275)
|
||||
|
||||
## 3.4.5
|
||||
|
||||
`2018-05-03`
|
||||
|
||||
- 🐞 Fix file object is empty and file name not showing in Upload. [#10319](https://github.com/ant-design/ant-design/issues/10319)
|
||||
|
||||
## 3.4.4
|
||||
|
||||
`2018-04-28`
|
||||
|
||||
- 🐞 Fix that Upload file in`onChange({ file })` is not a File instance introduced in `3.4.2`. [#10293](https://github.com/ant-design/ant-design/issues/10293)
|
||||
- 🐞 Fix style lose bug when use tree shaking in webpack@4. [#10217](https://github.com/ant-design/ant-design/pull/10217) [@whtsky](https://github.com/whtsky)
|
||||
|
||||
## 3.4.3
|
||||
|
||||
`2018-04-23`
|
||||
|
||||
- 🐞 Fix style lose bug when use tree shaking in webpack@4. [#10197](https://github.com/ant-design/ant-design/pull/10197) [@Aladdin-ADD](https://github.com/Aladdin-ADD)
|
||||
- 🐞 Fix `Menu` item's clickable region in dark theme. [#10187](https://github.com/ant-design/ant-design/pull/10187) [@dgeibi ](https://github.com/dgeibi )
|
||||
|
||||
## 3.4.2
|
||||
|
||||
`2018-04-22`
|
||||
@@ -356,7 +515,7 @@ Happy 2018 !~ 2018 2018 2018 coming!~~~
|
||||
|
||||
`2017-12-04`
|
||||
|
||||
Learn more in the [Ant Design 3.0 announcement post](https://medium.com/ant-design/announcing-ant-design-3-0-70e3e65eca0c)!
|
||||
Learn more in the [Ant Design 3.0 announcement post](https://medium.com/ant-design/announcing-ant-design-3-0-70e3e65eca0c).
|
||||
|
||||
### Major Changes
|
||||
|
||||
|
||||
@@ -15,6 +15,166 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 3.6.3
|
||||
|
||||
`2018-06-17`
|
||||
|
||||
- 🐞 修复 Upload 图片文件后缀名为大写时无法正确识别的问题。[#10928](https://github.com/ant-design/ant-design/pull/10928) [@sliwey](https://github.com/sliwey)
|
||||
- 🐞 修复 InputNumber 在浏览器缩放时边框样式丢失的问题。[#10562](https://github.com/ant-design/ant-design/issues/10562)
|
||||
- 🐞 修复 Spin 内使用 `position: fixed` 的元素无法固定的问题。[#10196](https://github.com/ant-design/ant-design/issues/10196)
|
||||
- 🐞 修复小号表格下固定列的边框样式问题。[#9754](https://github.com/ant-design/ant-design/issues/9754)
|
||||
- 🐞 修复 Table `filterIcon` 的 `className` 属性失效的问题。[#10937](https://github.com/ant-design/ant-design/issues/10937)
|
||||
- 🐞 修复 Affix 的 `offsetTop` 和 `offsetBottom` 无法动态修改的问题。[#10874](https://github.com/ant-design/ant-design/issues/10874)
|
||||
- TypeScript
|
||||
- 🐞 修复 TreeSelect `TS2339` 错误。[#10868](https://github.com/ant-design/ant-design/issues/10868)
|
||||
- 🌟 补充 Form 的 `validateMessages` 和 `onFieldsChange` 参数的定义。
|
||||
- 🌟 优化 Button 的属性定义。[#10877](https://github.com/ant-design/ant-design/pull/10877) [@zheeeng](https://github.com/zheeeng)
|
||||
- 🌟 补充 AutoComplete 的 `backfill` 属性定义。[#10909](https://github.com/ant-design/ant-design/pull/10909) [@zhanba](https://github.com/zhanba)
|
||||
|
||||
## 3.6.2
|
||||
|
||||
`2018-06-09`
|
||||
|
||||
- 🐞 修复 Table 数据变化时全选勾选框状态显示不正确的问题。[#10629](https://github.com/ant-design/ant-design/issues/10629)
|
||||
- 🐞 修复 Button.Group 中使用 disabled 按钮时缺失边框。
|
||||
- 🐞 修复 Upload 中 `beforeUpload` 返回 `false` 时,文件列表排序会被反转的问题。[#10681](https://github.com/ant-design/ant-design/issues/10681)
|
||||
- 🐞 修复 Calendar 表格中内容溢出的问题。[#10808](https://github.com/ant-design/ant-design/pull/10808) [@Yangzhedi](https://github.com/ant-design/Yangzhedi)
|
||||
- Spin
|
||||
- 🐞 修复使用图标时不能按照 `size` 正确显示大小的问题。[#10786](https://github.com/ant-design/ant-design/issues/10786)
|
||||
- 🐞 修复默认旋转时 `delay` 不生效的问题。[#10727](https://github.com/ant-design/ant-design/pull/10727) [@dreamerblue](https://github.com/dreamerblue)
|
||||
- 修复 Badge 的状态色不跟主题色变化的问题。
|
||||
- TypeScript
|
||||
- 🐞 修复 Menu 类型定义。[#10773](https://github.com/ant-design/ant-design/issues/10773)
|
||||
- 🐞 修复 AutoComplete 类型定义。[#10745](https://github.com/ant-design/ant-design/issues/10745) [#10619](https://github.com/ant-design/ant-design/issues/10619)
|
||||
- 🐞 修复 Tree 类型定义。[#10841](https://github.com/ant-design/ant-design/pull/10841) [@Voronar](https://github.com/Voronar)
|
||||
- 🐞 修复 Checkbox.Group 的类型定义。[#10677](https://github.com/ant-design/ant-design/pull/10677)
|
||||
|
||||
## 3.6.0
|
||||
|
||||
`2018-06-02`
|
||||
|
||||
* 🌟 `Form` 表单错误信息展示支持传入 ReactNode。 [#10136](https://github.com/ant-design/ant-design/issues/10136) [@lovekonakona](https://github.com/lovekonakona)
|
||||
* 🌟 `List` 组件支持指定分页器的位置。 [#10581](https://github.com/ant-design/ant-design/pull/10581) [@zheeeng](https://github.com/zheeeng)
|
||||
* 🌟 `Layout.Sider` 支持 dark/light 主题定制。 [#10142](https://github.com/ant-design/ant-design/issues/10142) [@pd4d10](https://github.com/pd4d10)
|
||||
* 🌟 支持 Ant Design 站点的离线模式。 [#10625](https://github.com/ant-design/ant-design/issues/10625)
|
||||
* 🌟 `Transfer` 新增 `style` 以及 `operationStyle` 属性配置样式。 [@eduludi](https://github.com/eduludi)
|
||||
* 🌟 `Message` 增加 promise 化的回调接口。 [#10421](https://github.com/ant-design/ant-design/issues/10421) [@zhujinxuan](https://github.com/zhujinxuan)
|
||||
* 🐞 修复编译时 typescript v2.9.1兼容性问题。 [#10729](https://github.com/ant-design/ant-design/issues/10729) [@karol-majewski](https://github.com/karol-majewski)
|
||||
* 🐞 修复 `Menu` 嵌套超过两层时选中最里层后对应最外层没有亮起问题。 [#8666](https://github.com/ant-design/ant-design/issues/8666) [@stonehank](https://github.com/stonehank)
|
||||
* 🐞 修复 `Affix` 组件 offsetBottom 无效问题。 [#10674](https://github.com/ant-design/ant-design/issues/10674)
|
||||
|
||||
## 3.5.4
|
||||
|
||||
`2018-05-26`
|
||||
|
||||
- 🐞 修复 `Cascader` 的 `showSearch` 无效问题。[968488a2](https://github.com/ant-design/ant-design/commit/968488a2fac9bcb16bee9f0c248f49bca00dbec6)
|
||||
- 🐞 使 `Badge[status]` 支持 `Tooltip`。[#10626](https://github.com/ant-design/ant-design/issues/10626)
|
||||
- 🐞 修复父元素使用 `text-align` 会影响 `Spin` 的问题。[#10643](https://github.com/ant-design/ant-design/pull/10643) [@wmzhong](https://github.com/wmzhong)
|
||||
- 💄 `Table` 换行从 `break-all` 改为 `break-word`。[#10655](https://github.com/ant-design/ant-design/pull/10655) [@clinyong](https://github.com/clinyong)
|
||||
- 🌟 `Search` 在未定义 `enterButton` 时,点击搜索图标将触发 `onSearch`。 [36ffe7e1](https://github.com/ant-design/ant-design/commit/36ffe7e1dc9d9473c8c68168ab79b7a03a604702)
|
||||
|
||||
## 3.5.3
|
||||
|
||||
`2018-05-20`
|
||||
|
||||
- 🐞 修复了 `Affix` 当 `offsetTop === 0`, 值将变为 `undefined` 的问题 [#10566](https://github.com/ant-design/ant-design/pull/10566)
|
||||
- 🐞 修复了 `Menu` item 中的高亮链接颜色问题 [09d5e36](https://github.com/ant-design/ant-design/commit/09d5e36cfa27e371a7b4d4e68276a279698ea901)
|
||||
- 🐞 修复了 `Input.Group` 组件阴影被遮盖的问题 [#10230](https://github.com/ant-design/ant-design/issues/10230)
|
||||
- 🐞 修复了 `Transfer` 组件 checkbox 事件触发两次的问题 [`#10480`](https://github.com/ant-design/ant-design/issues/10480)
|
||||
- 💄 统一 less 的变量命名 [12d3046](https://github.com/ant-design/ant-design/commit/12d3046687a0dcdb51fece08dd2bea64f185cc40)
|
||||
- 💄 微调了 `Dropdown` 的样式 [8e2f72f](https://github.com/ant-design/ant-design/commit/8e2f72ffe0eb300f5997296726b02246bf990c8f)
|
||||
- 💄 现在中文文档的组件会用中文语言包进行演示。[9b17a94](https://github.com/ant-design/ant-design/commit/9b17a943f5d57d40d65041b7b0c247add09d2851)
|
||||
- 💄 主站主题切换 修改为 `antd-theme-generato` ,感谢 [@mzohaibqc](https://github.com/mzohaibqc) 的工作.
|
||||
- TypeScript
|
||||
- 🐞 修复了 `Row` 中 gutter 属性的类型问题 [b7d508e](https://github.com/ant-design/ant-design/commit/b7d508e1662bf20a0cacbe6440a2ce31a65a8a59)
|
||||
- 💄 改进了 `Form` 组件类型 [#10564](https://github.com/ant-design/ant-design/pull/10564)
|
||||
- 💄 改进了 `Button` 和 `Tag` 类型 [1ed9fed](https://github.com/ant-design/ant-design/commit/1ed9fed2cf1c99b947359fafb101b2e58213cb48)
|
||||
|
||||
## 3.5.2
|
||||
|
||||
`2018-05-13`
|
||||
|
||||
- 🐞 修复 `Table` 过滤器和 `Transfer` 复选框无法点击的问题。[#10452](https://github.com/ant-design/ant-design/issues/10452)
|
||||
- 🐞 修复 `Cascader` 的 `displayRender` 里的链接无法点击的问题。[#10433](https://github.com/ant-design/ant-design/issues/10433)
|
||||
- 🐞 修复 `Button` ref 不兼容问题。[#10405](https://github.com/ant-design/ant-design/issues/10405)
|
||||
- 🐞 修复 `Form` 表单项校验位置高度时出现抖动问题。[#10445](https://github.com/ant-design/ant-design/issues/10445)
|
||||
- 🌟 设置 `Layout` 宽度时,允许使用任何的 CSS 单位。 [#10479](https://github.com/ant-design/ant-design/pull/10479)
|
||||
|
||||
## 3.5.1
|
||||
|
||||
`2018-05-09`
|
||||
|
||||
- 🐞 修复 Input.Group 在 Form 下样式错位的问题。[#10371](https://github.com/ant-design/ant-design/issues/10371)
|
||||
- 🐞 修复 Select 箭头和内容重叠的问题。[#10383](https://github.com/ant-design/ant-design/issues/10383)
|
||||
- 🐞 移除 Collapse 点击时的 focus 样式。
|
||||
- 🐞 移除 Input.Group 和 Checkbox 不必要的 `z-index`。[#9840](https://github.com/ant-design/ant-design/issues/9840) [#10385](https://github.com/ant-design/ant-design/issues/10385)
|
||||
- 🐞 修复一个数字等宽字体没有加粗的问题。
|
||||
- Table
|
||||
- 💄 重写了可编辑表格的演示。[#10119](https://github.com/ant-design/ant-design/pull/10119)
|
||||
- 🐞 修复一个表格列内容互相重叠的问题。[#9822](https://github.com/ant-design/ant-design/issues/9822)
|
||||
- TypeScript
|
||||
- 🐞 调整 Breadcrumb.Item 的类型。[#10372](https://github.com/ant-design/ant-design/pull/10372) [@karol-majewski](https://github.com/karol-majewski)
|
||||
- 🐞 修复 Table 的 `rowSelection` 的类型。[#10374](https://github.com/ant-design/ant-design/issues/10374)
|
||||
|
||||
## 3.5.0
|
||||
|
||||
`2018-05-04`
|
||||
|
||||
- 🌟 组件 `Badge` 新增 `title` 属性支持鼠标 hover 的时候显示。[74d81c2](https://github.com/ant-design/ant-design/commit/74d81c2d078a3c84b3e44cbfbdd99b8f479ea71d) [@ludwigbacklund](https://github.com/ludwigbacklund)
|
||||
- 🌟 添加 `successPercent` 为 `Progress[format]` 的参数。[#10096](https://github.com/ant-design/ant-design/issues/10096)
|
||||
- 🌟 更新 `rc-notification` 到 3.1.0 来支持组件 `Notification` 的 `maxCount` 属性。[#10161](https://github.com/ant-design/ant-design/pull/10161) [@jzhangs](https://github.com/jzhangs)
|
||||
- 🌟 更新 `rc-cascader` 到 1.13.0 来支持组件 `Cascader` 的 `filedNames` 属性。[react-component/cascader#23](https://github.com/react-component/cascader/pull/23) [@405go](https://github.com/405go)
|
||||
- 🌟 组件 `Notification` 支持通过 key 更新通知属性。 [react-component/notification#40](https://github.com/react-component/notification/pull/40) [@yevhen-hryhorevskyi](https://github.com/yevhen-hryhorevskyi)
|
||||
- 🌟 组件 `List` 支持内置的翻页功能。[#10135](https://github.com/ant-design/ant-design/pull/10135)
|
||||
- Table
|
||||
- 🌟 新增 `sortOrder` 参数传递给列配置中的 `sorter` 方法。[#10306](https://github.com/ant-design/ant-design/pull/10306) [@kumarashwin](https://github.com/kumarashwin)
|
||||
- 🐞 修复头部单元格的边框样式问题。[#10359](https://github.com/ant-design/ant-design/issues/10359)
|
||||
- 🐞 修复当数据变化时用户选择项丢失的问题。[#10332](https://github.com/ant-design/ant-design/pull/10332) [@chrvadala](https://github.com/chrvadala)
|
||||
- `Menu` 升级 `rc-menu` 到 `7.x` [#10305](https://github.com/ant-design/ant-design/pull/10305)
|
||||
- 🌟 更好的 aria-* 属性支持。[react-component/menu#137](https://github.com/react-component/menu/pull/137)
|
||||
- 🌟 一些内部优化提升组件性能。[react-component/menu#133](https://github.com/react-component/menu/pull/133)
|
||||
- 🌟 支持将属性传递到菜单项中。[react-component/menu#135](https://github.com/react-component/menu/pull/135)
|
||||
- 🐞 修复一些快捷键的问题。[react-component/menu#132](https://github.com/react-component/menu/pull/132)
|
||||
- Collapse
|
||||
- 🌟 更新 `rc-collapse` 到 1.9.0 优化键盘支持。[react-component/collapse#84](https://github.com/react-component/collapse/pull/84/) [@kossel](https://github.com/kossel)
|
||||
- 🌟 支持通过 less 定义组件 `Collapse` 的样式。[#9943](https://github.com/ant-design/ant-design/pull/9943) [@davidhatten](https://github.com/davidhatten)
|
||||
- Select
|
||||
- 🐞 修复 `placeholder` 的 ts 类型问题。[#10282](https://github.com/ant-design/ant-design/pull/10282) [@thomasthiebaud](https://github.com/thomasthiebaud)
|
||||
- 🐞 修复不显示箭头时多余的空白。[#10296](https://github.com/ant-design/ant-design/pull/10296)
|
||||
- 🐞 修复属性 `value` 的 typescript 类型错误。[#10336](https://github.com/ant-design/ant-design/pull/10336) [@paranoidjk](https://github.com/paranoidjk)
|
||||
- Input
|
||||
- 🐞 修复 `Input.Search` 当 disabled 为 true 时按钮没有被禁用的问题。[#10040](https://github.com/ant-design/ant-design/issues/10040)
|
||||
- 🐞 修复 `Input.Group` 在表单中对齐的问题。[#10281](https://github.com/ant-design/ant-design/issues/10281)
|
||||
- Form
|
||||
- 🐞 修复 `Form.onValuesChange` 的 ts 类型错误。[#10231](https://github.com/ant-design/ant-design/pull/10231) [@whtsky](https://github.com/whtsky)
|
||||
- 🐞 修复 `ComponentDecorator` typescript 定义的错误。[#10324](https://github.com/ant-design/ant-design/pull/10324) [@paranoidjk](https://github.com/paranoidjk)
|
||||
- 🐞 修复 `Divider` 为 dashed 时的样式问题。[#10216](https://github.com/ant-design/ant-design/issues/10216)
|
||||
- 🐞 修复 `Spin` 覆盖层的展示问题。[#10227](https://github.com/ant-design/ant-design/issues/10227)
|
||||
- 🐞 修复 `Notification` 鼠标 hover 是图标的颜色问题。[#10272](https://github.com/ant-design/ant-design/issues/10272)
|
||||
- 🐞 修复 `Upload` 组件属性 `lastModifiedDate` 的拼写错误。[#10315](https://github.com/ant-design/ant-design/pull/10315) [@danielg2002](https://github.com/danielg2002)
|
||||
- 🐞 修复 `Button` 的属性类型,使用 `React.HTMLProps`。[#10229](https://github.com/ant-design/ant-design/pull/10229) [@whtsky](https://github.com/whtsky)
|
||||
- 🐞 修复 less 命名约定不一致的问题。 [#10275](https://github.com/ant-design/ant-design/issues/10275)
|
||||
|
||||
## 3.4.5
|
||||
|
||||
`2018-05-03`
|
||||
|
||||
- 🐞 修复 Upload 上传文件名不展示(file 对象属性为空)的问题。[#10319](https://github.com/ant-design/ant-design/issues/10319)
|
||||
|
||||
## 3.4.4
|
||||
|
||||
`2018-04-28`
|
||||
|
||||
- 🐞 修复 3.4.2 中引入的 Upload 中 onChange 参数 `{ file }` file 不是 File 实例的问题。[#10293](https://github.com/ant-design/ant-design/issues/10293)
|
||||
- 🐞 修复 webpack@4 下使用 Tree Shaking 样式丢失的问题。[#10217](https://github.com/ant-design/ant-design/pull/10217) [@whtsky](https://github.com/whtsky)
|
||||
|
||||
## 3.4.3
|
||||
|
||||
`2018-04-23`
|
||||
|
||||
- 🐞 修复了 webpack@4 下使用 Tree Shaking 样式丢失的问题。[#10197](https://github.com/ant-design/ant-design/pull/10197) [@Aladdin-ADD](https://github.com/Aladdin-ADD)
|
||||
- 🐞 修复 `Menu` 组件在 `dark` 主题下点击区域的问题。[#10187](https://github.com/ant-design/ant-design/pull/10187) [@dgeibi](https://github.com/dgeibi)
|
||||
|
||||
## 3.4.2
|
||||
|
||||
`2018-04-22`
|
||||
@@ -357,11 +517,11 @@ timeline: true
|
||||
|
||||
`2017-12-04`
|
||||
|
||||
更多内容见 [Ant Design 3.0 发布公告](https://medium.com/ant-design/announcing-ant-design-3-0-70e3e65eca0c)!
|
||||
更多内容见 [Ant Design 3.0 发布公告](https://medium.com/ant-design/announcing-ant-design-3-0-70e3e65eca0c)。
|
||||
|
||||
### 主要变化
|
||||
|
||||
- 全新的[色彩系统](https://ant.design/docs/spec/colors-cn#Color-Palettes),组件主色由 『`#108EE9`』 改为 『`#1890FF`』,新主色我们称之为『拂晓蓝』。
|
||||
- 全新的[色彩系统](https://ant.design/docs/spec/colors-cn#Color-Palettes),组件主色由『`#108EE9`』改为『`#1890FF`』,新主色我们称之为『拂晓蓝』。
|
||||
- 全新的视觉样式和组件尺寸,更现代更美观。
|
||||
- 基础字体大小由 `12px` 增大到 `14px`。
|
||||
- 默认语言由中文改为英文。
|
||||
@@ -373,6 +533,8 @@ timeline: true
|
||||
|
||||
### 不兼容改动
|
||||
|
||||
> 如果你从 2.x 升级到 3.x,建议直接升级到 3.x 的最新版本。
|
||||
|
||||
此版本有部分不兼容的改动,升级时确保修改相应的使用代码。另外由于人肉查找代码中的废弃用法过于低效,所以我们提供了 [antd-migration-helper](https://github.com/ant-design/antd-migration-helper) 用于扫描代码中的废弃用法。
|
||||
|
||||
- Card 的 `noHovering` 属性重命名为 `hoverable`,且默认值改为 `true`。
|
||||
@@ -419,7 +581,7 @@ timeline: true
|
||||
|
||||
- Form 下的表单控件不再默认为 `size="large"`。
|
||||
- `Input.Search` 默认的 🔍 图标只作为装饰,不再响应用户交互。需要添加可交互按钮请使用 `enterButton`。
|
||||
- UMD 版本的 `dist/antd.js` 不再包含 moment,使用的时候需要自己引入 moment。
|
||||
- UMD 版本的 `dist/antd.js` 不再包含 moment,使用的时候需要自己引入 moment。
|
||||
```diff
|
||||
<html>
|
||||
<head>
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
|
||||
[](https://travis-ci.org/ant-design/ant-design)
|
||||
[](https://codecov.io/gh/ant-design/ant-design/branch/master)
|
||||
[](https://gemnasium.com/ant-design/ant-design)
|
||||
[](https://david-dm.org/ant-design/ant-design)
|
||||
[](https://david-dm.org/ant-design/ant-design#info=devDependencies&view=list)
|
||||
|
||||
[](https://www.npmjs.org/package/antd)
|
||||
[](http://www.npmtrends.com/antd)
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
|
||||
[](https://travis-ci.org/ant-design/ant-design)
|
||||
[](https://codecov.io/gh/ant-design/ant-design/branch/master)
|
||||
[](https://gemnasium.com/ant-design/ant-design)
|
||||
[](https://david-dm.org/ant-design/ant-design)
|
||||
[](https://david-dm.org/ant-design/ant-design#info=devDependencies&view=list)
|
||||
|
||||
[](https://www.npmjs.org/package/antd)
|
||||
[](http://www.npmtrends.com/antd)
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
const OLD_NODE_ENV = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'development';
|
||||
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
const antd = require('..');
|
||||
|
||||
describe('antd', () => {
|
||||
afterAll(() => {
|
||||
process.env.NODE_ENV = OLD_NODE_ENV;
|
||||
});
|
||||
|
||||
it('exports modules correctly', () => {
|
||||
expect(Object.keys(antd)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should hint when import all components', () => {
|
||||
it('should hint when import all components in dev mode', () => {
|
||||
expect(warnSpy).toBeCalledWith(
|
||||
'You are using a whole package of antd, please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size.'
|
||||
);
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
const availablePrefixs = ['moz', 'ms', 'webkit'];
|
||||
|
||||
function requestAnimationFramePolyfill() {
|
||||
let lastTime = 0;
|
||||
return function(callback: (n: number) => void) {
|
||||
const currTime = new Date().getTime();
|
||||
const timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||||
const id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
|
||||
lastTime = currTime + timeToCall;
|
||||
return id;
|
||||
};
|
||||
}
|
||||
|
||||
export default function getRequestAnimationFrame() {
|
||||
if (typeof window === 'undefined') {
|
||||
return () => {};
|
||||
}
|
||||
if (window.requestAnimationFrame) {
|
||||
// https://github.com/vuejs/vue/issues/4465
|
||||
return window.requestAnimationFrame.bind(window);
|
||||
}
|
||||
|
||||
const prefix = availablePrefixs.filter(key => `${key}RequestAnimationFrame` in window)[0];
|
||||
|
||||
return prefix
|
||||
? (window as any)[`${prefix}RequestAnimationFrame`]
|
||||
: requestAnimationFramePolyfill();
|
||||
}
|
||||
|
||||
export function cancelRequestAnimationFrame(id: number) {
|
||||
if (typeof window === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
if (window.cancelAnimationFrame) {
|
||||
return window.cancelAnimationFrame(id);
|
||||
}
|
||||
const prefix = availablePrefixs.filter(key =>
|
||||
`${key}CancelAnimationFrame` in window || `${key}CancelRequestAnimationFrame` in window,
|
||||
)[0];
|
||||
|
||||
return prefix ?
|
||||
(
|
||||
(window as any)[`${prefix}CancelAnimationFrame`] ||
|
||||
(window as any)[`${prefix}CancelRequestAnimationFrame`]
|
||||
).call(this, id) : clearTimeout(id);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
let animation: boolean;
|
||||
|
||||
function isCssAnimationSupported() {
|
||||
if (animation !== undefined) {
|
||||
return animation;
|
||||
}
|
||||
const domPrefixes = 'Webkit Moz O ms Khtml'.split(' ');
|
||||
const elm = document.createElement('div');
|
||||
if (elm.style.animationName !== undefined) {
|
||||
animation = true;
|
||||
}
|
||||
if (animation !== undefined) {
|
||||
for (let i = 0; i < domPrefixes.length; i++) {
|
||||
if ((elm.style as any)[`${domPrefixes[i]}AnimationName`] !== undefined) {
|
||||
animation = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
animation = animation || false;
|
||||
return animation;
|
||||
}
|
||||
|
||||
export default isCssAnimationSupported;
|
||||
@@ -1,7 +1,5 @@
|
||||
import cssAnimation from 'css-animation';
|
||||
import getRequestAnimationFrame, { cancelRequestAnimationFrame } from './getRequestAnimationFrame';
|
||||
|
||||
const reqAnimFrame = getRequestAnimationFrame();
|
||||
import raf from 'raf';
|
||||
|
||||
function animate(node: HTMLElement, show: boolean, done: () => void) {
|
||||
let height: number;
|
||||
@@ -19,16 +17,16 @@ function animate(node: HTMLElement, show: boolean, done: () => void) {
|
||||
},
|
||||
active() {
|
||||
if (requestAnimationFrameId) {
|
||||
cancelRequestAnimationFrame(requestAnimationFrameId);
|
||||
raf.cancel(requestAnimationFrameId);
|
||||
}
|
||||
requestAnimationFrameId = reqAnimFrame(() => {
|
||||
requestAnimationFrameId = raf(() => {
|
||||
node.style.height = `${show ? height : 0}px`;
|
||||
node.style.opacity = show ? '1' : '0';
|
||||
});
|
||||
},
|
||||
end() {
|
||||
if (requestAnimationFrameId) {
|
||||
cancelRequestAnimationFrame(requestAnimationFrameId);
|
||||
raf.cancel(requestAnimationFrameId);
|
||||
}
|
||||
node.style.height = '';
|
||||
node.style.opacity = '';
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import getRequestAnimationFrame, { cancelRequestAnimationFrame } from '../_util/getRequestAnimationFrame';
|
||||
|
||||
const reqAnimFrame = getRequestAnimationFrame();
|
||||
import raf from 'raf';
|
||||
|
||||
export default function throttleByAnimationFrame(fn: (...args: any[]) => void) {
|
||||
let requestId: number | null;
|
||||
@@ -12,11 +10,11 @@ export default function throttleByAnimationFrame(fn: (...args: any[]) => void) {
|
||||
|
||||
const throttled = (...args: any[]) => {
|
||||
if (requestId == null) {
|
||||
requestId = reqAnimFrame(later(args));
|
||||
requestId = raf(later(args));
|
||||
}
|
||||
};
|
||||
|
||||
(throttled as any).cancel = () => cancelRequestAnimationFrame(requestId!);
|
||||
(throttled as any).cancel = () => raf.cancel(requestId!);
|
||||
|
||||
return throttled;
|
||||
}
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
export type Diff<T extends string, U extends string> = ({ [P in T]: P } &
|
||||
{ [P in U]: never } & { [x: string]: never })[T];
|
||||
export type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;
|
||||
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
||||
|
||||
@@ -7,7 +7,6 @@ const events = {};
|
||||
|
||||
class AffixMounter extends React.Component {
|
||||
componentDidMount() {
|
||||
this.container.scrollTop = 100;
|
||||
this.container.addEventListener = jest.fn().mockImplementation((event, cb) => {
|
||||
events[event] = cb;
|
||||
});
|
||||
@@ -34,6 +33,7 @@ class AffixMounter extends React.Component {
|
||||
<Affix
|
||||
target={() => this.container}
|
||||
ref={ele => this.affix = ele}
|
||||
{...this.props}
|
||||
>
|
||||
<Button type="primary" >
|
||||
Fixed at the top of container
|
||||
@@ -46,6 +46,8 @@ class AffixMounter extends React.Component {
|
||||
}
|
||||
|
||||
describe('Affix Render', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
@@ -54,23 +56,63 @@ describe('Affix Render', () => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('Anchor render perfectly', () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
const wrapper = mount(<AffixMounter />, { attachTo: document.getElementById('mounter') });
|
||||
jest.runAllTimers();
|
||||
|
||||
const scrollTo = (top) => {
|
||||
wrapper.instance().affix.fixedNode.parentNode.getBoundingClientRect = jest.fn(() => {
|
||||
return {
|
||||
bottom: 100, height: 28, left: 0, right: 0, top: -50, width: 195,
|
||||
bottom: 100, height: 28, left: 0, right: 0, top: 50 - top, width: 195,
|
||||
};
|
||||
});
|
||||
|
||||
wrapper.instance().container.scrollTop = top;
|
||||
events.scroll({
|
||||
type: 'scroll',
|
||||
});
|
||||
|
||||
jest.runAllTimers();
|
||||
};
|
||||
|
||||
it('Anchor render perfectly', () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
wrapper = mount(<AffixMounter />, { attachTo: document.getElementById('mounter') });
|
||||
jest.runAllTimers();
|
||||
|
||||
scrollTo(0);
|
||||
expect(wrapper.instance().affix.state.affixStyle).toBe(null);
|
||||
|
||||
scrollTo(100);
|
||||
expect(wrapper.instance().affix.state.affixStyle).not.toBe(null);
|
||||
|
||||
scrollTo(0);
|
||||
expect(wrapper.instance().affix.state.affixStyle).toBe(null);
|
||||
});
|
||||
|
||||
it('support offsetBottom', () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
wrapper = mount(<AffixMounter offsetBottom={0} />, { attachTo: document.getElementById('mounter') });
|
||||
jest.runAllTimers();
|
||||
|
||||
scrollTo(0);
|
||||
expect(wrapper.instance().affix.state.affixStyle).not.toBe(null);
|
||||
|
||||
scrollTo(100);
|
||||
expect(wrapper.instance().affix.state.affixStyle).toBe(null);
|
||||
|
||||
scrollTo(0);
|
||||
expect(wrapper.instance().affix.state.affixStyle).not.toBe(null);
|
||||
});
|
||||
|
||||
it('updatePosition when offsetTop changed', () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
wrapper = mount(<AffixMounter offsetTop={0} />, { attachTo: document.getElementById('mounter') });
|
||||
jest.runAllTimers();
|
||||
|
||||
scrollTo(100);
|
||||
expect(wrapper.instance().affix.state.affixStyle.top).toBe(0);
|
||||
wrapper.setProps({
|
||||
offsetTop: 10,
|
||||
});
|
||||
jest.runAllTimers();
|
||||
expect(wrapper.instance().affix.state.affixStyle.top).toBe(10);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,16 +16,46 @@ The simplest usage.
|
||||
````jsx
|
||||
import { Affix, Button } from 'antd';
|
||||
|
||||
class Demo extends React.Component {
|
||||
state = {
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Affix offsetTop={this.state.top}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
top: this.state.top + 10,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Affix top
|
||||
</Button>
|
||||
</Affix>
|
||||
<br />
|
||||
<Affix offsetBottom={this.state.bottom}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
bottom: this.state.bottom + 10,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Affix bottom
|
||||
</Button>
|
||||
</Affix>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Affix>
|
||||
<Button type="primary">Affix top</Button>
|
||||
</Affix>
|
||||
<br />
|
||||
<Affix offsetBottom={0}>
|
||||
<Button type="primary">Affix bottom</Button>
|
||||
</Affix>
|
||||
</div>,
|
||||
<Demo />,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -38,8 +38,7 @@ function getOffset(element: HTMLElement, target: HTMLElement | Window | null) {
|
||||
function noop() {}
|
||||
|
||||
function getDefaultTarget() {
|
||||
return typeof window !== 'undefined' ?
|
||||
window : null;
|
||||
return typeof window !== 'undefined' ? window : null;
|
||||
}
|
||||
|
||||
// Affix
|
||||
@@ -145,7 +144,9 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
const targetNode = target();
|
||||
|
||||
// Backwards support
|
||||
offsetTop = offsetTop || offset;
|
||||
// Fix: if offsetTop === 0, it will get undefined,
|
||||
// if offsetBottom is type of number, offsetMode will be { top: false, ... }
|
||||
offsetTop = typeof offsetTop === 'undefined' ? offset : offsetTop;
|
||||
const scrollTop = getScroll(targetNode, true);
|
||||
const affixNode = ReactDOM.findDOMNode(this) as HTMLElement;
|
||||
const elemOffset = getOffset(affixNode, targetNode);
|
||||
@@ -232,6 +233,12 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
// Mock Event object.
|
||||
this.updatePosition({});
|
||||
}
|
||||
if (
|
||||
this.props.offsetTop !== nextProps.offsetTop ||
|
||||
this.props.offsetBottom !== nextProps.offsetBottom
|
||||
) {
|
||||
this.updatePosition({});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
||||
31
components/alert/__tests__/index.test.js
Normal file
31
components/alert/__tests__/index.test.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Alert from '..';
|
||||
|
||||
describe('Alert', () => {
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('could be closed', () => {
|
||||
const onClose = jest.fn();
|
||||
const afterClose = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Alert
|
||||
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
||||
type="warning"
|
||||
closable
|
||||
onClose={onClose}
|
||||
afterClose={afterClose}
|
||||
/>
|
||||
);
|
||||
wrapper.find('.ant-alert-close-icon').simulate('click');
|
||||
expect(onClose).toBeCalled();
|
||||
jest.runAllTimers();
|
||||
expect(afterClose).toBeCalled();
|
||||
});
|
||||
});
|
||||
@@ -16,7 +16,7 @@ title: Alert
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| afterClose | 关闭动画结束后的回掉 | () => void | - |
|
||||
| afterClose | 关闭动画结束后触发的回调函数 | () => void | - |
|
||||
| banner | 是否用作顶部公告 | boolean | false |
|
||||
| closable | 默认不显示关闭按钮 | boolean | 无 |
|
||||
| closeText | 自定义关闭按钮 | string\|ReactNode | 无 |
|
||||
|
||||
@@ -6,7 +6,7 @@ import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import Affix from '../affix';
|
||||
import AnchorLink from './AnchorLink';
|
||||
import getScroll from '../_util/getScroll';
|
||||
import getRequestAnimationFrame from '../_util/getRequestAnimationFrame';
|
||||
import raf from 'raf';
|
||||
|
||||
function getDefaultContainer() {
|
||||
return window;
|
||||
@@ -43,7 +43,6 @@ function easeInOutCubic(t: number, b: number, c: number, d: number) {
|
||||
return cc / 2 * ((t -= 2) * t * t + 2) + b;
|
||||
}
|
||||
|
||||
const reqAnimFrame = getRequestAnimationFrame();
|
||||
const sharpMatcherRegx = /#([^#]+)$/;
|
||||
function scrollTo(href: string, offsetTop = 0, getContainer: () => AnchorContainer, callback = () => { }) {
|
||||
const container = getContainer();
|
||||
@@ -67,12 +66,12 @@ function scrollTo(href: string, offsetTop = 0, getContainer: () => AnchorContain
|
||||
(container as HTMLElement).scrollTop = nextScrollTop;
|
||||
}
|
||||
if (time < 450) {
|
||||
reqAnimFrame(frameFunc);
|
||||
raf(frameFunc);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
reqAnimFrame(frameFunc);
|
||||
raf(frameFunc);
|
||||
history.pushState(null, '', href);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ describe('Anchor Render', () => {
|
||||
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - scoll', () => {
|
||||
it('Anchor render perfectly for complete href - scroll', () => {
|
||||
let root = document.getElementById('root');
|
||||
if (!root) {
|
||||
root = document.createElement('div', { id: 'root' });
|
||||
@@ -45,7 +45,8 @@ describe('Anchor Render', () => {
|
||||
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - scollTo', () => {
|
||||
it('Anchor render perfectly for complete href - scrollTo', async () => {
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
let root = document.getElementById('root');
|
||||
if (!root) {
|
||||
root = document.createElement('div', { id: 'root' });
|
||||
@@ -60,5 +61,33 @@ describe('Anchor Render', () => {
|
||||
);
|
||||
wrapper.instance().handleScrollTo('##API');
|
||||
expect(wrapper.instance().state.activeLink).toBe('##API');
|
||||
expect(scrollToSpy).not.toHaveBeenCalled();
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
expect(scrollToSpy).toHaveBeenCalled();
|
||||
expect(wrapper.instance().animating).toBe(true);
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
expect(wrapper.instance().animating).toBe(false);
|
||||
});
|
||||
|
||||
it('should remove listener when unmount', async () => {
|
||||
const wrapper = mount(
|
||||
<Anchor>
|
||||
<Link href="#API" title="API" />
|
||||
</Anchor>
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn(wrapper.instance().scrollEvent, 'remove');
|
||||
wrapper.unmount();
|
||||
expect(removeListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should unregister link when unmount children', async () => {
|
||||
const wrapper = mount(
|
||||
<Anchor>
|
||||
<Link href="#API" title="API" />
|
||||
</Anchor>
|
||||
);
|
||||
expect(wrapper.instance().links).toEqual(['#API']);
|
||||
wrapper.setProps({ children: null });
|
||||
expect(wrapper.instance().links).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
input here
|
||||
</div>
|
||||
@@ -47,7 +47,7 @@ exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -78,7 +78,7 @@ exports[`renders ./components/auto-complete/demo/certain-category.md correctly 1
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
input here
|
||||
</div>
|
||||
@@ -117,7 +117,7 @@ exports[`renders ./components/auto-complete/demo/certain-category.md correctly 1
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -166,7 +166,7 @@ exports[`renders ./components/auto-complete/demo/custom.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -193,7 +193,7 @@ exports[`renders ./components/auto-complete/demo/non-case-sensitive.md correctly
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
try to type \`b\`
|
||||
</div>
|
||||
@@ -221,7 +221,7 @@ exports[`renders ./components/auto-complete/demo/non-case-sensitive.md correctly
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -248,7 +248,7 @@ exports[`renders ./components/auto-complete/demo/options.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
input here
|
||||
</div>
|
||||
@@ -276,7 +276,7 @@ exports[`renders ./components/auto-complete/demo/options.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -307,7 +307,7 @@ exports[`renders ./components/auto-complete/demo/uncertain-category.md correctly
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
input here
|
||||
</div>
|
||||
@@ -351,7 +351,7 @@ exports[`renders ./components/auto-complete/demo/uncertain-category.md correctly
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
|
||||
@@ -6,7 +6,11 @@ import Input from '../input';
|
||||
import InputElement from './InputElement';
|
||||
|
||||
export interface DataSourceItemObject { value: string; text: string; }
|
||||
export type DataSourceItemType = string | DataSourceItemObject;
|
||||
export type DataSourceItemType =
|
||||
string |
|
||||
DataSourceItemObject |
|
||||
React.ReactElement<OptionProps> |
|
||||
React.ReactElement<OptGroupProps>;
|
||||
|
||||
export interface AutoCompleteInputProps {
|
||||
onChange?: React.FormEventHandler<any>;
|
||||
@@ -22,6 +26,7 @@ export interface AutoCompleteProps extends AbstractSelectProps {
|
||||
value?: SelectValue;
|
||||
defaultValue?: SelectValue;
|
||||
dataSource?: DataSourceItemType[];
|
||||
backfill?: boolean;
|
||||
optionLabelProp?: string;
|
||||
onChange?: (value: SelectValue) => void;
|
||||
onSelect?: (value: SelectValue, option: Object) => any;
|
||||
|
||||
@@ -75,7 +75,7 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
|
||||
render() {
|
||||
const {
|
||||
prefixCls, shape, size, src, icon, className, ...others,
|
||||
prefixCls, shape, size, src, icon, className, ...others
|
||||
} = this.props;
|
||||
|
||||
const sizeCls = classNames({
|
||||
|
||||
@@ -4,9 +4,7 @@ import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import getScroll from '../_util/getScroll';
|
||||
import getRequestAnimationFrame from '../_util/getRequestAnimationFrame';
|
||||
|
||||
const reqAnimFrame = getRequestAnimationFrame();
|
||||
import raf from 'raf';
|
||||
|
||||
const easeInOutCubic = (t: number, b: number, c: number, d: number) => {
|
||||
const cc = c - b;
|
||||
@@ -64,10 +62,10 @@ export default class BackTop extends React.Component<BackTopProps, any> {
|
||||
const time = timestamp - startTime;
|
||||
this.setScrollTop(easeInOutCubic(time, scrollTop, 0, 450));
|
||||
if (time < 450) {
|
||||
reqAnimFrame(frameFunc);
|
||||
raf(frameFunc);
|
||||
}
|
||||
};
|
||||
reqAnimFrame(frameFunc);
|
||||
raf(frameFunc);
|
||||
(this.props.onClick || noop)(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -1617,3 +1617,177 @@ exports[`renders ./components/badge/demo/status.md correctly 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/badge/demo/title.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="ant-badge"
|
||||
>
|
||||
<a
|
||||
class="head-example"
|
||||
href="#"
|
||||
/>
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true"
|
||||
title="Custom hover text"
|
||||
>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%)"
|
||||
>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
9
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="current"
|
||||
>
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
9
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class=""
|
||||
>
|
||||
9
|
||||
</p>
|
||||
</span>
|
||||
</sup>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
2187
components/badge/__tests__/__snapshots__/index.test.js.snap
Normal file
2187
components/badge/__tests__/__snapshots__/index.test.js.snap
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,65 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { mount, render } from 'enzyme';
|
||||
import Badge from '../index';
|
||||
import Tooltip from '../../tooltip';
|
||||
|
||||
describe('Badge', () => {
|
||||
test('badge dot not scaling count > 9', () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('badge dot not scaling count > 9', () => {
|
||||
const badge = mount(<Badge count={10} dot />);
|
||||
expect(badge.find('.ant-card-multiple-words').length).toBe(0);
|
||||
});
|
||||
test('badge dot not showing count == 0', () => {
|
||||
|
||||
it('badge dot not showing count == 0', () => {
|
||||
const badge = mount(<Badge count={0} dot />);
|
||||
expect(badge.find('.ant-badge-dot').length).toBe(0);
|
||||
});
|
||||
|
||||
it('should have an overriden title attribute', () => {
|
||||
const badge = mount(<Badge count={10} title="Custom title" />);
|
||||
expect(badge.find('.ant-scroll-number').getDOMNode().attributes.getNamedItem('title').value).toEqual('Custom title');
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/10626
|
||||
it('should be composable with Tooltip', () => {
|
||||
const wrapper = mount(
|
||||
<Tooltip title="Fix the error">
|
||||
<Badge status="error" />
|
||||
</Tooltip>
|
||||
);
|
||||
wrapper.find('Badge').simulate('mouseenter');
|
||||
jest.runAllTimers();
|
||||
expect(wrapper.instance().tooltip.props.visible).toBe(true);
|
||||
});
|
||||
|
||||
it('should render when count is changed', () => {
|
||||
const wrapper = mount(<Badge count={9} />);
|
||||
wrapper.setProps({ count: 10 });
|
||||
jest.runAllTimers();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
wrapper.setProps({ count: 11 });
|
||||
jest.runAllTimers();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
wrapper.setProps({ count: 11 });
|
||||
jest.runAllTimers();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
wrapper.setProps({ count: 10 });
|
||||
jest.runAllTimers();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
jest.runAllTimers();
|
||||
wrapper.setProps({ count: 9 });
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should be compatible with borderColor style', () => {
|
||||
const wrapper = render(<Badge count={4} style={{ backgroundColor: '#fff', color: '#999', borderColor: '#d9d9d9' }} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
39
components/badge/demo/title.md
Normal file
39
components/badge/demo/title.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 自定义标题
|
||||
en-US: Title
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
设置鼠标放在状态点上时显示的文字
|
||||
|
||||
## en-US
|
||||
|
||||
The badge will display `title` when hovered over, instead of `count`.
|
||||
|
||||
````jsx
|
||||
import { Badge } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Badge count={5} title="Custom hover text">
|
||||
<a href="#" className="head-example" />
|
||||
</Badge>
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
||||
|
||||
<style>
|
||||
.ant-badge:not(.ant-badge-status) {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.head-example {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 4px;
|
||||
background: #eee;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
@@ -31,3 +31,4 @@ Badge normally appears in proximity to notifications or user avatars with eye-ca
|
||||
| showZero | Whether to show badge when `count` is zero | boolean | `false` |
|
||||
| status | Set Badge as a status dot | `success` \| `processing` \| `default` \| `error` \| `warning` | `''` |
|
||||
| text | If `status` is set, `text` sets the display text of the status `dot` | string | `''` |
|
||||
| title | Text to show when hovering over the badge | string | `count` |
|
||||
|
||||
@@ -21,6 +21,7 @@ export interface BadgeProps {
|
||||
status?: 'success' | 'processing' | 'default' | 'error' | 'warning';
|
||||
text?: string;
|
||||
offset?: [number | string, number | string];
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export default class Badge extends React.Component<BadgeProps, any> {
|
||||
@@ -57,7 +58,8 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
status,
|
||||
text,
|
||||
offset,
|
||||
...restProps,
|
||||
title,
|
||||
...restProps
|
||||
} = this.props;
|
||||
let displayCount = (count as number) > (overflowCount as number) ? `${overflowCount}+` : count;
|
||||
const isZero = displayCount === '0' || displayCount === 0;
|
||||
@@ -90,7 +92,7 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
// <Badge status="success" />
|
||||
if (!children && status) {
|
||||
return (
|
||||
<span className={badgeCls} style={styleWithOffset}>
|
||||
<span {...restProps} className={badgeCls} style={styleWithOffset}>
|
||||
<span className={statusCls} />
|
||||
<span className={`${prefixCls}-status-text`}>{text}</span>
|
||||
</span>
|
||||
@@ -103,8 +105,9 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
data-show={!hidden}
|
||||
className={scrollNumberCls}
|
||||
count={displayCount}
|
||||
title={count}
|
||||
title={title || count}
|
||||
style={styleWithOffset}
|
||||
key="scrollNumber"
|
||||
/>
|
||||
);
|
||||
|
||||
|
||||
@@ -32,3 +32,4 @@ title: Badge
|
||||
| showZero | 当数值为 0 时,是否展示 Badge | boolean | false |
|
||||
| status | 设置 Badge 为状态点 | Enum{ 'success', 'processing, 'default', 'error', 'warning' } | '' |
|
||||
| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | string | '' |
|
||||
| title | 设置鼠标放在状态点上时显示的文字 | string | `count` |
|
||||
|
||||
@@ -41,7 +41,7 @@ function defaultItemRender(route: Route, params: any, routes: Route[], paths: st
|
||||
}
|
||||
|
||||
export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
static Item: any;
|
||||
static Item: typeof BreadcrumbItem;
|
||||
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-breadcrumb',
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`react router react router 3 1`] = `
|
||||
<Breadcrumb
|
||||
params={
|
||||
Object {
|
||||
"id": 1,
|
||||
}
|
||||
}
|
||||
prefixCls="ant-breadcrumb"
|
||||
routes={
|
||||
Array [
|
||||
Object {
|
||||
"breadcrumbName": "Home",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Application List",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Application:id",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Detail",
|
||||
"name": "detail",
|
||||
"path": "detail",
|
||||
},
|
||||
],
|
||||
"name": "app",
|
||||
"path": ":id",
|
||||
},
|
||||
],
|
||||
"name": "apps",
|
||||
"path": "apps",
|
||||
},
|
||||
],
|
||||
"name": "home",
|
||||
"path": "/",
|
||||
},
|
||||
Object {
|
||||
"breadcrumbName": "Application List",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Application:id",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Detail",
|
||||
"name": "detail",
|
||||
"path": "detail",
|
||||
},
|
||||
],
|
||||
"name": "app",
|
||||
"path": ":id",
|
||||
},
|
||||
],
|
||||
"name": "apps",
|
||||
"path": "apps",
|
||||
},
|
||||
Object {
|
||||
"breadcrumbName": "Application:id",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Detail",
|
||||
"name": "detail",
|
||||
"path": "detail",
|
||||
},
|
||||
],
|
||||
"name": "app",
|
||||
"path": ":id",
|
||||
},
|
||||
Object {
|
||||
"breadcrumbName": "Detail",
|
||||
"name": "detail",
|
||||
"path": "detail",
|
||||
},
|
||||
]
|
||||
}
|
||||
separator="/"
|
||||
>
|
||||
<div
|
||||
className="ant-breadcrumb"
|
||||
>
|
||||
<BreadcrumbItem
|
||||
key="Home"
|
||||
prefixCls="ant-breadcrumb"
|
||||
separator="/"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
className="ant-breadcrumb-link"
|
||||
>
|
||||
<a
|
||||
href="#/"
|
||||
>
|
||||
Home
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
className="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</span>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbItem
|
||||
key="Application List"
|
||||
prefixCls="ant-breadcrumb"
|
||||
separator="/"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
className="ant-breadcrumb-link"
|
||||
>
|
||||
<a
|
||||
href="#/apps"
|
||||
>
|
||||
Application List
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
className="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</span>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbItem
|
||||
key="Application:id"
|
||||
prefixCls="ant-breadcrumb"
|
||||
separator="/"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
className="ant-breadcrumb-link"
|
||||
>
|
||||
<a
|
||||
href="#/apps/1"
|
||||
>
|
||||
Application1
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
className="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</span>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbItem
|
||||
key="Detail"
|
||||
prefixCls="ant-breadcrumb"
|
||||
separator="/"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
className="ant-breadcrumb-link"
|
||||
>
|
||||
<span>
|
||||
Detail
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
className="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</span>
|
||||
</BreadcrumbItem>
|
||||
</div>
|
||||
</Breadcrumb>
|
||||
`;
|
||||
150
components/breadcrumb/__tests__/router.test.js
Normal file
150
components/breadcrumb/__tests__/router.test.js
Normal file
@@ -0,0 +1,150 @@
|
||||
import React from 'react';
|
||||
import { Route, Switch, Link, withRouter, MemoryRouter } from 'react-router-dom';
|
||||
import { mount } from 'enzyme';
|
||||
import Breadcrumb from '../index';
|
||||
|
||||
const Apps = () => (
|
||||
<ul className="app-list">
|
||||
<li>
|
||||
<Link to="/apps/1">Application1</Link>:<Link to="/apps/1/detail">Detail</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/apps/2">Application2</Link>:<Link to="/apps/2/detail">Detail</Link>
|
||||
</li>
|
||||
</ul>
|
||||
);
|
||||
|
||||
const breadcrumbNameMap = {
|
||||
'/apps': 'Application List',
|
||||
'/apps/1': 'Application1',
|
||||
'/apps/2': 'Application2',
|
||||
'/apps/1/detail': 'Detail',
|
||||
'/apps/2/detail': 'Detail',
|
||||
};
|
||||
|
||||
const Home = withRouter((props) => {
|
||||
const { location, history } = props;
|
||||
const pathSnippets = location.pathname.split('/').filter(i => i);
|
||||
const extraBreadcrumbItems = pathSnippets.map((_, index) => {
|
||||
const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;
|
||||
return (
|
||||
<Breadcrumb.Item key={url}>
|
||||
<Link to={url}>
|
||||
{breadcrumbNameMap[url]}
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
);
|
||||
});
|
||||
const breadcrumbItems = [(
|
||||
<Breadcrumb.Item key="home">
|
||||
<Link to="/">Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
)].concat(extraBreadcrumbItems);
|
||||
return (
|
||||
<div className="demo">
|
||||
<div className="demo-nav">
|
||||
<a onClick={() => history.push('/')}>Home</a>
|
||||
<a onClick={() => history.push('/apps')}>Application List</a>
|
||||
</div>
|
||||
<Switch>
|
||||
<Route path="/apps" component={Apps} />
|
||||
<Route render={() => <span>Home Page</span>} />
|
||||
</Switch>
|
||||
<Breadcrumb>
|
||||
{breadcrumbItems}
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
describe('react router', () => {
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
// https://github.com/airbnb/enzyme/issues/875
|
||||
it('react router 4', () => {
|
||||
const wrapper = mount(
|
||||
<MemoryRouter initialEntries={['/']} initialIndex={0}>
|
||||
<Home />
|
||||
</MemoryRouter>
|
||||
);
|
||||
expect(wrapper.find('BreadcrumbItem').length).toBe(1);
|
||||
expect(wrapper.find('BreadcrumbItem .ant-breadcrumb-link').at(0).text()).toBe('Home');
|
||||
wrapper.find('.demo-nav a').at(1).simulate('click');
|
||||
expect(wrapper.find('BreadcrumbItem').length).toBe(2);
|
||||
expect(wrapper.find('BreadcrumbItem .ant-breadcrumb-link').at(1).text()).toBe('Application List');
|
||||
});
|
||||
|
||||
it('react router 3', () => {
|
||||
const routes = [{
|
||||
name: 'home',
|
||||
breadcrumbName: 'Home',
|
||||
path: '/',
|
||||
childRoutes: [
|
||||
{
|
||||
name: 'apps',
|
||||
breadcrumbName: 'Application List',
|
||||
path: 'apps',
|
||||
childRoutes: [
|
||||
{
|
||||
name: 'app',
|
||||
breadcrumbName: 'Application:id',
|
||||
path: ':id',
|
||||
childRoutes: [
|
||||
{
|
||||
name: 'detail',
|
||||
breadcrumbName: 'Detail',
|
||||
path: 'detail',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'apps',
|
||||
breadcrumbName: 'Application List',
|
||||
path: 'apps',
|
||||
childRoutes: [
|
||||
{
|
||||
name: 'app',
|
||||
breadcrumbName: 'Application:id',
|
||||
path: ':id',
|
||||
childRoutes: [
|
||||
{
|
||||
name: 'detail',
|
||||
breadcrumbName: 'Detail',
|
||||
path: 'detail',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'app',
|
||||
breadcrumbName: 'Application:id',
|
||||
path: ':id',
|
||||
childRoutes: [
|
||||
{
|
||||
name: 'detail',
|
||||
breadcrumbName: 'Detail',
|
||||
path: 'detail',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'detail',
|
||||
breadcrumbName: 'Detail',
|
||||
path: 'detail',
|
||||
}];
|
||||
const wrapper = mount(
|
||||
<Breadcrumb routes={routes} params={{ id: 1 }} />
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -211,24 +211,6 @@ exports[`renders ./components/button/demo/disabled.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-background-ghost"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Ghost
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-background-ghost"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Ghost(disabled)
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-dashed"
|
||||
type="button"
|
||||
@@ -246,6 +228,27 @@ exports[`renders ./components/button/demo/disabled.md correctly 1`] = `
|
||||
Dashed(disabled)
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
style="padding:8px 8px 0 8px;background:rgb(190, 200, 200)"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-background-ghost"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Ghost
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-background-ghost"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Ghost(disabled)
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
@@ -66,6 +66,48 @@ exports[`Button renders Chinese characters correctly 3`] = `
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button renders Chinese characters correctly 4`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-search"
|
||||
/>
|
||||
<span>
|
||||
按钮
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button renders Chinese characters correctly 5`] = `
|
||||
<button
|
||||
class="ant-btn ant-btn-loading"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-spin anticon-loading"
|
||||
/>
|
||||
<span>
|
||||
按钮
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button renders Chinese characters correctly 6`] = `
|
||||
<button
|
||||
class="ant-btn ant-btn-loading"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-spin anticon-loading"
|
||||
/>
|
||||
<span>
|
||||
按 钮
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button renders correctly 1`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
|
||||
@@ -26,6 +26,21 @@ describe('Button', () => {
|
||||
<Button><Icon type="search" />按钮</Button>
|
||||
);
|
||||
expect(wrapper2).toMatchSnapshot();
|
||||
// should not insert space when there is icon
|
||||
const wrapper3 = render(
|
||||
<Button icon="search">按钮</Button>
|
||||
);
|
||||
expect(wrapper3).toMatchSnapshot();
|
||||
// should not insert space when there is icon while loading
|
||||
const wrapper4 = render(
|
||||
<Button icon="search" loading>按钮</Button>
|
||||
);
|
||||
expect(wrapper4).toMatchSnapshot();
|
||||
// should insert space while loading
|
||||
const wrapper5 = render(
|
||||
<Button loading>按钮</Button>
|
||||
);
|
||||
expect(wrapper5).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders Chinese characters correctly in HOC', () => {
|
||||
@@ -46,7 +61,7 @@ describe('Button', () => {
|
||||
expect(wrapper.find('.ant-btn').hasClass('ant-btn-two-chinese-chars')).toBe(true);
|
||||
});
|
||||
|
||||
it('have static perperty for type detecting', () => {
|
||||
it('have static property for type detecting', () => {
|
||||
const wrapper = mount(
|
||||
<Button>Button Text</Button>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,6 @@ import * as React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import Icon from '../icon';
|
||||
import Group from './button-group';
|
||||
|
||||
@@ -37,30 +36,32 @@ function insertSpace(child: React.ReactChild, needInserted: boolean) {
|
||||
export type ButtonType = 'default' | 'primary' | 'ghost' | 'dashed' | 'danger';
|
||||
export type ButtonShape = 'circle' | 'circle-outline';
|
||||
export type ButtonSize = 'small' | 'default' | 'large';
|
||||
export type ButtonHTMLType = 'submit' | 'button' | 'reset';
|
||||
|
||||
export interface ButtonProps {
|
||||
export interface BaseButtonProps {
|
||||
type?: ButtonType;
|
||||
htmlType?: string;
|
||||
icon?: string;
|
||||
shape?: ButtonShape;
|
||||
size?: ButtonSize;
|
||||
onClick?: React.FormEventHandler<any>;
|
||||
onMouseUp?: React.FormEventHandler<any>;
|
||||
onMouseDown?: React.FormEventHandler<any>;
|
||||
onKeyPress?: React.KeyboardEventHandler<any>;
|
||||
onKeyDown?: React.KeyboardEventHandler<any>;
|
||||
tabIndex?: number;
|
||||
loading?: boolean | { delay?: number };
|
||||
disabled?: boolean;
|
||||
style?: React.CSSProperties;
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
ghost?: boolean;
|
||||
target?: string;
|
||||
href?: string;
|
||||
download?: string;
|
||||
}
|
||||
|
||||
export type AnchorButtonProps = {
|
||||
href: string;
|
||||
target?: string;
|
||||
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
} & BaseButtonProps & React.AnchorHTMLAttributes<HTMLAnchorElement>;
|
||||
|
||||
export type NativeButtonProps = {
|
||||
htmlType?: ButtonHTMLType;
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
} & BaseButtonProps & React.ButtonHTMLAttributes<HTMLButtonElement>;
|
||||
|
||||
export type ButtonProps = AnchorButtonProps | NativeButtonProps;
|
||||
|
||||
export default class Button extends React.Component<ButtonProps, any> {
|
||||
static Group: typeof Group;
|
||||
static __ANT_BUTTON = true;
|
||||
@@ -143,7 +144,7 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
}
|
||||
}
|
||||
|
||||
handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
handleClick: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = e => {
|
||||
// Add click effect
|
||||
this.setState({ clicked: true });
|
||||
clearTimeout(this.timeout);
|
||||
@@ -151,19 +152,18 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
|
||||
const onClick = this.props.onClick;
|
||||
if (onClick) {
|
||||
onClick(e);
|
||||
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
|
||||
}
|
||||
}
|
||||
|
||||
isNeedInserted() {
|
||||
const { loading, icon, children } = this.props;
|
||||
const iconType = loading ? 'loading' : icon;
|
||||
return React.Children.count(children) === 1 && (!iconType || iconType === 'loading');
|
||||
const { icon, children } = this.props;
|
||||
return React.Children.count(children) === 1 && !icon;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
type, shape, size, className, htmlType, children, icon, prefixCls, ghost, ...others,
|
||||
type, shape, size, className, children, icon, prefixCls, ghost, loading: _loadingProp, ...rest
|
||||
} = this.props;
|
||||
|
||||
const { loading, clicked, hasTwoCNChar } = this.state;
|
||||
@@ -181,8 +181,6 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
break;
|
||||
}
|
||||
|
||||
const ComponentProp = others.href ? 'a' : 'button';
|
||||
|
||||
const classes = classNames(prefixCls, className, {
|
||||
[`${prefixCls}-${type}`]: type,
|
||||
[`${prefixCls}-${shape}`]: shape,
|
||||
@@ -199,15 +197,30 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
const kids = (children || children === 0)
|
||||
? React.Children.map(children, child => insertSpace(child, this.isNeedInserted())) : null;
|
||||
|
||||
return (
|
||||
<ComponentProp
|
||||
{...omit(others, ['loading'])}
|
||||
type={others.href ? undefined : (htmlType || 'button')}
|
||||
className={classes}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
{iconNode}{kids}
|
||||
</ComponentProp>
|
||||
);
|
||||
if ('href' in rest) {
|
||||
return (
|
||||
<a
|
||||
{...rest}
|
||||
className={classes}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
{iconNode}{kids}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
// React does not recognize the `htmlType` prop on a DOM element. Here we pick it out of `rest`.
|
||||
const { htmlType, ...otherProps } = rest;
|
||||
|
||||
return (
|
||||
<button
|
||||
{...otherProps}
|
||||
type={htmlType || 'button'}
|
||||
className={classes}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
{iconNode}{kids}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,12 @@ ReactDOM.render(
|
||||
<Button>Default</Button>
|
||||
<Button disabled>Default(disabled)</Button>
|
||||
<br />
|
||||
<Button ghost>Ghost</Button>
|
||||
<Button ghost disabled>Ghost(disabled)</Button>
|
||||
<br />
|
||||
<Button type="dashed">Dashed</Button>
|
||||
<Button type="dashed" disabled>Dashed(disabled)</Button>
|
||||
<div style={{ padding: '8px 8px 0 8px', background: 'rgb(190, 200, 200)' }}>
|
||||
<Button ghost>Ghost</Button>
|
||||
<Button ghost disabled>Ghost(disabled)</Button>
|
||||
</div>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
|
||||
@@ -21,6 +21,7 @@ To get a customized button, just set `type`/`shape`/`size`/`loading`/`disabled`.
|
||||
| htmlType | set the original html `type` of `button`, see: [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type) | string | `button` |
|
||||
| icon | set the icon of button, see: Icon component | string | - |
|
||||
| loading | set the loading status of button | boolean \| { delay: number } | false |
|
||||
| disabled | disabled state of button | boolean | `false` |
|
||||
| shape | can be set to `circle` or omitted | string | - |
|
||||
| size | can be set to `small` `large` or omitted | string | `default` |
|
||||
| target | same as target attribute of a, works when href is specified | string | - |
|
||||
|
||||
@@ -24,6 +24,7 @@ subtitle: 按钮
|
||||
| htmlType | 设置 `button` 原生的 `type` 值,可选值请参考 [HTML 标准](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type) | string | `button` |
|
||||
| icon | 设置按钮的图标类型 | string | - |
|
||||
| loading | 设置按钮载入状态 | boolean \| { delay: number } | `false` |
|
||||
| disabled | 按钮失效状态 | boolean | `false` |
|
||||
| shape | 设置按钮形状,可选值为 `circle` 或者不设 | string | - |
|
||||
| size | 设置按钮大小,可选值为 `small` `large` 或者不设 | string | `default` |
|
||||
| target | 相当于 a 链接的 target 属性,href 存在时生效 | string | - |
|
||||
|
||||
@@ -250,11 +250,16 @@
|
||||
.@{btnClassName} + &,
|
||||
span + .@{btnClassName},
|
||||
.@{btnClassName} + span,
|
||||
> span + span,
|
||||
& + .@{btnClassName},
|
||||
& + & {
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
.@{btnClassName}-primary + .@{btnClassName}:not(.@{btnClassName}-primary):not([disabled]) {
|
||||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
.@{btnClassName}:not(:first-child):not(:last-child) {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ exports[`renders ./components/calendar/demo/basic.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -65,7 +65,7 @@ exports[`renders ./components/calendar/demo/basic.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -236,7 +236,7 @@ exports[`renders ./components/calendar/demo/basic.md correctly 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell"
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell ant-fullcalendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="October 31, 2016"
|
||||
>
|
||||
@@ -796,7 +796,7 @@ exports[`renders ./components/calendar/demo/basic.md correctly 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="November 30, 2016"
|
||||
>
|
||||
@@ -1042,7 +1042,7 @@ exports[`renders ./components/calendar/demo/card.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -1074,7 +1074,7 @@ exports[`renders ./components/calendar/demo/card.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -1245,7 +1245,7 @@ exports[`renders ./components/calendar/demo/card.md correctly 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell"
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell ant-fullcalendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="October 31, 2016"
|
||||
>
|
||||
@@ -1805,7 +1805,7 @@ exports[`renders ./components/calendar/demo/card.md correctly 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="November 30, 2016"
|
||||
>
|
||||
@@ -2049,7 +2049,7 @@ exports[`renders ./components/calendar/demo/notice-calendar.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -2081,7 +2081,7 @@ exports[`renders ./components/calendar/demo/notice-calendar.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -2256,7 +2256,7 @@ exports[`renders ./components/calendar/demo/notice-calendar.md correctly 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell"
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-month-cell ant-fullcalendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="October 31, 2016"
|
||||
>
|
||||
@@ -3093,7 +3093,7 @@ exports[`renders ./components/calendar/demo/notice-calendar.md correctly 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="November 30, 2016"
|
||||
>
|
||||
@@ -3466,7 +3466,7 @@ exports[`renders ./components/calendar/demo/select.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -3498,7 +3498,7 @@ exports[`renders ./components/calendar/demo/select.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -4211,7 +4211,7 @@ exports[`renders ./components/calendar/demo/select.md correctly 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-fullcalendar-cell"
|
||||
class="ant-fullcalendar-cell ant-fullcalendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="January 31, 2017"
|
||||
>
|
||||
|
||||
@@ -235,7 +235,7 @@
|
||||
}
|
||||
|
||||
&-fullscreen &-content {
|
||||
height: 90px;
|
||||
height: 88px;
|
||||
overflow-y: auto;
|
||||
position: static;
|
||||
width: auto;
|
||||
|
||||
152
components/card/__tests__/__snapshots__/index.test.js.snap
Normal file
152
components/card/__tests__/__snapshots__/index.test.js.snap
Normal file
@@ -0,0 +1,152 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Card should still have padding when card which set padding to 0 is loading 1`] = `
|
||||
<div
|
||||
class="ant-card ant-card-loading ant-card-bordered"
|
||||
>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
style="padding: 0px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-content"
|
||||
style="padding: 24px;"
|
||||
>
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left: -4px; margin-right: -4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-col-22"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left: -4px; margin-right: -4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-col-8"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-15"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left: -4px; margin-right: -4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-18"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left: -4px; margin-right: -4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-col-13"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-9"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left: -4px; margin-right: -4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-col-4"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-3"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-16"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left: -4px; margin-right: -4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-col-8"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-8"
|
||||
style="padding-left: 4px; padding-right: 4px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-loading-block"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -34,4 +34,9 @@ describe('Card', () => {
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-card-wider-padding').length).toBe(0);
|
||||
});
|
||||
|
||||
it('should still have padding when card which set padding to 0 is loading', () => {
|
||||
const wrapper = mount(<Card loading bodyStyle={{ padding: 0 }}>xxx</Card>);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -133,8 +133,8 @@ export default class Card extends React.Component<CardProps, CardState> {
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
prefixCls = 'ant-card', className, extra, bodyStyle, noHovering, hoverable, title, loading,
|
||||
bordered = true, type, cover, actions, tabList, children, activeTabKey, defaultActiveTabKey, ...others,
|
||||
prefixCls = 'ant-card', className, extra, bodyStyle = {}, noHovering, hoverable, title, loading,
|
||||
bordered = true, type, cover, actions, tabList, children, activeTabKey, defaultActiveTabKey, ...others
|
||||
} = this.props;
|
||||
|
||||
const classString = classNames(prefixCls, className, {
|
||||
@@ -148,8 +148,14 @@ export default class Card extends React.Component<CardProps, CardState> {
|
||||
[`${prefixCls}-type-${type}`]: !!type,
|
||||
});
|
||||
|
||||
const loadingBlockStyle = (bodyStyle.padding === 0 || bodyStyle.padding === '0px')
|
||||
? { padding: 24 } : undefined;
|
||||
|
||||
const loadingBlock = (
|
||||
<div className={`${prefixCls}-loading-content`}>
|
||||
<div
|
||||
className={`${prefixCls}-loading-content`}
|
||||
style={loadingBlockStyle}
|
||||
>
|
||||
<Row gutter={8}>
|
||||
<Col span={22}>
|
||||
<div className={`${prefixCls}-loading-block`} />
|
||||
|
||||
@@ -3,6 +3,14 @@ import { mount } from 'enzyme';
|
||||
import Carousel from '..';
|
||||
|
||||
describe('Carousel', () => {
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('should has innerSlider', () => {
|
||||
const wrapper = mount(<Carousel><div /></Carousel>);
|
||||
const { innerSlider } = wrapper.instance();
|
||||
@@ -10,4 +18,42 @@ describe('Carousel', () => {
|
||||
expect(innerSlider).toBe(innerSliderFromRefs);
|
||||
expect(typeof innerSlider.slickNext).toBe('function');
|
||||
});
|
||||
|
||||
it('should has prev, next and go function', () => {
|
||||
const wrapper = mount(<Carousel><div>1</div><div>2</div><div>3</div></Carousel>);
|
||||
const { prev, next, goTo } = wrapper.instance();
|
||||
expect(typeof prev).toBe('function');
|
||||
expect(typeof next).toBe('function');
|
||||
expect(typeof goTo).toBe('function');
|
||||
expect(wrapper.instance().slick.innerSlider.state.currentSlide).toBe(0);
|
||||
wrapper.instance().goTo(2);
|
||||
jest.runAllTimers();
|
||||
expect(wrapper.instance().slick.innerSlider.state.currentSlide).toBe(2);
|
||||
wrapper.instance().prev();
|
||||
jest.runAllTimers();
|
||||
expect(wrapper.instance().slick.innerSlider.state.currentSlide).toBe(1);
|
||||
wrapper.instance().next();
|
||||
jest.runAllTimers();
|
||||
expect(wrapper.instance().slick.innerSlider.state.currentSlide).toBe(2);
|
||||
});
|
||||
|
||||
it('should trigger autoPlay after window resize', async () => {
|
||||
jest.useRealTimers();
|
||||
const wrapper = mount(<Carousel autoplay><div>1</div><div>2</div><div>3</div></Carousel>);
|
||||
const spy = jest.spyOn(wrapper.instance().slick.innerSlider, 'autoPlay');
|
||||
window.resizeTo(1000);
|
||||
expect(spy).not.toBeCalled();
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
expect(spy).toBeCalled();
|
||||
});
|
||||
|
||||
it('cancel resize listener when unmount', async () => {
|
||||
const wrapper = mount(<Carousel autoplay><div>1</div><div>2</div><div>3</div></Carousel>);
|
||||
const onWindowResized = wrapper.instance().onWindowResized;
|
||||
const spy = jest.spyOn(wrapper.instance().onWindowResized, 'cancel');
|
||||
const spy2 = jest.spyOn(window, 'removeEventListener');
|
||||
wrapper.unmount();
|
||||
expect(spy).toBeCalled();
|
||||
expect(spy2).toBeCalledWith('resize', onWindowResized);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -143,6 +143,28 @@ exports[`renders ./components/cascader/demo/disabled-option.md correctly 1`] = `
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/cascader/demo/fileds-name.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-cascader-picker"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="ant-cascader-picker-label"
|
||||
/>
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="ant-input ant-cascader-input "
|
||||
placeholder="Please select"
|
||||
readonly=""
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<i
|
||||
class="anticon anticon-down ant-cascader-picker-arrow"
|
||||
/>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/cascader/demo/hover.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-cascader-picker"
|
||||
@@ -189,7 +211,7 @@ exports[`renders ./components/cascader/demo/lazy.md correctly 1`] = `
|
||||
|
||||
exports[`renders ./components/cascader/demo/search.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-cascader-picker"
|
||||
class="ant-cascader-picker ant-cascader-picker-show-search"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
|
||||
@@ -215,6 +215,632 @@ exports[`Cascader popup correctly with defaultValue 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Cascader should highlight keyword and filter when search in Cascader 1`] = `
|
||||
<Popup
|
||||
action={
|
||||
Array [
|
||||
"click",
|
||||
]
|
||||
}
|
||||
align={
|
||||
Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"tl",
|
||||
"bl",
|
||||
],
|
||||
}
|
||||
}
|
||||
className=""
|
||||
destroyPopupOnHide={false}
|
||||
getClassNameFromAlign={[Function]}
|
||||
getRootDomNode={[Function]}
|
||||
mask={false}
|
||||
onAlign={[Function]}
|
||||
prefixCls="ant-cascader-menus"
|
||||
style={Object {}}
|
||||
transitionName="slide-up"
|
||||
visible={true}
|
||||
>
|
||||
<div>
|
||||
<Animate
|
||||
animation={Object {}}
|
||||
component=""
|
||||
componentProps={Object {}}
|
||||
exclusive={true}
|
||||
onAppear={[Function]}
|
||||
onEnd={[Function]}
|
||||
onEnter={[Function]}
|
||||
onLeave={[Function]}
|
||||
showProp="xVisible"
|
||||
transitionAppear={true}
|
||||
transitionEnter={true}
|
||||
transitionLeave={true}
|
||||
transitionName="slide-up"
|
||||
>
|
||||
<AnimateChild
|
||||
animation={Object {}}
|
||||
key="popup"
|
||||
transitionAppear={true}
|
||||
transitionEnter={true}
|
||||
transitionLeave={true}
|
||||
transitionName="slide-up"
|
||||
>
|
||||
<Align
|
||||
align={
|
||||
Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"tl",
|
||||
"bl",
|
||||
],
|
||||
}
|
||||
}
|
||||
childrenProps={
|
||||
Object {
|
||||
"visible": "xVisible",
|
||||
}
|
||||
}
|
||||
disabled={false}
|
||||
key="popup"
|
||||
monitorBufferTime={50}
|
||||
monitorWindowResize={true}
|
||||
onAlign={[Function]}
|
||||
target={[Function]}
|
||||
xVisible={true}
|
||||
>
|
||||
<PopupInner
|
||||
className="ant-cascader-menus ant-cascader-menus-placement-bottomLeft "
|
||||
hiddenClassName="ant-cascader-menus-hidden"
|
||||
prefixCls="ant-cascader-menus"
|
||||
style={Object {}}
|
||||
visible={true}
|
||||
>
|
||||
<div
|
||||
className="ant-cascader-menus ant-cascader-menus-placement-bottomLeft "
|
||||
style={Object {}}
|
||||
>
|
||||
<LazyRenderBox
|
||||
className="ant-cascader-menus-content"
|
||||
visible={true}
|
||||
>
|
||||
<Menus
|
||||
activeValue={Array []}
|
||||
allowClear={true}
|
||||
builtinPlacements={
|
||||
Object {
|
||||
"bottomLeft": Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"tl",
|
||||
"bl",
|
||||
],
|
||||
},
|
||||
"bottomRight": Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"tr",
|
||||
"br",
|
||||
],
|
||||
},
|
||||
"topLeft": Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
-4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"bl",
|
||||
"tl",
|
||||
],
|
||||
},
|
||||
"topRight": Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
-4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"br",
|
||||
"tr",
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
defaultFiledNames={
|
||||
Object {
|
||||
"children": "children",
|
||||
"label": "label",
|
||||
"value": "value",
|
||||
}
|
||||
}
|
||||
disabled={false}
|
||||
dropdownMenuColumnStyle={
|
||||
Object {
|
||||
"width": 0,
|
||||
}
|
||||
}
|
||||
expandTrigger="click"
|
||||
filedNames={
|
||||
Object {
|
||||
"children": "children",
|
||||
"label": "label",
|
||||
"value": "value",
|
||||
}
|
||||
}
|
||||
inputPrefixCls="ant-input"
|
||||
notFoundContent="Not Found"
|
||||
onChange={[Function]}
|
||||
onPopupVisibleChange={[Function]}
|
||||
onSelect={[Function]}
|
||||
options={
|
||||
Array [
|
||||
Object {
|
||||
"__IS_FILTERED_OPTION": true,
|
||||
"disabled": false,
|
||||
"label": Array [
|
||||
"Jiangsu",
|
||||
Array [
|
||||
" / ",
|
||||
"Nanjing",
|
||||
],
|
||||
Array [
|
||||
" / ",
|
||||
"Zhong Hua Men",
|
||||
],
|
||||
],
|
||||
"path": Array [
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"label": "Zhong Hua Men",
|
||||
"value": "zhonghuamen",
|
||||
},
|
||||
],
|
||||
"label": "Nanjing",
|
||||
"value": "nanjing",
|
||||
},
|
||||
],
|
||||
"label": "Jiangsu",
|
||||
"value": "jiangsu",
|
||||
},
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"label": "Zhong Hua Men",
|
||||
"value": "zhonghuamen",
|
||||
},
|
||||
],
|
||||
"label": "Nanjing",
|
||||
"value": "nanjing",
|
||||
},
|
||||
Object {
|
||||
"label": "Zhong Hua Men",
|
||||
"value": "zhonghuamen",
|
||||
},
|
||||
],
|
||||
"value": Array [
|
||||
"jiangsu",
|
||||
"nanjing",
|
||||
"zhonghuamen",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"__IS_FILTERED_OPTION": true,
|
||||
"disabled": false,
|
||||
"label": Array [
|
||||
"Zhejiang",
|
||||
Array [
|
||||
" / ",
|
||||
Array [
|
||||
"Hang",
|
||||
Array [
|
||||
<span
|
||||
className="ant-cascader-menu-item-keyword"
|
||||
>
|
||||
z
|
||||
</span>,
|
||||
"hou",
|
||||
],
|
||||
],
|
||||
],
|
||||
Array [
|
||||
" / ",
|
||||
"West Lake",
|
||||
],
|
||||
],
|
||||
"path": Array [
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"label": "West Lake",
|
||||
"value": "xihu",
|
||||
},
|
||||
],
|
||||
"label": "Hangzhou",
|
||||
"value": "hangzhou",
|
||||
},
|
||||
],
|
||||
"label": "Zhejiang",
|
||||
"value": "zhejiang",
|
||||
},
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"label": "West Lake",
|
||||
"value": "xihu",
|
||||
},
|
||||
],
|
||||
"label": "Hangzhou",
|
||||
"value": "hangzhou",
|
||||
},
|
||||
Object {
|
||||
"label": "West Lake",
|
||||
"value": "xihu",
|
||||
},
|
||||
],
|
||||
"value": Array [
|
||||
"zhejiang",
|
||||
"hangzhou",
|
||||
"xihu",
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
placeholder="Please select"
|
||||
popupClassName=""
|
||||
popupPlacement="bottomLeft"
|
||||
popupVisible={true}
|
||||
prefixCls="ant-cascader"
|
||||
showSearch={
|
||||
Object {
|
||||
"filter": [Function],
|
||||
}
|
||||
}
|
||||
transitionName="slide-up"
|
||||
value={Array []}
|
||||
visible={true}
|
||||
>
|
||||
<div>
|
||||
<ul
|
||||
className="ant-cascader-menu"
|
||||
key="0"
|
||||
style={
|
||||
Object {
|
||||
"width": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<li
|
||||
className="ant-cascader-menu-item"
|
||||
key="jiangsu,nanjing,zhonghuamen"
|
||||
onClick={[Function]}
|
||||
title=""
|
||||
>
|
||||
Jiangsu
|
||||
/
|
||||
Nanjing
|
||||
/
|
||||
Zhong Hua Men
|
||||
</li>
|
||||
<li
|
||||
className="ant-cascader-menu-item"
|
||||
key="zhejiang,hangzhou,xihu"
|
||||
onClick={[Function]}
|
||||
title=""
|
||||
>
|
||||
Zhejiang
|
||||
/
|
||||
Hang
|
||||
<span
|
||||
className="ant-cascader-menu-item-keyword"
|
||||
key="seperator"
|
||||
>
|
||||
z
|
||||
</span>
|
||||
hou
|
||||
/
|
||||
West Lake
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Menus>
|
||||
</LazyRenderBox>
|
||||
</div>
|
||||
</PopupInner>
|
||||
</Align>
|
||||
</AnimateChild>
|
||||
</Animate>
|
||||
</div>
|
||||
</Popup>
|
||||
`;
|
||||
|
||||
exports[`Cascader should render not found content 1`] = `
|
||||
<Popup
|
||||
action={
|
||||
Array [
|
||||
"click",
|
||||
]
|
||||
}
|
||||
align={
|
||||
Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"tl",
|
||||
"bl",
|
||||
],
|
||||
}
|
||||
}
|
||||
className=""
|
||||
destroyPopupOnHide={false}
|
||||
getClassNameFromAlign={[Function]}
|
||||
getRootDomNode={[Function]}
|
||||
mask={false}
|
||||
onAlign={[Function]}
|
||||
prefixCls="ant-cascader-menus"
|
||||
style={Object {}}
|
||||
transitionName="slide-up"
|
||||
visible={true}
|
||||
>
|
||||
<div>
|
||||
<Animate
|
||||
animation={Object {}}
|
||||
component=""
|
||||
componentProps={Object {}}
|
||||
exclusive={true}
|
||||
onAppear={[Function]}
|
||||
onEnd={[Function]}
|
||||
onEnter={[Function]}
|
||||
onLeave={[Function]}
|
||||
showProp="xVisible"
|
||||
transitionAppear={true}
|
||||
transitionEnter={true}
|
||||
transitionLeave={true}
|
||||
transitionName="slide-up"
|
||||
>
|
||||
<AnimateChild
|
||||
animation={Object {}}
|
||||
key="popup"
|
||||
transitionAppear={true}
|
||||
transitionEnter={true}
|
||||
transitionLeave={true}
|
||||
transitionName="slide-up"
|
||||
>
|
||||
<Align
|
||||
align={
|
||||
Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"tl",
|
||||
"bl",
|
||||
],
|
||||
}
|
||||
}
|
||||
childrenProps={
|
||||
Object {
|
||||
"visible": "xVisible",
|
||||
}
|
||||
}
|
||||
disabled={false}
|
||||
key="popup"
|
||||
monitorBufferTime={50}
|
||||
monitorWindowResize={true}
|
||||
onAlign={[Function]}
|
||||
target={[Function]}
|
||||
xVisible={true}
|
||||
>
|
||||
<PopupInner
|
||||
className="ant-cascader-menus ant-cascader-menus-placement-bottomLeft "
|
||||
hiddenClassName="ant-cascader-menus-hidden"
|
||||
prefixCls="ant-cascader-menus"
|
||||
style={Object {}}
|
||||
visible={true}
|
||||
>
|
||||
<div
|
||||
className="ant-cascader-menus ant-cascader-menus-placement-bottomLeft "
|
||||
style={Object {}}
|
||||
>
|
||||
<LazyRenderBox
|
||||
className="ant-cascader-menus-content"
|
||||
visible={true}
|
||||
>
|
||||
<Menus
|
||||
activeValue={Array []}
|
||||
allowClear={true}
|
||||
builtinPlacements={
|
||||
Object {
|
||||
"bottomLeft": Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"tl",
|
||||
"bl",
|
||||
],
|
||||
},
|
||||
"bottomRight": Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"tr",
|
||||
"br",
|
||||
],
|
||||
},
|
||||
"topLeft": Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
-4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"bl",
|
||||
"tl",
|
||||
],
|
||||
},
|
||||
"topRight": Object {
|
||||
"offset": Array [
|
||||
0,
|
||||
-4,
|
||||
],
|
||||
"overflow": Object {
|
||||
"adjustX": 1,
|
||||
"adjustY": 1,
|
||||
},
|
||||
"points": Array [
|
||||
"br",
|
||||
"tr",
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
defaultFiledNames={
|
||||
Object {
|
||||
"children": "children",
|
||||
"label": "label",
|
||||
"value": "value",
|
||||
}
|
||||
}
|
||||
disabled={false}
|
||||
dropdownMenuColumnStyle={
|
||||
Object {
|
||||
"height": "auto",
|
||||
"width": 0,
|
||||
}
|
||||
}
|
||||
expandTrigger="click"
|
||||
filedNames={
|
||||
Object {
|
||||
"children": "children",
|
||||
"label": "label",
|
||||
"value": "value",
|
||||
}
|
||||
}
|
||||
inputPrefixCls="ant-input"
|
||||
notFoundContent="Not Found"
|
||||
onChange={[Function]}
|
||||
onPopupVisibleChange={[Function]}
|
||||
onSelect={[Function]}
|
||||
options={
|
||||
Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"label": "Not Found",
|
||||
"value": "ANT_CASCADER_NOT_FOUND",
|
||||
},
|
||||
]
|
||||
}
|
||||
placeholder="Please select"
|
||||
popupClassName=""
|
||||
popupPlacement="bottomLeft"
|
||||
popupVisible={true}
|
||||
prefixCls="ant-cascader"
|
||||
showSearch={
|
||||
Object {
|
||||
"filter": [Function],
|
||||
}
|
||||
}
|
||||
transitionName="slide-up"
|
||||
value={Array []}
|
||||
visible={true}
|
||||
>
|
||||
<div>
|
||||
<ul
|
||||
className="ant-cascader-menu"
|
||||
key="0"
|
||||
style={
|
||||
Object {
|
||||
"height": "auto",
|
||||
"width": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<li
|
||||
className="ant-cascader-menu-item ant-cascader-menu-item-disabled"
|
||||
key="ANT_CASCADER_NOT_FOUND"
|
||||
onClick={[Function]}
|
||||
title="Not Found"
|
||||
>
|
||||
Not Found
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Menus>
|
||||
</LazyRenderBox>
|
||||
</div>
|
||||
</PopupInner>
|
||||
</Align>
|
||||
</AnimateChild>
|
||||
</Animate>
|
||||
</div>
|
||||
</Popup>
|
||||
`;
|
||||
|
||||
exports[`Cascader support controlled mode 1`] = `
|
||||
<span
|
||||
class="ant-cascader-picker"
|
||||
|
||||
@@ -28,6 +28,10 @@ const options = [{
|
||||
}],
|
||||
}];
|
||||
|
||||
function filter(inputValue, path) {
|
||||
return path.some(option => (option.label).toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
|
||||
}
|
||||
|
||||
describe('Cascader', () => {
|
||||
focusTest(Cascader);
|
||||
|
||||
@@ -39,11 +43,13 @@ describe('Cascader', () => {
|
||||
});
|
||||
|
||||
it('popup correctly when panel is open', () => {
|
||||
const onPopupVisibleChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Cascader options={options} />
|
||||
<Cascader options={options} onPopupVisibleChange={onPopupVisibleChange} />
|
||||
);
|
||||
wrapper.find('input').simulate('click');
|
||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
||||
expect(onPopupVisibleChange).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it('support controlled mode', () => {
|
||||
@@ -64,8 +70,18 @@ describe('Cascader', () => {
|
||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support popupVisible', () => {
|
||||
const wrapper = mount(
|
||||
<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />
|
||||
);
|
||||
expect(wrapper.find('Trigger').instance().getComponent().props.visible).toBe(false);
|
||||
wrapper.setProps({ popupVisible: true });
|
||||
expect(wrapper.find('Trigger').instance().getComponent().props.visible).toBe(true);
|
||||
});
|
||||
|
||||
it('can be selected', () => {
|
||||
const wrapper = mount(<Cascader options={options} />);
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<Cascader options={options} onChange={onChange} />);
|
||||
wrapper.find('input').simulate('click');
|
||||
let popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
||||
popupWrapper.find('.ant-cascader-menu').at(0).find('.ant-cascader-menu-item').at(0)
|
||||
@@ -79,6 +95,7 @@ describe('Cascader', () => {
|
||||
popupWrapper.find('.ant-cascader-menu').at(2).find('.ant-cascader-menu-item').at(0)
|
||||
.simulate('click');
|
||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
||||
expect(onChange).toHaveBeenCalledWith(['zhejiang', 'hangzhou', 'xihu'], expect.anything());
|
||||
});
|
||||
|
||||
it('backspace should work with `Cascader[showSearch]`', () => {
|
||||
@@ -89,4 +106,88 @@ describe('Cascader', () => {
|
||||
// Simulate onKeyDown will not trigger onChange by default, so the value is still '123'
|
||||
expect(wrapper.state('inputValue')).toBe('123');
|
||||
});
|
||||
|
||||
it('should highlight keyword and filter when search in Cascader', () => {
|
||||
const wrapper = mount(<Cascader options={options} showSearch={{ filter }} />);
|
||||
wrapper.find('input').simulate('click');
|
||||
wrapper.find('input').simulate('change', { target: { value: 'z' } });
|
||||
expect(wrapper.state('inputValue')).toBe('z');
|
||||
const popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
||||
expect(popupWrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render not found content', () => {
|
||||
const wrapper = mount(<Cascader options={options} showSearch={{ filter }} />);
|
||||
wrapper.find('input').simulate('click');
|
||||
wrapper.find('input').simulate('change', { target: { value: '__notfoundkeyword__' } });
|
||||
expect(wrapper.state('inputValue')).toBe('__notfoundkeyword__');
|
||||
const popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
||||
expect(popupWrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support to clear selection', () => {
|
||||
const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />);
|
||||
expect(wrapper.find('.ant-cascader-picker-label').text()).toBe('Zhejiang / Hangzhou');
|
||||
wrapper.find('.ant-cascader-picker-clear').at(0).simulate('click');
|
||||
expect(wrapper.find('.ant-cascader-picker-label').text()).toBe('');
|
||||
});
|
||||
|
||||
it('should close popup when clear selection', () => {
|
||||
const onPopupVisibleChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Cascader
|
||||
options={options}
|
||||
popupVisible
|
||||
defaultValue={['zhejiang', 'hangzhou']}
|
||||
onPopupVisibleChange={onPopupVisibleChange}
|
||||
/>
|
||||
);
|
||||
wrapper.find('.ant-cascader-picker-clear').at(0).simulate('click');
|
||||
expect(onPopupVisibleChange).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('should clear search input when clear selection', () => {
|
||||
const wrapper = mount(
|
||||
<Cascader
|
||||
options={options}
|
||||
defaultValue={['zhejiang', 'hangzhou']}
|
||||
showSearch
|
||||
/>
|
||||
);
|
||||
wrapper.find('input').simulate('click');
|
||||
wrapper.find('input').simulate('change', { target: { value: 'xxx' } });
|
||||
expect(wrapper.state('inputValue')).toBe('xxx');
|
||||
wrapper.find('.ant-cascader-picker-clear').at(0).simulate('click');
|
||||
expect(wrapper.state('inputValue')).toBe('');
|
||||
});
|
||||
|
||||
it('should not trigger visible change when click search input', () => {
|
||||
const onPopupVisibleChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Cascader
|
||||
options={options}
|
||||
showSearch
|
||||
onPopupVisibleChange={onPopupVisibleChange}
|
||||
/>
|
||||
);
|
||||
wrapper.find('input').simulate('focus');
|
||||
expect(onPopupVisibleChange).toHaveBeenCalledTimes(0);
|
||||
wrapper.find('input').simulate('click');
|
||||
expect(onPopupVisibleChange).toHaveBeenCalledTimes(1);
|
||||
wrapper.find('input').simulate('click');
|
||||
expect(onPopupVisibleChange).toHaveBeenCalledTimes(1);
|
||||
wrapper.find('input').simulate('blur');
|
||||
wrapper.setState({ popupVisible: false });
|
||||
wrapper.find('input').simulate('click');
|
||||
expect(onPopupVisibleChange).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('should change filtered item when options are changed', () => {
|
||||
const wrapper = mount(<Cascader options={options} showSearch={{ filter }} />);
|
||||
wrapper.find('input').simulate('click');
|
||||
wrapper.find('input').simulate('change', { target: { value: 'a' } });
|
||||
expect(wrapper.find('.ant-cascader-menu-item').length).toBe(2);
|
||||
wrapper.setProps({ options: [options[0]] });
|
||||
expect(wrapper.find('.ant-cascader-menu-item').length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
50
components/cascader/demo/fileds-name.md
Normal file
50
components/cascader/demo/fileds-name.md
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
order: 10
|
||||
title:
|
||||
zh-CN: 自定义字段名
|
||||
en-US: Custom Filed Names
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
自定义字段名。
|
||||
|
||||
## en-US
|
||||
|
||||
Custom filed names.
|
||||
|
||||
````jsx
|
||||
import { Cascader } from 'antd';
|
||||
|
||||
const options = [{
|
||||
code: 'zhejiang',
|
||||
name: 'Zhejiang',
|
||||
items: [{
|
||||
code: 'hangzhou',
|
||||
name: 'Hangzhou',
|
||||
items: [{
|
||||
code: 'xihu',
|
||||
name: 'West Lake',
|
||||
}],
|
||||
}],
|
||||
}, {
|
||||
code: 'jiangsu',
|
||||
name: 'Jiangsu',
|
||||
items: [{
|
||||
code: 'nanjing',
|
||||
name: 'Nanjing',
|
||||
items: [{
|
||||
code: 'zhonghuamen',
|
||||
name: 'Zhong Hua Men',
|
||||
}],
|
||||
}],
|
||||
}];
|
||||
|
||||
function onChange(value) {
|
||||
console.log(value);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<Cascader filedNames={{ label: 'name', value: 'code', children: 'items' }} options={options} onChange={onChange} placeholder="Please select" />
|
||||
, mountNode);
|
||||
````
|
||||
@@ -42,6 +42,7 @@ Cascade selection box.
|
||||
| value | selected value | string\[] | - |
|
||||
| onChange | callback when finishing cascader select | `(value, selectedOptions) => void` | - |
|
||||
| onPopupVisibleChange | callback when popup shown or hidden | `(value) => void` | - |
|
||||
| filedNames | custom field name for label and value and children | object | `{ label: 'label', value: 'value', children: 'children' }` |
|
||||
|
||||
Fields in `showSearch`:
|
||||
|
||||
|
||||
@@ -8,19 +8,36 @@ import Input from '../input';
|
||||
import Icon from '../icon';
|
||||
|
||||
export interface CascaderOptionType {
|
||||
value: string;
|
||||
label: React.ReactNode;
|
||||
value?: string;
|
||||
label?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
children?: Array<CascaderOptionType>;
|
||||
__IS_FILTERED_OPTION?: boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface FiledNamesType {
|
||||
value?: string;
|
||||
label?: string;
|
||||
children?: string;
|
||||
}
|
||||
|
||||
export interface FilledFiledNamesType {
|
||||
value: string;
|
||||
label: string;
|
||||
children: string;
|
||||
}
|
||||
|
||||
export type CascaderExpandTrigger = 'click' | 'hover';
|
||||
|
||||
export interface ShowSearchType {
|
||||
filter?: (inputValue: string, path: CascaderOptionType[]) => boolean;
|
||||
render?: (inputValue: string, path: CascaderOptionType[], prefixCls: string | undefined) => React.ReactNode;
|
||||
sort?: (a: CascaderOptionType[], b: CascaderOptionType[], inputValue: string) => number;
|
||||
filter?: (inputValue: string, path: CascaderOptionType[], names: FilledFiledNamesType) => boolean;
|
||||
render?: (
|
||||
inputValue: string,
|
||||
path: CascaderOptionType[],
|
||||
prefixCls: string | undefined,
|
||||
names: FilledFiledNamesType,
|
||||
) => React.ReactNode;
|
||||
sort?: (a: CascaderOptionType[], b: CascaderOptionType[], inputValue: string, names: FilledFiledNamesType) => number;
|
||||
matchInputWidth?: boolean;
|
||||
}
|
||||
|
||||
@@ -64,6 +81,7 @@ export interface CascaderProps {
|
||||
inputPrefixCls?: string;
|
||||
getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement;
|
||||
popupVisible?: boolean;
|
||||
filedNames?: FiledNamesType;
|
||||
}
|
||||
|
||||
export interface CascaderState {
|
||||
@@ -71,7 +89,7 @@ export interface CascaderState {
|
||||
inputValue: string;
|
||||
value: string[];
|
||||
popupVisible: boolean | undefined;
|
||||
flattenOptions: CascaderOptionType[][];
|
||||
flattenOptions: CascaderOptionType[][] | undefined;
|
||||
}
|
||||
|
||||
function highlightKeyword(str: string, keyword: string, prefixCls: string | undefined) {
|
||||
@@ -82,26 +100,43 @@ function highlightKeyword(str: string, keyword: string, prefixCls: string | unde
|
||||
]);
|
||||
}
|
||||
|
||||
function defaultFilterOption(inputValue: string, path: CascaderOptionType[]) {
|
||||
return path.some(option => (option.label as string).indexOf(inputValue) > -1);
|
||||
function defaultFilterOption(inputValue: string, path: CascaderOptionType[], names: FilledFiledNamesType) {
|
||||
return path.some(option => (option[names.label] as string).indexOf(inputValue) > -1);
|
||||
}
|
||||
|
||||
function defaultRenderFilteredOption(inputValue: string, path: CascaderOptionType[], prefixCls: string | undefined) {
|
||||
return path.map(({ label }, index) => {
|
||||
function defaultRenderFilteredOption(
|
||||
inputValue: string,
|
||||
path: CascaderOptionType[],
|
||||
prefixCls: string | undefined,
|
||||
names: FilledFiledNamesType,
|
||||
) {
|
||||
return path.map((option, index) => {
|
||||
const label = option[names.label];
|
||||
const node = (label as string).indexOf(inputValue) > -1 ?
|
||||
highlightKeyword(label as string, inputValue, prefixCls) : label;
|
||||
return index === 0 ? node : [' / ', node];
|
||||
});
|
||||
}
|
||||
|
||||
function defaultSortFilteredOption(a: any[], b: any[], inputValue: string) {
|
||||
function defaultSortFilteredOption(
|
||||
a: CascaderOptionType[], b: CascaderOptionType[], inputValue: string, names: FilledFiledNamesType,
|
||||
) {
|
||||
function callback(elem: CascaderOptionType) {
|
||||
return (elem.label as string).indexOf(inputValue) > -1;
|
||||
return (elem[names.label] as string).indexOf(inputValue) > -1;
|
||||
}
|
||||
|
||||
return a.findIndex(callback) - b.findIndex(callback);
|
||||
}
|
||||
|
||||
function getFilledFieldNames(filedNames: FiledNamesType = {}) {
|
||||
const names: FilledFiledNamesType = {
|
||||
children: filedNames.children || 'children',
|
||||
label: filedNames.label || 'label',
|
||||
value: filedNames.value || 'value',
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
const defaultDisplayRender = (label: string[]) => label.join(' / ');
|
||||
|
||||
export default class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
@@ -128,7 +163,8 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
inputValue: '',
|
||||
inputFocused: false,
|
||||
popupVisible: props.popupVisible,
|
||||
flattenOptions: props.showSearch && this.flattenTree(props.options, props.changeOnSelect),
|
||||
flattenOptions:
|
||||
props.showSearch ? this.flattenTree(props.options, props.changeOnSelect, props.filedNames) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -140,11 +176,13 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
this.setState({ popupVisible: nextProps.popupVisible });
|
||||
}
|
||||
if (nextProps.showSearch && this.props.options !== nextProps.options) {
|
||||
this.setState({ flattenOptions: this.flattenTree(nextProps.options, nextProps.changeOnSelect) });
|
||||
this.setState({
|
||||
flattenOptions: this.flattenTree(nextProps.options, nextProps.changeOnSelect, nextProps.filedNames),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleChange = (value: any, selectedOptions: any[]) => {
|
||||
handleChange = (value: any, selectedOptions: CascaderOptionType[]) => {
|
||||
this.setState({ inputValue: '' });
|
||||
if (selectedOptions[0].__IS_FILTERED_OPTION) {
|
||||
const unwrappedValue = value[0];
|
||||
@@ -181,7 +219,9 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
// Prevent `Trigger` behaviour.
|
||||
if (inputFocused || popupVisible) {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
if (e.nativeEvent.stopImmediatePropagation) {
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +236,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
this.setState({ inputValue });
|
||||
}
|
||||
|
||||
setValue = (value: string[], selectedOptions: any[] = []) => {
|
||||
setValue = (value: string[], selectedOptions: CascaderOptionType[] = []) => {
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ value });
|
||||
}
|
||||
@@ -207,13 +247,14 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
}
|
||||
|
||||
getLabel() {
|
||||
const { options, displayRender = defaultDisplayRender as Function } = this.props;
|
||||
const { options, displayRender = defaultDisplayRender as Function, filedNames } = this.props;
|
||||
const names = getFilledFieldNames(filedNames);
|
||||
const value = this.state.value;
|
||||
const unwrappedValue = Array.isArray(value[0]) ? value[0] : value;
|
||||
const selectedOptions: CascaderOptionType[] = arrayTreeFilter(options,
|
||||
(o: CascaderOptionType, level: number) => o.value === unwrappedValue[level],
|
||||
(o: CascaderOptionType, level: number) => o[names.value] === unwrappedValue[level],
|
||||
);
|
||||
const label = selectedOptions.map(o => o.label);
|
||||
const label = selectedOptions.map(o => o[names.label]);
|
||||
return displayRender(label, selectedOptions);
|
||||
}
|
||||
|
||||
@@ -228,43 +269,58 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
}
|
||||
}
|
||||
|
||||
flattenTree(options: CascaderOptionType[], changeOnSelect: boolean | undefined, ancestor: CascaderOptionType[] = []) {
|
||||
let flattenOptions: any = [];
|
||||
flattenTree(
|
||||
options: CascaderOptionType[],
|
||||
changeOnSelect: boolean | undefined,
|
||||
filedNames: FiledNamesType | undefined,
|
||||
ancestor: CascaderOptionType[] = [],
|
||||
) {
|
||||
const names: FilledFiledNamesType = getFilledFieldNames(filedNames);
|
||||
let flattenOptions = [] as CascaderOptionType[][];
|
||||
let childrenName = names.children;
|
||||
options.forEach((option) => {
|
||||
const path = ancestor.concat(option);
|
||||
if (changeOnSelect || !option.children || !option.children.length) {
|
||||
if (changeOnSelect || !option[childrenName] || !option[childrenName].length) {
|
||||
flattenOptions.push(path);
|
||||
}
|
||||
if (option.children) {
|
||||
flattenOptions = flattenOptions.concat(this.flattenTree(option.children, changeOnSelect, path));
|
||||
if (option[childrenName]) {
|
||||
flattenOptions = flattenOptions.concat(
|
||||
this.flattenTree(
|
||||
option[childrenName],
|
||||
changeOnSelect,
|
||||
filedNames,
|
||||
path,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
return flattenOptions;
|
||||
}
|
||||
|
||||
generateFilteredOptions(prefixCls: string | undefined) {
|
||||
const { showSearch, notFoundContent } = this.props;
|
||||
const { showSearch, notFoundContent, filedNames } = this.props;
|
||||
const names: FilledFiledNamesType = getFilledFieldNames(filedNames);
|
||||
const {
|
||||
filter = defaultFilterOption,
|
||||
render = defaultRenderFilteredOption,
|
||||
sort = defaultSortFilteredOption,
|
||||
} = showSearch as ShowSearchType;
|
||||
const { flattenOptions, inputValue } = this.state;
|
||||
const filtered = flattenOptions.filter((path) => filter(this.state.inputValue, path))
|
||||
.sort((a, b) => sort(a, b, inputValue));
|
||||
const { flattenOptions = [], inputValue } = this.state;
|
||||
const filtered = flattenOptions.filter((path) => filter(this.state.inputValue, path, names))
|
||||
.sort((a, b) => sort(a, b, inputValue, names));
|
||||
|
||||
if (filtered.length > 0) {
|
||||
return filtered.map((path: any) => {
|
||||
return filtered.map((path: CascaderOptionType[]) => {
|
||||
return {
|
||||
__IS_FILTERED_OPTION: true,
|
||||
path,
|
||||
label: render(inputValue, path, prefixCls),
|
||||
value: path.map((o: CascaderOptionType) => o.value),
|
||||
disabled: path.some((o: CascaderOptionType) => o.disabled),
|
||||
[names.label]: render(inputValue, path, prefixCls, names),
|
||||
[names.value]: path.map((o: CascaderOptionType) => o[names.value]),
|
||||
disabled: path.some((o: CascaderOptionType) => !!o.disabled),
|
||||
} as CascaderOptionType;
|
||||
});
|
||||
}
|
||||
return [{ label: notFoundContent, value: 'ANT_CASCADER_NOT_FOUND', disabled: true }];
|
||||
return [{ [names.label]: notFoundContent, [names.value]: 'ANT_CASCADER_NOT_FOUND', disabled: true }];
|
||||
}
|
||||
|
||||
focus() {
|
||||
@@ -283,7 +339,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
const { props, state } = this;
|
||||
const {
|
||||
prefixCls, inputPrefixCls, children, placeholder, size, disabled,
|
||||
className, style, allowClear, showSearch = false, ...otherProps,
|
||||
className, style, allowClear, showSearch = false, ...otherProps
|
||||
} = props;
|
||||
const value = state.value;
|
||||
|
||||
@@ -307,6 +363,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
[`${prefixCls}-picker-with-value`]: state.inputValue,
|
||||
[`${prefixCls}-picker-disabled`]: disabled,
|
||||
[`${prefixCls}-picker-${size}`]: !!size,
|
||||
[`${prefixCls}-picker-show-search`]: !!showSearch,
|
||||
});
|
||||
|
||||
// Fix bug of https://github.com/facebook/react/pull/5004
|
||||
@@ -328,6 +385,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
'renderFilteredOption',
|
||||
'sortFilteredOption',
|
||||
'notFoundContent',
|
||||
'filedNames',
|
||||
]);
|
||||
|
||||
let options = props.options;
|
||||
|
||||
@@ -43,6 +43,7 @@ subtitle: 级联选择
|
||||
| value | 指定选中项 | string\[] | - |
|
||||
| onChange | 选择完成后的回调 | `(value, selectedOptions) => void` | - |
|
||||
| onPopupVisibleChange | 显示/隐藏浮层的回调 | `(value) => void` | - |
|
||||
| filedNames | 自定义 options 中 label name children 的字段 | object | `{ label: 'label', value: 'value', children: 'children' }` |
|
||||
|
||||
`showSearch` 为对象时,其中的字段:
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
display: block;
|
||||
position: static;
|
||||
}
|
||||
|
||||
&-picker-show-search &-input.@{ant-prefix}-input {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&-picker {
|
||||
|
||||
@@ -35,7 +35,7 @@ export interface CheckboxChangeEvent {
|
||||
target: CheckboxChangeEventTarget;
|
||||
stopPropagation: () => void;
|
||||
preventDefault: () => void;
|
||||
nativeEvent: MouseEvent;
|
||||
nativeEvent: Event;
|
||||
}
|
||||
|
||||
export default class Checkbox extends React.Component<CheckboxProps, {}> {
|
||||
@@ -79,7 +79,7 @@ export default class Checkbox extends React.Component<CheckboxProps, {}> {
|
||||
style,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
...restProps,
|
||||
...restProps
|
||||
} = props;
|
||||
const { checkboxGroup } = context;
|
||||
let checkboxProps: CheckboxProps = { ...restProps };
|
||||
|
||||
@@ -4,7 +4,7 @@ import classNames from 'classnames';
|
||||
import shallowEqual from 'shallowequal';
|
||||
import Checkbox from './Checkbox';
|
||||
|
||||
export type CheckboxValueType = string | number;
|
||||
export type CheckboxValueType = string | number | boolean;
|
||||
|
||||
export interface CheckboxOptionType {
|
||||
label: string;
|
||||
@@ -121,7 +121,7 @@ export default class CheckboxGroup extends React.Component<CheckboxGroupProps, C
|
||||
children = this.getOptions().map(option => (
|
||||
<Checkbox
|
||||
prefixCls={prefixCls}
|
||||
key={option.value}
|
||||
key={option.value.toString()}
|
||||
disabled={'disabled' in option ? option.disabled : props.disabled}
|
||||
value={option.value}
|
||||
checked={state.value.indexOf(option.value) !== -1}
|
||||
|
||||
@@ -13,7 +13,9 @@ Checkbox.
|
||||
|
||||
## API
|
||||
|
||||
### Checkbox
|
||||
### Props
|
||||
|
||||
#### Checkbox
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
@@ -21,9 +23,10 @@ Checkbox.
|
||||
| checked | Specifies whether the checkbox is selected. | boolean | false |
|
||||
| defaultChecked | Specifies the initial state: whether or not the checkbox is selected. | boolean | false |
|
||||
| disabled | Disable checkbox | boolean | false |
|
||||
| indeterminate | indeterminate checked state of checkbox | boolean | false |
|
||||
| onChange | The callback function that is triggered when the state changes. | Function(e:Event) | - |
|
||||
|
||||
### Checkbox Group
|
||||
#### Checkbox Group
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
@@ -33,11 +36,11 @@ Checkbox.
|
||||
| value | Used for setting the currently selected value. | string\[] | \[] |
|
||||
| onChange | The callback function that is triggered when the state changes. | Function(checkedValue) | - |
|
||||
|
||||
## Methods
|
||||
### Methods
|
||||
|
||||
### Checkbox
|
||||
#### Checkbox
|
||||
|
||||
| Name | Description |
|
||||
| ---- | ----------- |
|
||||
| blur() | remove focus |
|
||||
| focus() | get focus |
|
||||
| blur() | remove focus |
|
||||
|
||||
@@ -14,30 +14,34 @@ title: Checkbox
|
||||
|
||||
## API
|
||||
|
||||
### Checkbox
|
||||
### 属性
|
||||
|
||||
#### Checkbox
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| autoFocus | 自动获取焦点 | boolean | false |
|
||||
| checked | 指定当前是否选中 | boolean | false |
|
||||
| defaultChecked | 初始是否选中 | boolean | false |
|
||||
| disabled | 失效状态 | boolean | false |
|
||||
| indeterminate | 设置 indeterminate 状态,只负责样式控制 | boolean | false |
|
||||
| onChange | 变化时回调函数 | Function(e:Event) | - |
|
||||
|
||||
### Checkbox Group
|
||||
#### Checkbox Group
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| defaultValue | 默认选中的选项 | string\[] | \[] |
|
||||
| disabled | 整组失效 | boolean | false |
|
||||
| options | 指定可选项 | string\[] | \[] |
|
||||
| value | 指定选中的选项 | string\[] | \[] |
|
||||
| onChange | 变化时回调函数 | Function(checkedValue) | - |
|
||||
|
||||
## 方法
|
||||
### 方法
|
||||
|
||||
### Checkbox
|
||||
#### Checkbox
|
||||
|
||||
| 名称 | 描述 |
|
||||
| --- | --- |
|
||||
| blur() | 移除焦点 |
|
||||
| focus() | 获取焦点 |
|
||||
| blur() | 移除焦点 |
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
exports[`renders ./components/collapse/demo/accordion.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-collapse"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -21,12 +22,12 @@ exports[`renders ./components/collapse/demo/accordion.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -36,12 +37,12 @@ exports[`renders ./components/collapse/demo/accordion.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -58,12 +59,12 @@ exports[`renders ./components/collapse/demo/basic.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-collapse-item ant-collapse-item-active"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -72,7 +73,6 @@ exports[`renders ./components/collapse/demo/basic.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-content ant-collapse-content-active"
|
||||
role="tabpanel"
|
||||
>
|
||||
<div
|
||||
class="ant-collapse-content-box"
|
||||
@@ -89,12 +89,12 @@ exports[`renders ./components/collapse/demo/basic.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -104,12 +104,12 @@ exports[`renders ./components/collapse/demo/basic.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item ant-collapse-item-disabled"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -126,12 +126,12 @@ exports[`renders ./components/collapse/demo/borderless.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-collapse-item ant-collapse-item-active"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -140,7 +140,6 @@ exports[`renders ./components/collapse/demo/borderless.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-content ant-collapse-content-active"
|
||||
role="tabpanel"
|
||||
>
|
||||
<div
|
||||
class="ant-collapse-content-box"
|
||||
@@ -155,12 +154,12 @@ exports[`renders ./components/collapse/demo/borderless.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -170,12 +169,12 @@ exports[`renders ./components/collapse/demo/borderless.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -192,13 +191,13 @@ exports[`renders ./components/collapse/demo/custom.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-collapse-item ant-collapse-item-active"
|
||||
role="tablist"
|
||||
style="background:#f7f7f7;border-radius:4px;margin-bottom:24px;border:0;overflow:hidden"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -207,7 +206,6 @@ exports[`renders ./components/collapse/demo/custom.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-content ant-collapse-content-active"
|
||||
role="tabpanel"
|
||||
>
|
||||
<div
|
||||
class="ant-collapse-content-box"
|
||||
@@ -224,13 +222,13 @@ exports[`renders ./components/collapse/demo/custom.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
style="background:#f7f7f7;border-radius:4px;margin-bottom:24px;border:0;overflow:hidden"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -240,13 +238,13 @@ exports[`renders ./components/collapse/demo/custom.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
style="background:#f7f7f7;border-radius:4px;margin-bottom:24px;border:0;overflow:hidden"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -263,12 +261,12 @@ exports[`renders ./components/collapse/demo/mix.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -278,12 +276,12 @@ exports[`renders ./components/collapse/demo/mix.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -293,12 +291,12 @@ exports[`renders ./components/collapse/demo/mix.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -315,12 +313,12 @@ exports[`renders ./components/collapse/demo/noarrow.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-collapse-item ant-collapse-item-active"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
class="arrow"
|
||||
@@ -329,7 +327,6 @@ exports[`renders ./components/collapse/demo/noarrow.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-content ant-collapse-content-active"
|
||||
role="tabpanel"
|
||||
>
|
||||
<div
|
||||
class="ant-collapse-content-box"
|
||||
@@ -346,12 +343,12 @@ exports[`renders ./components/collapse/demo/noarrow.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-collapse-item ant-collapse-no-arrow"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="ant-collapse-header"
|
||||
role="tab"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
This is panel header with no arrow icon
|
||||
</div>
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
|
||||
@collapse-prefix-cls: ~"@{ant-prefix}-collapse";
|
||||
|
||||
@collapse-header-bg: @background-color-light;
|
||||
@collapse-active-bg: @background-color-base;
|
||||
|
||||
.collapse-close() {
|
||||
transform: rotate(0);
|
||||
}
|
||||
@@ -32,7 +29,7 @@
|
||||
|
||||
> .@{collapse-prefix-cls}-header {
|
||||
line-height: 22px;
|
||||
padding: 12px 0 12px 40px;
|
||||
padding: @collapse-header-padding;
|
||||
color: @heading-color;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
@@ -53,6 +50,10 @@
|
||||
content: "\E61F";
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.@{collapse-prefix-cls}-no-arrow {
|
||||
@@ -69,13 +70,11 @@
|
||||
&-content {
|
||||
overflow: hidden;
|
||||
color: @text-color;
|
||||
padding: 0 @padding-md;
|
||||
background-color: @component-background;
|
||||
background-color: @collapse-content-bg;
|
||||
border-top: @border-width-base @border-style-base @border-color-base;
|
||||
|
||||
& > &-box {
|
||||
padding-top: @padding-md;
|
||||
padding-bottom: @padding-md;
|
||||
padding: @collapse-content-padding;
|
||||
}
|
||||
|
||||
&-inactive {
|
||||
|
||||
@@ -261,7 +261,7 @@ exports[`DatePicker prop locale should works 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="December 31, 1999"
|
||||
>
|
||||
@@ -689,7 +689,7 @@ exports[`DatePicker prop locale should works 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-calendar-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="January 31, 2000"
|
||||
>
|
||||
|
||||
@@ -221,7 +221,7 @@ exports[`RangePicker show month panel according to value 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="1999年12月31日"
|
||||
>
|
||||
@@ -649,7 +649,7 @@ exports[`RangePicker show month panel according to value 1`] = `
|
||||
role="row"
|
||||
>
|
||||
<td
|
||||
class="ant-calendar-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="2000年1月31日"
|
||||
>
|
||||
@@ -902,7 +902,7 @@ exports[`RangePicker show month panel according to value 1`] = `
|
||||
role="row"
|
||||
>
|
||||
<td
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="2000年1月31日"
|
||||
>
|
||||
@@ -1299,7 +1299,7 @@ exports[`RangePicker show month panel according to value 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-calendar-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="2000年2月29日"
|
||||
>
|
||||
@@ -1489,7 +1489,7 @@ exports[`RangePicker show month panel according to value 1`] = `
|
||||
class="ant-calendar-time-picker-btn"
|
||||
role="button"
|
||||
>
|
||||
Select time
|
||||
select time
|
||||
</a>
|
||||
<a
|
||||
class="ant-calendar-ok-btn"
|
||||
@@ -1726,7 +1726,7 @@ exports[`RangePicker switch to corresponding month panel when click presetted ra
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="1999年12月31日"
|
||||
>
|
||||
@@ -2154,7 +2154,7 @@ exports[`RangePicker switch to corresponding month panel when click presetted ra
|
||||
role="row"
|
||||
>
|
||||
<td
|
||||
class="ant-calendar-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="2000年1月31日"
|
||||
>
|
||||
@@ -2407,7 +2407,7 @@ exports[`RangePicker switch to corresponding month panel when click presetted ra
|
||||
role="row"
|
||||
>
|
||||
<td
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="2000年1月31日"
|
||||
>
|
||||
@@ -2804,7 +2804,7 @@ exports[`RangePicker switch to corresponding month panel when click presetted ra
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-calendar-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="2000年2月29日"
|
||||
>
|
||||
@@ -3001,7 +3001,7 @@ exports[`RangePicker switch to corresponding month panel when click presetted ra
|
||||
class="ant-calendar-time-picker-btn"
|
||||
role="button"
|
||||
>
|
||||
Select time
|
||||
select time
|
||||
</a>
|
||||
<a
|
||||
class="ant-calendar-ok-btn"
|
||||
|
||||
@@ -482,7 +482,7 @@ exports[`MonthPicker and WeekPicker render WeekPicker 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-month-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="1999年12月31日"
|
||||
>
|
||||
@@ -886,7 +886,7 @@ exports[`MonthPicker and WeekPicker render WeekPicker 1`] = `
|
||||
5
|
||||
</td>
|
||||
<td
|
||||
class="ant-calendar-cell"
|
||||
class="ant-calendar-cell ant-calendar-last-day-of-month"
|
||||
role="gridcell"
|
||||
title="2000年1月31日"
|
||||
>
|
||||
|
||||
@@ -19,13 +19,25 @@ There are four kinds of picker:
|
||||
- RangePicker
|
||||
- WeekPicker
|
||||
|
||||
### Localization
|
||||
|
||||
The default locale is en-US, if you need to use other languages, recommend to use internationalized components provided by us at the entrance. Look at: [LocaleProvider](http://ant.design/components/locale-provider/).
|
||||
|
||||
If there are special needs (only modifying single component language), Please use the property: local. Example: [default](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json).
|
||||
|
||||
```jsx
|
||||
import locale from 'antd/lib/date-picker/locale/zh_CN';
|
||||
|
||||
<DatePicker locale={locale} />
|
||||
```
|
||||
|
||||
**Note:** Part of locale of DatePicker, MonthPicker, RangePicker, WeekPicker is read from value. So, please set the locale of moment correctly.
|
||||
|
||||
```jsx
|
||||
// The default locale is en-US, if you want to use other locale, just set locale in entry file globaly.
|
||||
// import moment from 'moment';
|
||||
// import 'moment/locale/zh-cn';
|
||||
// moment.locale('zh-cn');
|
||||
import moment from 'moment';
|
||||
import 'moment/src/locale/zh-cn';
|
||||
// import 'moment/locale/zh-cn'; if you are using webpack 1
|
||||
|
||||
<DatePicker defaultValue={moment('2015-01-01', 'YYYY-MM-DD')} />
|
||||
```
|
||||
@@ -51,6 +63,8 @@ The following APIs are shared by DatePicker, MonthPicker, RangePicker, WeekPicke
|
||||
| size | determine the size of the input box, the height of `large` and `small`, are 40px and 24px respectively, while default size is 32px | string | - |
|
||||
| style | to customize the style of the input box | object | {} |
|
||||
| onOpenChange | a callback function, can be executed whether the popup calendar is popped up or closed | function(status) | - |
|
||||
| mode | picker panel mode | `time|date|month|year` | 'date' |
|
||||
| onPanelChange | callback when picker panel mode is changed | function(value, mode) | - |
|
||||
|
||||
### Common Methods
|
||||
|
||||
|
||||
@@ -20,13 +20,25 @@ subtitle: 日期选择框
|
||||
- RangePicker
|
||||
- WeekPicker
|
||||
|
||||
### 国际化配置
|
||||
|
||||
默认配置为 en-US,如果你需要设置其他语言,推荐在入口处使用我们提供的国际化组件,详见:[LocaleProvider国际化](http://ant.design/components/locale-provider-cn/)。
|
||||
|
||||
如有特殊需求(仅修改单一组件的语言),请使用 locale 参数,参考:[默认配置](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json)。
|
||||
|
||||
```jsx
|
||||
import locale from 'antd/lib/date-picker/locale/zh_CN';
|
||||
|
||||
<DatePicker locale={locale} />
|
||||
```
|
||||
|
||||
**注意:**DatePicker、MonthPicker、RangePicker、WeekPicker 部分 locale 是从 value 中读取,所以请先正确设置 moment 的 locale。
|
||||
|
||||
```jsx
|
||||
// 默认语言为 en-US,如果你需要设置其他语言,推荐在入口文件全局设置 locale
|
||||
// import moment from 'moment';
|
||||
// import 'moment/locale/zh-cn';
|
||||
// moment.locale('zh-cn');
|
||||
import moment from 'moment';
|
||||
import 'moment/src/locale/zh-cn';
|
||||
// import 'moment/locale/zh-cn'; if you are using webpack 1
|
||||
|
||||
<DatePicker defaultValue={moment('2015-01-01', 'YYYY-MM-DD')} />
|
||||
```
|
||||
@@ -74,6 +86,8 @@ subtitle: 日期选择框
|
||||
| value | 日期 | [moment](http://momentjs.com/) | 无 |
|
||||
| onChange | 时间发生变化的回调 | function(date: moment, dateString: string) | 无 |
|
||||
| onOk | 点击确定按钮的回调 | function() | - |
|
||||
| mode | 日期面板的状态 | `time|date|month|year` | 'date' |
|
||||
| onPanelChange | 日期面板变化时的回调 | function(value, mode) | - |
|
||||
|
||||
### MonthPicker
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ A divider line separates different content.
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| dashed | whether line is dashed | Boolean | false |
|
||||
| dashed | whether line is dashed | boolean | false |
|
||||
| type | direction type of divider | enum: `horizontal` `vertical` | `horizontal` |
|
||||
| orientation | position of title inside divider | enum: `left` `right` `center` | `center` |
|
||||
| className | className of container | string | - |
|
||||
| style | style object of container | object | - |
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function Divider({
|
||||
className,
|
||||
children,
|
||||
dashed,
|
||||
...restProps,
|
||||
...restProps
|
||||
}: DividerProps) {
|
||||
const orientationPrefix = (orientation.length > 0) ? '-' + orientation : orientation;
|
||||
const classString = classNames(
|
||||
|
||||
@@ -16,6 +16,8 @@ subtitle: 分割线
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| dashed | 是否虚线 | Boolean | false |
|
||||
| dashed | 是否虚线 | boolean | false |
|
||||
| type | 水平还是垂直类型 | enum: `horizontal` `vertical` | `horizontal` |
|
||||
| orientation | 分割线标题的位置 | enum: `left` `right` | `center` |
|
||||
| className | 分割线样式类 | string | - |
|
||||
| style | 分割线样式对象 | object | - |
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
margin: 24px 0;
|
||||
clear: both;
|
||||
}
|
||||
&-horizontal&-with-text {
|
||||
|
||||
&-horizontal&-with-text,
|
||||
&-horizontal&-with-text-left,
|
||||
&-horizontal&-with-text-right {
|
||||
display: table;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
@@ -33,7 +36,6 @@
|
||||
color: @heading-color;
|
||||
font-size: @font-size-lg;
|
||||
margin: 16px 0;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
@@ -45,82 +47,50 @@
|
||||
transform: translateY(50%);
|
||||
}
|
||||
}
|
||||
&-inner-text {
|
||||
display: inline-block;
|
||||
padding: 0 24px;
|
||||
}
|
||||
&-horizontal&-with-text-left {
|
||||
display: table;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
background: transparent;
|
||||
font-weight: 500;
|
||||
color: @heading-color;
|
||||
font-size: @font-size-base;
|
||||
margin: 16px 0;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: table-cell;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
width: 5%;
|
||||
border-top: 1px solid @border-color-split;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
display: table-cell;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
width: 95%;
|
||||
border-top: 1px solid @border-color-split;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
&-inner-text {
|
||||
&-horizontal&-with-text-left,
|
||||
&-horizontal&-with-text-right {
|
||||
font-size: @font-size-base;
|
||||
.@{divider-prefix-cls}-inner-text {
|
||||
display: inline-block;
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&-horizontal&-with-text-left {
|
||||
&:before {
|
||||
top: 50%;
|
||||
width: 5%;
|
||||
}
|
||||
&:after {
|
||||
top: 50%;
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
|
||||
&-horizontal&-with-text-right {
|
||||
display: table;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
background: transparent;
|
||||
font-weight: 500;
|
||||
color: @heading-color;
|
||||
font-size: @font-size-base;
|
||||
margin: 16px 0;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: table-cell;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
width: 95%;
|
||||
border-top: 1px solid @border-color-split;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
display: table-cell;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
width: 5%;
|
||||
border-top: 1px solid @border-color-split;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
&-inner-text {
|
||||
display: inline-block;
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&-inner-text {
|
||||
display: inline-block;
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
&-dashed {
|
||||
background: none;
|
||||
border-top: 1px dashed @border-color-split;
|
||||
}
|
||||
&-horizontal&-with-text&-dashed {
|
||||
&-horizontal&-with-text&-dashed,
|
||||
&-horizontal&-with-text-left&-dashed,
|
||||
&-horizontal&-with-text-right&-dashed {
|
||||
border-top: 0;
|
||||
&:before,
|
||||
&:after {
|
||||
|
||||
@@ -35,11 +35,11 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-dropdown-trigger ant-btn-default"
|
||||
class="ant-btn ant-dropdown-trigger ant-btn-default ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-down"
|
||||
class="anticon anticon-ellipsis"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
@@ -57,12 +57,12 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-dropdown-trigger ant-btn-default"
|
||||
class="ant-btn ant-dropdown-trigger ant-btn-default ant-btn-icon-only"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-down"
|
||||
class="anticon anticon-ellipsis"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import Button from '../button';
|
||||
import { ButtonGroupProps } from '../button/button-group';
|
||||
import Icon from '../icon';
|
||||
import Dropdown, { DropDownProps } from './dropdown';
|
||||
import classNames from 'classnames';
|
||||
const ButtonGroup = Button.Group;
|
||||
@@ -9,7 +8,7 @@ const ButtonGroup = Button.Group;
|
||||
export interface DropdownButtonProps extends ButtonGroupProps, DropDownProps {
|
||||
type?: 'primary' | 'ghost' | 'dashed';
|
||||
disabled?: boolean;
|
||||
onClick?: React.MouseEventHandler<any>;
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
children?: any;
|
||||
}
|
||||
|
||||
@@ -25,7 +24,7 @@ export default class DropdownButton extends React.Component<DropdownButtonProps,
|
||||
type, disabled, onClick, children,
|
||||
prefixCls, className, overlay, trigger, align,
|
||||
visible, onVisibleChange, placement, getPopupContainer,
|
||||
...restProps,
|
||||
...restProps
|
||||
} = this.props;
|
||||
|
||||
const dropdownProps = {
|
||||
@@ -36,9 +35,9 @@ export default class DropdownButton extends React.Component<DropdownButtonProps,
|
||||
onVisibleChange,
|
||||
placement,
|
||||
getPopupContainer,
|
||||
};
|
||||
} as DropDownProps;
|
||||
if ('visible' in this.props) {
|
||||
(dropdownProps as any).visible = visible;
|
||||
dropdownProps.visible = visible;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -54,9 +53,7 @@ export default class DropdownButton extends React.Component<DropdownButtonProps,
|
||||
{children}
|
||||
</Button>
|
||||
<Dropdown {...dropdownProps}>
|
||||
<Button type={type}>
|
||||
<Icon type="down" />
|
||||
</Button>
|
||||
<Button type={type} icon="ellipsis" />
|
||||
</Dropdown>
|
||||
</ButtonGroup>
|
||||
);
|
||||
|
||||
@@ -41,11 +41,13 @@ export default class Dropdown extends React.Component<DropDownProps, any> {
|
||||
|
||||
componentDidMount() {
|
||||
const { overlay } = this.props;
|
||||
const overlayProps = (overlay as any).props as any;
|
||||
warning(
|
||||
!overlayProps.mode || overlayProps.mode === 'vertical',
|
||||
`mode="${overlayProps.mode}" is not supported for Dropdown\'s Menu.`,
|
||||
);
|
||||
if (overlay) {
|
||||
const overlayProps = (overlay as React.ReactElement<any>).props;
|
||||
warning(
|
||||
!overlayProps.mode || overlayProps.mode === 'vertical',
|
||||
`mode="${overlayProps.mode}" is not supported for Dropdown\'s Menu.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -59,10 +61,12 @@ export default class Dropdown extends React.Component<DropDownProps, any> {
|
||||
disabled,
|
||||
});
|
||||
// menu cannot be selectable in dropdown defaultly
|
||||
const selectable = overlay.props.selectable || false;
|
||||
// menu should be focusable in dropdown defaultly
|
||||
const { selectable = false, focusable = true } = overlay.props;
|
||||
const fixedModeOverlay = React.cloneElement(overlay, {
|
||||
mode: 'vertical',
|
||||
selectable,
|
||||
focusable,
|
||||
});
|
||||
return (
|
||||
<RcDropdown
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
outline: none;
|
||||
position: relative;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
padding: 4px 0;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
background-color: @component-background;
|
||||
@@ -102,26 +102,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child,
|
||||
&:first-child > a {
|
||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||
}
|
||||
|
||||
&:last-child,
|
||||
&:last-child > a {
|
||||
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||
}
|
||||
|
||||
&:only-child,
|
||||
&:only-child > a {
|
||||
border-radius: @border-radius-base;
|
||||
}
|
||||
|
||||
&-divider {
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
background-color: @border-color-split;
|
||||
line-height: 0;
|
||||
margin: 4px 0;
|
||||
}
|
||||
.@{dropdown-prefix-cls}-menu-submenu-arrow {
|
||||
position: absolute;
|
||||
@@ -138,10 +124,6 @@
|
||||
|
||||
&-submenu-title {
|
||||
padding-right: 26px;
|
||||
&:first-child,
|
||||
&:last-child {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-submenu-vertical {
|
||||
@@ -163,13 +145,6 @@
|
||||
color: @disabled-color;
|
||||
}
|
||||
}
|
||||
&-submenu:first-child &-submenu-title {
|
||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||
}
|
||||
|
||||
&-submenu:last-child &-submenu-title {
|
||||
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||
}
|
||||
}
|
||||
|
||||
&.slide-down-enter.slide-down-enter-active&-placement-bottomLeft,
|
||||
@@ -208,6 +183,9 @@
|
||||
.@{iconfont-css-prefix}-down {
|
||||
.iconfont-size-under-12px(10px);
|
||||
}
|
||||
.@{iconfont-css-prefix}-ellipsis {
|
||||
text-shadow: 0 0 currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
.@{dropdown-prefix-cls}-button {
|
||||
|
||||
@@ -9,16 +9,26 @@ import FormItem from './FormItem';
|
||||
import { FIELD_META_PROP, FIELD_DATA_PROP } from './constants';
|
||||
import { Omit } from '../_util/type';
|
||||
|
||||
type FormCreateOptionMessagesCallback = (...args: any[]) => string;
|
||||
|
||||
interface FormCreateOptionMessages {
|
||||
[messageId: string]:
|
||||
| string
|
||||
| FormCreateOptionMessagesCallback
|
||||
| FormCreateOptionMessages;
|
||||
}
|
||||
|
||||
export interface FormCreateOption<T> {
|
||||
onFieldsChange?: (props: T, fields: Array<any>) => void;
|
||||
onValuesChange?: (props: T, values: any) => void;
|
||||
onFieldsChange?: (props: T, fields: Array<any>, allFields: any, add: string) => void;
|
||||
onValuesChange?: (props: T, changedValues: any, allValues: any) => void;
|
||||
mapPropsToFields?: (props: T) => void;
|
||||
validateMessages?: FormCreateOptionMessages;
|
||||
withRef?: boolean;
|
||||
}
|
||||
|
||||
export type FormLayout = 'horizontal' | 'inline' | 'vertical';
|
||||
|
||||
export interface FormProps {
|
||||
export interface FormProps extends React.FormHTMLAttributes<HTMLFormElement> {
|
||||
layout?: FormLayout;
|
||||
form?: WrappedFormUtils;
|
||||
onSubmit?: React.FormEventHandler<any>;
|
||||
@@ -115,10 +125,14 @@ export interface FormComponentProps {
|
||||
form: WrappedFormUtils;
|
||||
}
|
||||
|
||||
export interface RcBaseFormProps {
|
||||
wrappedComponentRef?: any;
|
||||
}
|
||||
|
||||
export interface ComponentDecorator {
|
||||
<P extends FormComponentProps>(
|
||||
component: React.ComponentClass<P> | React.SFC<P>,
|
||||
): React.ComponentClass<Omit<P, keyof FormComponentProps>>;
|
||||
): React.ComponentClass<RcBaseFormProps & Omit<P, keyof FormComponentProps>>;
|
||||
}
|
||||
|
||||
export default class Form extends React.Component<FormProps, any> {
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import intersperse from 'intersperse';
|
||||
import Animate from 'rc-animate';
|
||||
import Row from '../grid/row';
|
||||
import Col, { ColProps } from '../grid/col';
|
||||
@@ -55,7 +56,7 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
|
||||
context: FormItemContext;
|
||||
|
||||
state = { helpShow: false };
|
||||
helpShow = false;
|
||||
|
||||
componentDidMount() {
|
||||
warning(
|
||||
@@ -65,15 +66,20 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
);
|
||||
}
|
||||
|
||||
getHelpMsg() {
|
||||
const props = this.props;
|
||||
const onlyControl = this.getOnlyControl();
|
||||
if (props.help === undefined && onlyControl) {
|
||||
getHelpMessage() {
|
||||
const { help } = this.props;
|
||||
if (help === undefined && this.getOnlyControl()) {
|
||||
const errors = this.getField().errors;
|
||||
return errors ? errors.map((e: any) => e.message).join(', ') : '';
|
||||
if (errors) {
|
||||
return intersperse(errors.map((e: any, index: number) => (
|
||||
React.isValidElement(e.message)
|
||||
? React.cloneElement(e.message, { key: index })
|
||||
: e.message
|
||||
)), ' ');
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
return props.help;
|
||||
return help;
|
||||
}
|
||||
|
||||
getControls(children: React.ReactNode, recursively: boolean) {
|
||||
@@ -124,17 +130,23 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
}
|
||||
|
||||
onHelpAnimEnd = (_key: string, helpShow: boolean) => {
|
||||
this.setState({ helpShow });
|
||||
this.helpShow = helpShow;
|
||||
if (!helpShow) {
|
||||
this.setState({});
|
||||
}
|
||||
}
|
||||
|
||||
renderHelp() {
|
||||
const prefixCls = this.props.prefixCls;
|
||||
const help = this.getHelpMsg();
|
||||
const help = this.getHelpMessage();
|
||||
const children = help ? (
|
||||
<div className={`${prefixCls}-explain`} key="help">
|
||||
{help}
|
||||
</div>
|
||||
) : null;
|
||||
if (children) {
|
||||
this.helpShow = !!children;
|
||||
}
|
||||
return (
|
||||
<Animate
|
||||
transitionName="show-help"
|
||||
@@ -306,11 +318,10 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
const style = props.style;
|
||||
const itemClassName = {
|
||||
[`${prefixCls}-item`]: true,
|
||||
[`${prefixCls}-item-with-help`]: !!this.getHelpMsg() || this.state.helpShow,
|
||||
[`${prefixCls}-item-with-help`]: this.helpShow,
|
||||
[`${prefixCls}-item-no-colon`]: !props.colon,
|
||||
[`${props.className}`]: !!props.className,
|
||||
};
|
||||
|
||||
return (
|
||||
<Row className={classNames(itemClassName)} style={style}>
|
||||
{children}
|
||||
|
||||
@@ -543,7 +543,7 @@ exports[`renders ./components/form/demo/coordinated.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
Select a option and change input text above
|
||||
</div>
|
||||
@@ -551,7 +551,7 @@ exports[`renders ./components/form/demo/coordinated.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -649,7 +649,7 @@ exports[`renders ./components/form/demo/customized-form-controls.md correctly 1`
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -1637,7 +1637,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -1698,7 +1698,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
website
|
||||
</div>
|
||||
@@ -1726,7 +1726,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -2263,7 +2263,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
Please select a country
|
||||
</div>
|
||||
@@ -2271,7 +2271,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -2321,7 +2321,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
Please select favourite colors
|
||||
</div>
|
||||
@@ -2417,6 +2417,8 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
data-__field="[object Object]"
|
||||
data-__meta="[object Object]"
|
||||
id="input-number"
|
||||
max="10"
|
||||
min="1"
|
||||
@@ -3340,7 +3342,7 @@ exports[`renders ./components/form/demo/validate-static.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
|
||||
100
components/form/__tests__/__snapshots__/message.test.js.snap
Normal file
100
components/form/__tests__/__snapshots__/message.test.js.snap
Normal file
@@ -0,0 +1,100 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Form should display custom message 1`] = `
|
||||
<form
|
||||
class="ant-form ant-form-horizontal"
|
||||
>
|
||||
<div
|
||||
class="ant-row ant-form-item ant-form-item-with-help"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-label"
|
||||
>
|
||||
<label
|
||||
class=""
|
||||
for="account"
|
||||
title="Account"
|
||||
>
|
||||
Account
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="ant-form-item-control-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control has-error"
|
||||
>
|
||||
<span
|
||||
class="ant-form-item-children"
|
||||
>
|
||||
<input
|
||||
data-__field="[object Object]"
|
||||
data-__meta="[object Object]"
|
||||
id="account"
|
||||
value="antd"
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain show-help-enter"
|
||||
>
|
||||
<span>
|
||||
Account does not exist,
|
||||
<a
|
||||
href="https://www.alipay.com/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Forgot account?
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
`;
|
||||
|
||||
exports[`Form should display two message 1`] = `
|
||||
<form
|
||||
class="ant-form ant-form-horizontal"
|
||||
>
|
||||
<div
|
||||
class="ant-row ant-form-item ant-form-item-with-help"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-label"
|
||||
>
|
||||
<label
|
||||
class=""
|
||||
for="account"
|
||||
title="Account"
|
||||
>
|
||||
Account
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="ant-form-item-control-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control has-error"
|
||||
>
|
||||
<span
|
||||
class="ant-form-item-children"
|
||||
>
|
||||
<input
|
||||
data-__field="[object Object]"
|
||||
data-__meta="[object Object]"
|
||||
id="account"
|
||||
value="+=-/"
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain show-help-enter"
|
||||
>
|
||||
Error message 1 Error message 2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
`;
|
||||
56
components/form/__tests__/message.test.js
Normal file
56
components/form/__tests__/message.test.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Form from '..';
|
||||
|
||||
describe('Form', () => {
|
||||
it('should display two message', () => {
|
||||
const rules = [{
|
||||
pattern: /^\w+$/,
|
||||
message: 'Error message 1',
|
||||
}, {
|
||||
pattern: /^\w+$/,
|
||||
message: 'Error message 2',
|
||||
}];
|
||||
let myForm;
|
||||
const Form1 = Form.create()(({ form }) => {
|
||||
myForm = form;
|
||||
return (
|
||||
<Form>
|
||||
<Form.Item label="Account">
|
||||
{form.getFieldDecorator('account', { initialValue: '+=-/', rules })(<input />)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
});
|
||||
|
||||
const wrapper = mount(<Form1 />);
|
||||
myForm.validateFields();
|
||||
|
||||
wrapper.update();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should display custom message', () => {
|
||||
const rules = [{
|
||||
pattern: /^$/,
|
||||
message: (<span>Account does not exist, <a rel="noopener noreferrer" href="https://www.alipay.com/" target="_blank">Forgot account?</a></span>),
|
||||
}];
|
||||
let myForm;
|
||||
const Form1 = Form.create()(({ form }) => {
|
||||
myForm = form;
|
||||
return (
|
||||
<Form>
|
||||
<Form.Item label="Account">
|
||||
{form.getFieldDecorator('account', { initialValue: 'antd', rules })(<input />)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
});
|
||||
|
||||
const wrapper = mount(<Form1 />);
|
||||
myForm.validateFields();
|
||||
|
||||
wrapper.update();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -56,7 +56,7 @@ The following `options` are available:
|
||||
| mapPropsToFields | Convert props to field value(e.g. reading the values from Redux store). And you must mark returned fields with [`Form.createFormField`](#Form.createFormField) | (props) => Object{ fieldName: FormField { value } } |
|
||||
| validateMessages | Default validate message. And its format is similar with [newMessages](https://github.com/yiminghe/async-validator/blob/master/src/messages.js)'s returned value | Object { [nested.path]: String } |
|
||||
| onFieldsChange | Specify a function that will be called when the value a `Form.Item` gets changed. Usage example: saving the field's value to Redux store. | Function(props, fields) |
|
||||
| onValuesChange | A handler while value of any field is changed | (props, values) => void |
|
||||
| onValuesChange | A handler while value of any field is changed | (props, changedValues, allValues) => void |
|
||||
|
||||
If the form has been decorated by `Form.create` then it has `this.props.form` property. `this.props.form` provides some APIs as follows:
|
||||
|
||||
@@ -147,7 +147,7 @@ Note:
|
||||
| enum | validate a value from a list of possible values | string | - |
|
||||
| len | validate an exact length of a field | number | - |
|
||||
| max | validate a max length of a field | number | - |
|
||||
| message | validation error message | string | - |
|
||||
| message | validation error message | string\|ReactNode | - |
|
||||
| min | validate a min length of a field | number | - |
|
||||
| pattern | validate from a regular expression | RegExp | - |
|
||||
| required | indicates whether field is required | boolean | `false` |
|
||||
|
||||
@@ -58,7 +58,7 @@ CustomizedForm = Form.create({})(CustomizedForm);
|
||||
| mapPropsToFields | 把父组件的属性映射到表单项上(如:把 Redux store 中的值读出),需要对返回值中的表单域数据用 [`Form.createFormField`](#Form.createFormField) 标记 | (props) => Object{ fieldName: FormField { value } } |
|
||||
| validateMessages | 默认校验信息,可用于把默认错误信息改为中文等,格式与 [newMessages](https://github.com/yiminghe/async-validator/blob/master/src/messages.js) 返回值一致 | Object { [nested.path]: String } |
|
||||
| onFieldsChange | 当 `Form.Item` 子节点的值发生改变时触发,可以把对应的值转存到 Redux store | Function(props, fields) |
|
||||
| onValuesChange | 任一表单域的值发生改变时的回调 | (props, values) => void |
|
||||
| onValuesChange | 任一表单域的值发生改变时的回调 | (props, changedValues, allValues) => void |
|
||||
|
||||
经过 `Form.create` 包装的组件将会自带 `this.props.form` 属性,`this.props.form` 提供的 API 如下:
|
||||
|
||||
@@ -148,7 +148,7 @@ CustomizedForm = Form.create({})(CustomizedForm);
|
||||
| enum | 枚举类型 | string | - |
|
||||
| len | 字段长度 | number | - |
|
||||
| max | 最大长度 | number | - |
|
||||
| message | 校验文案 | string | - |
|
||||
| message | 校验文案 | string\|ReactNode | - |
|
||||
| min | 最小长度 | number | - |
|
||||
| pattern | 正则表达式校验 | RegExp | - |
|
||||
| required | 是否必选 | boolean | `false` |
|
||||
|
||||
@@ -132,8 +132,9 @@ input[type="checkbox"] {
|
||||
.@{form-prefix-cls}-extra {
|
||||
color: @text-color-secondary;
|
||||
line-height: @line-height-base;
|
||||
transition: color .15s @ease-out;
|
||||
transition: color .3s @ease-out; // sync input color transition
|
||||
margin-top: @form-help-margin-top;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-extra {
|
||||
@@ -251,7 +252,9 @@ form {
|
||||
}
|
||||
|
||||
// fix input with addon position. https://github.com/ant-design/ant-design/issues/8243
|
||||
:not(.@{ant-prefix}-input-group-wrapper) > .@{ant-prefix}-input-group,
|
||||
.@{ant-prefix}-input-group-wrapper {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
@@ -574,7 +577,7 @@ form {
|
||||
}
|
||||
}
|
||||
|
||||
.show-help-motion(show-help, antShowHelp, 0.15s);
|
||||
.show-help-motion(show-help, antShowHelp, 0.3s);
|
||||
|
||||
@keyframes antShowHelpIn {
|
||||
0% {
|
||||
|
||||
@@ -22,17 +22,10 @@ import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
|
||||
export type BreakpointMap = {
|
||||
xs?: string;
|
||||
sm?: string;
|
||||
md?: string;
|
||||
lg?: string;
|
||||
xl?: string;
|
||||
xxl?: string
|
||||
};
|
||||
export type BreakpointMap = Partial<Record<Breakpoint, string>>;
|
||||
|
||||
export interface RowProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
gutter?: number | BreakpointMap;
|
||||
gutter?: number | Partial<Record<Breakpoint, number>>;
|
||||
type?: 'flex';
|
||||
align?: 'top' | 'middle' | 'bottom';
|
||||
justify?: 'start' | 'end' | 'center' | 'space-around' | 'space-between';
|
||||
@@ -122,7 +115,7 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
render() {
|
||||
const {
|
||||
type, justify, align, className, style, children,
|
||||
prefixCls = 'ant-row', ...others,
|
||||
prefixCls = 'ant-row', ...others
|
||||
} = this.props;
|
||||
const gutter = this.getGutter();
|
||||
const classes = classNames({
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// this file is not used if use https://github.com/ant-design/babel-plugin-import
|
||||
const ENV = process.env.NODE_ENV;
|
||||
if (ENV !== 'production' &&
|
||||
ENV !== 'test' &&
|
||||
typeof console !== 'undefined' &&
|
||||
console.warn &&
|
||||
typeof window !== 'undefined') {
|
||||
|
||||
@@ -2,7 +2,12 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import RcInputNumber from 'rc-input-number';
|
||||
|
||||
export interface InputNumberProps {
|
||||
import { Omit } from '../_util/type';
|
||||
|
||||
// omitting this attrs because they conflicts with the ones defined in InputNumberProps
|
||||
export type OmitAttrs = 'defaultValue' | 'onChange' | 'size';
|
||||
|
||||
export interface InputNumberProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, OmitAttrs> {
|
||||
prefixCls?: string;
|
||||
min?: number;
|
||||
max?: number;
|
||||
@@ -10,7 +15,6 @@ export interface InputNumberProps {
|
||||
step?: number | string;
|
||||
defaultValue?: number;
|
||||
tabIndex?: number;
|
||||
onKeyDown?: React.FormEventHandler<any>;
|
||||
onChange?: (value: number | string | undefined) => void;
|
||||
disabled?: boolean;
|
||||
size?: 'large' | 'small' | 'default';
|
||||
|
||||
@@ -60,7 +60,6 @@
|
||||
.disabled();
|
||||
.@{input-number-prefix-cls}-input {
|
||||
cursor: not-allowed;
|
||||
background-color: @disabled-bg;
|
||||
}
|
||||
.@{input-number-prefix-cls}-handler-wrap {
|
||||
display: none;
|
||||
@@ -74,17 +73,12 @@
|
||||
-moz-appearance: textfield;
|
||||
height: @input-height-base - 2px;
|
||||
transition: all 0.3s linear;
|
||||
color: @input-color;
|
||||
background-color: @input-bg;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
border-radius: @border-radius-base;
|
||||
padding: 0 @control-padding-horizontal - 1px;
|
||||
display: block;
|
||||
.placeholder();
|
||||
|
||||
&[disabled] {
|
||||
.disabled();
|
||||
}
|
||||
}
|
||||
|
||||
&-lg {
|
||||
@@ -109,7 +103,7 @@
|
||||
border-left: @border-width-base @border-style-base @border-color-base;
|
||||
width: 22px;
|
||||
height: 100%;
|
||||
background: @component-background;
|
||||
background: transparent;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
@@ -5,46 +5,23 @@ import omit from 'omit.js';
|
||||
import Group from './Group';
|
||||
import Search from './Search';
|
||||
import TextArea from './TextArea';
|
||||
import { Omit } from '../_util/type';
|
||||
|
||||
function fixControlledValue(value: undefined | null | string) {
|
||||
function fixControlledValue<T>(value: T) {
|
||||
if (typeof value === 'undefined' || value === null) {
|
||||
return '';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export interface AbstractInputProps {
|
||||
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
defaultValue?: any;
|
||||
value?: any;
|
||||
tabIndex?: number;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export interface InputProps extends AbstractInputProps {
|
||||
placeholder?: string;
|
||||
type?: string;
|
||||
id?: number | string;
|
||||
name?: string;
|
||||
size?: 'large' | 'default' | 'small';
|
||||
maxLength?: number | string;
|
||||
disabled?: boolean;
|
||||
readOnly?: boolean;
|
||||
onPressEnter?: React.KeyboardEventHandler<HTMLInputElement>;
|
||||
addonBefore?: React.ReactNode;
|
||||
addonAfter?: React.ReactNode;
|
||||
onPressEnter?: React.FormEventHandler<HTMLInputElement>;
|
||||
onKeyDown?: React.FormEventHandler<HTMLInputElement>;
|
||||
onKeyUp?: React.FormEventHandler<HTMLInputElement>;
|
||||
onChange?: React.ChangeEventHandler<HTMLInputElement>;
|
||||
onClick?: React.FormEventHandler<HTMLInputElement>;
|
||||
onFocus?: React.FormEventHandler<HTMLInputElement>;
|
||||
onBlur?: React.FormEventHandler<HTMLInputElement>;
|
||||
autoComplete?: string;
|
||||
prefix?: React.ReactNode;
|
||||
suffix?: React.ReactNode;
|
||||
spellCheck?: boolean;
|
||||
autoFocus?: boolean;
|
||||
}
|
||||
|
||||
export default class Input extends React.Component<InputProps, any> {
|
||||
|
||||
@@ -40,31 +40,32 @@ export default class Search extends React.Component<SearchProps, any> {
|
||||
}
|
||||
|
||||
getButtonOrIcon() {
|
||||
const { enterButton, prefixCls, size } = this.props;
|
||||
if (!enterButton) {
|
||||
return <Icon className={`${prefixCls}-icon`} type="search" key="searchIcon" />;
|
||||
}
|
||||
const { enterButton, prefixCls, size, disabled } = this.props;
|
||||
const enterButtonAsElement = enterButton as React.ReactElement<any>;
|
||||
if (enterButtonAsElement.type === Button || enterButtonAsElement.type === 'button') {
|
||||
return React.cloneElement(enterButtonAsElement, enterButtonAsElement.type === Button ? {
|
||||
let node;
|
||||
if (!enterButton) {
|
||||
node = <Icon className={`${prefixCls}-icon`} type="search" key="searchIcon" />;
|
||||
} else if (enterButtonAsElement.type === Button || enterButtonAsElement.type === 'button') {
|
||||
node = React.cloneElement(enterButtonAsElement, enterButtonAsElement.type === Button ? {
|
||||
className: `${prefixCls}-button`,
|
||||
size,
|
||||
onClick: this.onSearch,
|
||||
} : {
|
||||
onClick: this.onSearch,
|
||||
});
|
||||
} : {});
|
||||
} else {
|
||||
node = (
|
||||
<Button
|
||||
className={`${prefixCls}-button`}
|
||||
type="primary"
|
||||
size={size}
|
||||
disabled={disabled}
|
||||
key="enterButton"
|
||||
>
|
||||
{enterButton === true ? <Icon type="search" /> : enterButton}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Button
|
||||
className={`${prefixCls}-button`}
|
||||
type="primary"
|
||||
size={size}
|
||||
onClick={this.onSearch}
|
||||
key="enterButton"
|
||||
>
|
||||
{enterButton === true ? <Icon type="search" /> : enterButton}
|
||||
</Button>
|
||||
);
|
||||
return React.cloneElement(node, {
|
||||
onClick: this.onSearch,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import omit from 'omit.js';
|
||||
import classNames from 'classnames';
|
||||
import { AbstractInputProps } from './Input';
|
||||
import calculateNodeHeight from './calculateNodeHeight';
|
||||
|
||||
function onNextFrame(cb: () => void) {
|
||||
@@ -24,9 +23,10 @@ export interface AutoSizeType {
|
||||
maxRows?: number;
|
||||
}
|
||||
|
||||
export interface TextAreaProps extends AbstractInputProps {
|
||||
export interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
||||
prefixCls?: string;
|
||||
autosize?: boolean | AutoSizeType;
|
||||
onPressEnter?: React.FormEventHandler<any>;
|
||||
onPressEnter?: React.KeyboardEventHandler<HTMLTextAreaElement>;
|
||||
}
|
||||
|
||||
export interface TextAreaState {
|
||||
|
||||
@@ -20,4 +20,71 @@ describe('Input.Search', () => {
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should disable enter button when disabled prop is true', () => {
|
||||
const wrapper = mount(
|
||||
<Search placeholder="input search text" enterButton disabled />
|
||||
);
|
||||
expect(wrapper.find('.ant-btn-primary[disabled]')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should trigger onSearch when click search icon', () => {
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Search defaultValue="search text" onSearch={onSearch} />
|
||||
);
|
||||
wrapper.find('Icon').simulate('click');
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toBeCalledWith('search text');
|
||||
});
|
||||
|
||||
it('should trigger onSearch when click search button', () => {
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Search defaultValue="search text" enterButton onSearch={onSearch} />
|
||||
);
|
||||
wrapper.find('Button').simulate('click');
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toBeCalledWith('search text');
|
||||
});
|
||||
|
||||
it('should trigger onSearch when click search button with text', () => {
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Search defaultValue="search text" enterButton="button text" onSearch={onSearch} />
|
||||
);
|
||||
wrapper.find('Button').simulate('click');
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toBeCalledWith('search text');
|
||||
});
|
||||
|
||||
it('should trigger onSearch when click search button with customize button', () => {
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Search defaultValue="search text" enterButton={<Button>antd button</Button>} onSearch={onSearch} />
|
||||
);
|
||||
wrapper.find('Button').simulate('click');
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toBeCalledWith('search text');
|
||||
});
|
||||
|
||||
it('should trigger onSearch when click search button of native', () => {
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Search defaultValue="search text" enterButton={<button>antd button</button>} onSearch={onSearch} />
|
||||
);
|
||||
wrapper.find('button').simulate('click');
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toBeCalledWith('search text');
|
||||
});
|
||||
|
||||
it('should trigger onSearch when press enter', () => {
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Search defaultValue="search text" onSearch={onSearch} />
|
||||
);
|
||||
wrapper.find('input').simulate('keydown', { key: 'Enter', keyCode: 13 });
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toBeCalledWith('search text');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -68,7 +68,7 @@ exports[`renders ./components/input/demo/addon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -110,7 +110,7 @@ exports[`renders ./components/input/demo/addon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -242,7 +242,7 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -285,7 +285,7 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -399,7 +399,7 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -431,7 +431,7 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -468,7 +468,7 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -524,7 +524,7 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -548,7 +548,7 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
Email
|
||||
</div>
|
||||
@@ -576,7 +576,7 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
@@ -614,7 +614,7 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="unselectable"
|
||||
unselectable="on"
|
||||
>
|
||||
<b />
|
||||
</span>
|
||||
|
||||
@@ -34,6 +34,7 @@ exports[`Input.Search should support suffix 1`] = `
|
||||
"suffix",
|
||||
<Icon
|
||||
className="ant-input-search-icon"
|
||||
onClick={[Function]}
|
||||
type="search"
|
||||
/>,
|
||||
]
|
||||
@@ -57,10 +58,12 @@ exports[`Input.Search should support suffix 1`] = `
|
||||
<Icon
|
||||
className="ant-input-search-icon"
|
||||
key="searchIcon"
|
||||
onClick={[Function]}
|
||||
type="search"
|
||||
>
|
||||
<i
|
||||
className="anticon anticon-search ant-input-search-icon"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
</Icon>
|
||||
</span>
|
||||
|
||||
@@ -31,7 +31,12 @@ ReactDOM.render(
|
||||
enterButton
|
||||
/>
|
||||
<br /><br />
|
||||
<Search placeholder="input search text" enterButton="Search" size="large" />
|
||||
<Search
|
||||
placeholder="input search text"
|
||||
enterButton="Search"
|
||||
size="large"
|
||||
onSearch={value => console.log(value)}
|
||||
/>
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
||||
|
||||
@@ -9,13 +9,11 @@ title:
|
||||
|
||||
我们为 `<Input />` 输入框定义了三种尺寸(大、默认、小),高度分别为 `40px`、`32px` 和 `24px`。
|
||||
|
||||
注意: 在表单里面,我们只使用大尺寸的输入框。
|
||||
|
||||
## en-US
|
||||
|
||||
There are three sizes of an Input box: `large` (40px)、`default` (32px) and `small` (24px).
|
||||
|
||||
Note: Inside of forms, only the large size is used.
|
||||
|
||||
````jsx
|
||||
import { Input } from 'antd';
|
||||
|
||||
@@ -21,11 +21,13 @@
|
||||
border-color: ~`colorPalette("@{color}", 5)`;
|
||||
outline: 0;
|
||||
box-shadow: 0 0 @outline-blur-size @outline-width fade(@color, 20%);
|
||||
border-right-width: 1px !important;
|
||||
}
|
||||
|
||||
// == when hoverd
|
||||
.hover(@color: @input-hover-border-color) {
|
||||
border-color: ~`colorPalette("@{color}", 5)`;
|
||||
border-right-width: 1px !important;
|
||||
}
|
||||
|
||||
.disabled() {
|
||||
@@ -135,6 +137,11 @@
|
||||
margin-bottom: 0;
|
||||
&:focus {
|
||||
z-index: 1; // Fix https://gw.alipayobjects.com/zos/rmsportal/DHNpoqfMXSfrSnlZvhsJ.png
|
||||
border-right-width: 1px;
|
||||
}
|
||||
&:hover {
|
||||
z-index: 1;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +274,6 @@
|
||||
// Undo float for .ant-input-group .ant-input
|
||||
.@{inputClass} {
|
||||
float: none;
|
||||
z-index: auto;
|
||||
}
|
||||
|
||||
// reset border for Select, DatePicker, AutoComplete, Cascader, Mention, TimePicker
|
||||
@@ -311,20 +317,19 @@
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
|
||||
.@{inputClass} {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&:hover .@{inputClass}:not(.@{inputClass}-disabled) {
|
||||
.hover();
|
||||
}
|
||||
|
||||
.@{inputClass} {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.@{inputClass}-prefix,
|
||||
.@{inputClass}-suffix {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 2;
|
||||
line-height: 0;
|
||||
color: @input-color;
|
||||
:not(.anticon) {
|
||||
|
||||
@@ -7,8 +7,12 @@
|
||||
|
||||
.@{search-prefix} {
|
||||
&-icon {
|
||||
pointer-events: none;
|
||||
color: @text-color-secondary;
|
||||
cursor: pointer;
|
||||
transition: all .3s;
|
||||
&:hover {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(&-small) > .@{ant-prefix}-input-suffix {
|
||||
|
||||
@@ -31,6 +31,8 @@ const dimensionMap = {
|
||||
|
||||
export type CollapseType = 'clickTrigger' | 'responsive';
|
||||
|
||||
export type SiderTheme = 'light' | 'dark';
|
||||
|
||||
export interface SiderProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
prefixCls?: string;
|
||||
collapsible?: boolean;
|
||||
@@ -42,6 +44,7 @@ export interface SiderProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
width?: number | string;
|
||||
collapsedWidth?: number | string;
|
||||
breakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
|
||||
theme?: SiderTheme;
|
||||
}
|
||||
|
||||
export interface SiderState {
|
||||
@@ -73,6 +76,7 @@ export default class Sider extends React.Component<SiderProps, SiderState> {
|
||||
width: 200,
|
||||
collapsedWidth: 80,
|
||||
style: {},
|
||||
theme: 'dark' as SiderTheme,
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
@@ -174,15 +178,17 @@ export default class Sider extends React.Component<SiderProps, SiderState> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, className,
|
||||
const { prefixCls, className, theme,
|
||||
collapsible, reverseArrow, trigger, style, width, collapsedWidth,
|
||||
...others,
|
||||
...others
|
||||
} = this.props;
|
||||
const divProps = omit(others, ['collapsed',
|
||||
'defaultCollapsed', 'onCollapse', 'breakpoint']);
|
||||
const siderWidth = this.state.collapsed ? collapsedWidth : width;
|
||||
const rawWidth = this.state.collapsed ? collapsedWidth : width;
|
||||
// use "px" as fallback unit for width
|
||||
const siderWidth = typeof rawWidth === 'number' ? `${rawWidth}px` : String(rawWidth || 0);
|
||||
// special trigger when collapsedWidth == 0
|
||||
const zeroWidthTrigger = collapsedWidth === 0 || collapsedWidth === '0' || collapsedWidth === '0px' ? (
|
||||
const zeroWidthTrigger = parseFloat(String(collapsedWidth || 0)) === 0 ? (
|
||||
<span onClick={this.toggle} className={`${prefixCls}-zero-width-trigger`}>
|
||||
<Icon type="bars" />
|
||||
</span>
|
||||
@@ -201,21 +207,18 @@ export default class Sider extends React.Component<SiderProps, SiderState> {
|
||||
</div>
|
||||
) : null
|
||||
);
|
||||
// For collapsedWidth="40px"
|
||||
// https://github.com/ant-design/ant-design/issues/10140
|
||||
const siderWidthNumber = (siderWidth || 0).toString().replace(/px$/, '');
|
||||
const divStyle = {
|
||||
...style,
|
||||
flex: `0 0 ${siderWidthNumber}px`,
|
||||
maxWidth: `${siderWidthNumber}px`, // Fix width transition bug in IE11
|
||||
minWidth: `${siderWidthNumber}px`, // https://github.com/ant-design/ant-design/issues/6349
|
||||
width: `${siderWidthNumber}px`,
|
||||
flex: `0 0 ${siderWidth}`,
|
||||
maxWidth: siderWidth, // Fix width transition bug in IE11
|
||||
minWidth: siderWidth, // https://github.com/ant-design/ant-design/issues/6349
|
||||
width: siderWidth,
|
||||
};
|
||||
const siderCls = classNames(className, prefixCls, {
|
||||
const siderCls = classNames(className, prefixCls, `${prefixCls}-${theme}`, {
|
||||
[`${prefixCls}-collapsed`]: !!this.state.collapsed,
|
||||
[`${prefixCls}-has-trigger`]: collapsible && trigger !== null && !zeroWidthTrigger,
|
||||
[`${prefixCls}-below`]: !!this.state.below,
|
||||
[`${prefixCls}-zero-width`]: siderWidth === 0 || siderWidth === '0' || siderWidth === '0px',
|
||||
[`${prefixCls}-zero-width`]: parseFloat(siderWidth) === 0,
|
||||
});
|
||||
return (
|
||||
<div className={siderCls} {...divProps} style={divStyle}>
|
||||
|
||||
@@ -33,7 +33,7 @@ exports[`renders ./components/layout/demo/basic.md correctly 1`] = `
|
||||
class="ant-layout"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider"
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
>
|
||||
<div
|
||||
@@ -71,7 +71,7 @@ exports[`renders ./components/layout/demo/basic.md correctly 1`] = `
|
||||
Content
|
||||
</div>
|
||||
<div
|
||||
class="ant-layout-sider"
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
>
|
||||
<div
|
||||
@@ -91,7 +91,7 @@ exports[`renders ./components/layout/demo/basic.md correctly 1`] = `
|
||||
class="ant-layout"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider"
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
>
|
||||
<div
|
||||
@@ -128,7 +128,7 @@ exports[`renders ./components/layout/demo/custom-trigger.md correctly 1`] = `
|
||||
class="ant-layout"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider"
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
>
|
||||
<div
|
||||
@@ -138,13 +138,10 @@ exports[`renders ./components/layout/demo/custom-trigger.md correctly 1`] = `
|
||||
class="logo"
|
||||
/>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item ant-menu-item-selected"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -157,7 +154,6 @@ exports[`renders ./components/layout/demo/custom-trigger.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -170,7 +166,6 @@ exports[`renders ./components/layout/demo/custom-trigger.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -212,34 +207,29 @@ exports[`renders ./components/layout/demo/fixed.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-layout-header"
|
||||
style="position:fixed;width:100%"
|
||||
style="position:fixed;z-index:1;width:100%"
|
||||
>
|
||||
<div
|
||||
class="logo"
|
||||
/>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-dark ant-menu-root ant-menu-horizontal"
|
||||
role="menu"
|
||||
style="line-height:64px"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
>
|
||||
nav 1
|
||||
</li>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item ant-menu-item-selected"
|
||||
role="menuitem"
|
||||
>
|
||||
nav 2
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
>
|
||||
@@ -312,7 +302,7 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
|
||||
class="ant-layout"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider"
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="overflow:auto;height:100vh;position:fixed;left:0;flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
>
|
||||
<div
|
||||
@@ -322,13 +312,10 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
|
||||
class="logo"
|
||||
/>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -343,7 +330,6 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -358,7 +344,6 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -373,7 +358,6 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item ant-menu-item-selected"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -388,7 +372,6 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -403,7 +386,6 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -418,7 +400,6 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -433,7 +414,6 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -577,7 +557,7 @@ exports[`renders ./components/layout/demo/responsive.md correctly 1`] = `
|
||||
class="ant-layout"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider"
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
>
|
||||
<div
|
||||
@@ -587,13 +567,10 @@ exports[`renders ./components/layout/demo/responsive.md correctly 1`] = `
|
||||
class="logo"
|
||||
/>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -608,7 +585,6 @@ exports[`renders ./components/layout/demo/responsive.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -623,7 +599,6 @@ exports[`renders ./components/layout/demo/responsive.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -638,7 +613,6 @@ exports[`renders ./components/layout/demo/responsive.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item ant-menu-item-selected"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -688,7 +662,7 @@ exports[`renders ./components/layout/demo/side.md correctly 1`] = `
|
||||
style="min-height:100vh"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider ant-layout-sider-has-trigger"
|
||||
class="ant-layout-sider ant-layout-sider-dark ant-layout-sider-has-trigger"
|
||||
style="flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
>
|
||||
<div
|
||||
@@ -698,13 +672,10 @@ exports[`renders ./components/layout/demo/side.md correctly 1`] = `
|
||||
class="logo"
|
||||
/>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item ant-menu-item-selected"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -717,7 +688,6 @@ exports[`renders ./components/layout/demo/side.md correctly 1`] = `
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -731,11 +701,11 @@ exports[`renders ./components/layout/demo/side.md correctly 1`] = `
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline"
|
||||
role="menuitem"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-owns="sub1$Menu"
|
||||
class="ant-menu-submenu-title"
|
||||
style="padding-left:24px"
|
||||
>
|
||||
@@ -751,14 +721,15 @@ exports[`renders ./components/layout/demo/side.md correctly 1`] = `
|
||||
class="ant-menu-submenu-arrow"
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline"
|
||||
role="menuitem"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-owns="sub2$Menu"
|
||||
class="ant-menu-submenu-title"
|
||||
style="padding-left:24px"
|
||||
>
|
||||
@@ -774,9 +745,9 @@ exports[`renders ./components/layout/demo/side.md correctly 1`] = `
|
||||
class="ant-menu-submenu-arrow"
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
@@ -866,28 +837,23 @@ exports[`renders ./components/layout/demo/top.md correctly 1`] = `
|
||||
class="logo"
|
||||
/>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-dark ant-menu-root ant-menu-horizontal"
|
||||
role="menu"
|
||||
style="line-height:64px"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
>
|
||||
nav 1
|
||||
</li>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item ant-menu-item-selected"
|
||||
role="menuitem"
|
||||
>
|
||||
nav 2
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
>
|
||||
@@ -966,28 +932,23 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
|
||||
class="logo"
|
||||
/>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-dark ant-menu-root ant-menu-horizontal"
|
||||
role="menu"
|
||||
style="line-height:64px"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
>
|
||||
nav 1
|
||||
</li>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item ant-menu-item-selected"
|
||||
role="menuitem"
|
||||
>
|
||||
nav 2
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
>
|
||||
@@ -1045,21 +1006,20 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
|
||||
style="padding:24px 0;background:#fff"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider"
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="background:#fff;flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider-children"
|
||||
>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
|
||||
role="menu"
|
||||
style="height:100%"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected"
|
||||
role="menuitem"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
@@ -1079,13 +1039,11 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
|
||||
/>
|
||||
</div>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-sub ant-menu-inline"
|
||||
id="sub1$Menu"
|
||||
role="menu"
|
||||
>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item ant-menu-item-selected"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
@@ -1093,7 +1051,6 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
|
||||
option1
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
@@ -1101,7 +1058,6 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
|
||||
option2
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
@@ -1109,7 +1065,6 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
|
||||
option3
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
@@ -1120,11 +1075,11 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline"
|
||||
role="menuitem"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-owns="sub2$Menu"
|
||||
class="ant-menu-submenu-title"
|
||||
style="padding-left:24px"
|
||||
>
|
||||
@@ -1138,14 +1093,15 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
|
||||
class="ant-menu-submenu-arrow"
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline"
|
||||
role="menuitem"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-owns="sub3$Menu"
|
||||
class="ant-menu-submenu-title"
|
||||
style="padding-left:24px"
|
||||
>
|
||||
@@ -1159,6 +1115,7 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
|
||||
class="ant-menu-submenu-arrow"
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -1191,28 +1148,23 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
|
||||
class="logo"
|
||||
/>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-dark ant-menu-root ant-menu-horizontal"
|
||||
role="menu"
|
||||
style="line-height:64px"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
>
|
||||
nav 1
|
||||
</li>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item ant-menu-item-selected"
|
||||
role="menuitem"
|
||||
>
|
||||
nav 2
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
>
|
||||
@@ -1224,21 +1176,20 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
|
||||
class="ant-layout"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider"
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="background:#fff;flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider-children"
|
||||
>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
|
||||
role="menu"
|
||||
style="height:100%;border-right:0"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected"
|
||||
role="menuitem"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
@@ -1258,13 +1209,11 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
|
||||
/>
|
||||
</div>
|
||||
<ul
|
||||
aria-activedescendant=""
|
||||
class="ant-menu ant-menu-sub ant-menu-inline"
|
||||
id="sub1$Menu"
|
||||
role="menu"
|
||||
>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="ant-menu-item ant-menu-item-selected"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
@@ -1272,7 +1221,6 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
|
||||
option1
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
@@ -1280,7 +1228,6 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
|
||||
option2
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
@@ -1288,7 +1235,6 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
|
||||
option3
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
@@ -1299,11 +1245,11 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline"
|
||||
role="menuitem"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-owns="sub2$Menu"
|
||||
class="ant-menu-submenu-title"
|
||||
style="padding-left:24px"
|
||||
>
|
||||
@@ -1317,14 +1263,15 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
|
||||
class="ant-menu-submenu-arrow"
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline"
|
||||
role="menuitem"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-owns="sub3$Menu"
|
||||
class="ant-menu-submenu-title"
|
||||
style="padding-left:24px"
|
||||
>
|
||||
@@ -1338,6 +1285,7 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
|
||||
class="ant-menu-submenu-arrow"
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -34,4 +34,39 @@ describe('Layout', () => {
|
||||
);
|
||||
expect(wrapper.find('.ant-layout-sider').hasClass('ant-layout-sider-has-trigger')).toBe(true);
|
||||
});
|
||||
|
||||
it('should have 50% width of sidebar', async () => {
|
||||
const wrapper = mount(
|
||||
<Layout>
|
||||
<div><Sider width="50%">Sider</Sider></div>
|
||||
<Content>Content</Content>
|
||||
</Layout>
|
||||
);
|
||||
expect(wrapper.find('.ant-layout-sider').at(0).prop('style').width).toBe('50%');
|
||||
expect(wrapper.find('.ant-layout-sider').at(0).prop('style').flex).toBe('0 0 50%');
|
||||
});
|
||||
|
||||
it('detect ant-layout-sider-zero-width class in sider when its width is 0%', async () => {
|
||||
const wrapper = mount(
|
||||
<Layout>
|
||||
<div><Sider width="0%">Sider</Sider></div>
|
||||
<Content>Content</Content>
|
||||
</Layout>
|
||||
);
|
||||
expect(wrapper.find('.ant-layout-sider').hasClass('ant-layout-sider-zero-width')).toBe(true);
|
||||
});
|
||||
|
||||
it('detect ant-layout-sider-dark as default theme', async () => {
|
||||
const wrapper = mount(
|
||||
<Sider>Sider</Sider>
|
||||
);
|
||||
expect(wrapper.find('.ant-layout-sider').hasClass('ant-layout-sider-dark'));
|
||||
});
|
||||
|
||||
it('detect ant-layout-sider-light when set light theme', async () => {
|
||||
const wrapper = mount(
|
||||
<Sider theme="light">Sider</Sider>
|
||||
);
|
||||
expect(wrapper.find('.ant-layout-sider').hasClass('ant-layout-sider-light'));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ const { Header, Content, Footer } = Layout;
|
||||
|
||||
ReactDOM.render(
|
||||
<Layout>
|
||||
<Header style={{ position: 'fixed', width: '100%' }}>
|
||||
<Header style={{ position: 'fixed', zIndex: 1, width: '100%' }}>
|
||||
<div className="logo" />
|
||||
<Menu
|
||||
theme="dark"
|
||||
|
||||
@@ -98,6 +98,7 @@ The sidebar.
|
||||
| trigger | specify the customized trigger, set to null to hide the trigger | string\|ReactNode | - |
|
||||
| width | width of the sidebar | number\|string | 200 |
|
||||
| onCollapse | the callback function, executed by clicking the trigger or activating the responsive layout | (collapsed, type) => {} | - |
|
||||
| theme | color theme of the sidebar | string: `light` `dark` | `dark` |
|
||||
|
||||
#### breakpoint width
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user