mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-09 10:59:19 +08:00
Compare commits
619 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d4d6f5402 | ||
|
|
162b6979af | ||
|
|
b95207d58e | ||
|
|
882cec62d6 | ||
|
|
e573ac4e89 | ||
|
|
e915a83326 | ||
|
|
a9b95fe63b | ||
|
|
8e20fe6779 | ||
|
|
d8d48487b0 | ||
|
|
d89cca53b1 | ||
|
|
31fa14a742 | ||
|
|
77c5adbe4d | ||
|
|
bd9b38527e | ||
|
|
00d1276ed2 | ||
|
|
75d84b2041 | ||
|
|
cf360252f7 | ||
|
|
14f9f95864 | ||
|
|
0bf728c3e8 | ||
|
|
f958a1cbc8 | ||
|
|
c353e8bb06 | ||
|
|
49533aafdc | ||
|
|
27bc2d1e02 | ||
|
|
ada81616b5 | ||
|
|
0cdb4c8c86 | ||
|
|
76793143ae | ||
|
|
59a53fbb69 | ||
|
|
c7e1b050ab | ||
|
|
2c9ddcb1b2 | ||
|
|
37c894f1a2 | ||
|
|
059b106ccf | ||
|
|
11bbd725f7 | ||
|
|
e6b8e24828 | ||
|
|
9e9e62911c | ||
|
|
e761538e26 | ||
|
|
9b8e0bb908 | ||
|
|
7c77a764e1 | ||
|
|
527f34fe6d | ||
|
|
163154a4fb | ||
|
|
e3ac222fd3 | ||
|
|
d039e32e6b | ||
|
|
56c42e496b | ||
|
|
81bde547cd | ||
|
|
afe7172974 | ||
|
|
4be9535926 | ||
|
|
cf401f73c8 | ||
|
|
6773020607 | ||
|
|
cfd66fa030 | ||
|
|
6844c413c2 | ||
|
|
9fcd20c6cc | ||
|
|
3712832a03 | ||
|
|
fd9846a145 | ||
|
|
030c545964 | ||
|
|
9b54bd728d | ||
|
|
ef7e7a80d2 | ||
|
|
d5e7187d9d | ||
|
|
b2e92d38eb | ||
|
|
670ec79fa0 | ||
|
|
19da433933 | ||
|
|
f7c34de3ca | ||
|
|
84df944aaf | ||
|
|
98a13a7569 | ||
|
|
89d7101e6e | ||
|
|
ab972ac1eb | ||
|
|
9e96b9e2d5 | ||
|
|
2a3fc818d0 | ||
|
|
5a1ffb7894 | ||
|
|
cea0e45671 | ||
|
|
d13c76d7e4 | ||
|
|
5290421ac9 | ||
|
|
1bf9959062 | ||
|
|
75d7038691 | ||
|
|
4e9fc51dba | ||
|
|
d7949a76ad | ||
|
|
ccd2820ce7 | ||
|
|
b34b956529 | ||
|
|
47b3aa2225 | ||
|
|
84bd53627b | ||
|
|
cb2094265e | ||
|
|
f0a4e211b1 | ||
|
|
84225e4d50 | ||
|
|
94edeaa02f | ||
|
|
c93400d375 | ||
|
|
21bd9444f4 | ||
|
|
0cea6237dc | ||
|
|
a5efa7a81a | ||
|
|
129975f9dc | ||
|
|
bffa58f439 | ||
|
|
4b485d393b | ||
|
|
419004e38a | ||
|
|
b0b619c877 | ||
|
|
670f8f2f1e | ||
|
|
fdbf37a9c0 | ||
|
|
4af818ca8e | ||
|
|
0c2eed6866 | ||
|
|
e0f57e72e0 | ||
|
|
faa75d592c | ||
|
|
77bc48f146 | ||
|
|
67c88571e7 | ||
|
|
03e6b33681 | ||
|
|
973f55babb | ||
|
|
5203d256dd | ||
|
|
c54255a703 | ||
|
|
508401cca4 | ||
|
|
7c260c03a5 | ||
|
|
c13e56ab92 | ||
|
|
cc045bb325 | ||
|
|
6f6430bfee | ||
|
|
688f8a3ab0 | ||
|
|
415848c359 | ||
|
|
1e11c83e74 | ||
|
|
baf001898d | ||
|
|
2932b39c88 | ||
|
|
1f371eee09 | ||
|
|
58ccb40005 | ||
|
|
76466dae9f | ||
|
|
254c17e320 | ||
|
|
ebf9c1fa4a | ||
|
|
8b9a005c1f | ||
|
|
b57d306107 | ||
|
|
b467cc5cbb | ||
|
|
ae8603838a | ||
|
|
1bba2ef65e | ||
|
|
4066f2f624 | ||
|
|
c2437a915d | ||
|
|
a518a2b0b1 | ||
|
|
35a6a887a3 | ||
|
|
b264589b77 | ||
|
|
3629830a85 | ||
|
|
d7288e99a0 | ||
|
|
61378e4605 | ||
|
|
0689982def | ||
|
|
e613861e63 | ||
|
|
f646b6fae8 | ||
|
|
e657fb806f | ||
|
|
6619700893 | ||
|
|
0f93896f0b | ||
|
|
ac50fa147c | ||
|
|
fdbf95aabd | ||
|
|
c69cf4a261 | ||
|
|
476853c320 | ||
|
|
8d0bba4dea | ||
|
|
e197163a78 | ||
|
|
a7b81d52af | ||
|
|
6f1fe30df1 | ||
|
|
fb839eb1d1 | ||
|
|
706f0bbf56 | ||
|
|
50fe770458 | ||
|
|
c40b291415 | ||
|
|
6106aab9d5 | ||
|
|
d6d485b72d | ||
|
|
6ad1b18a47 | ||
|
|
4feb186085 | ||
|
|
baa56b6d85 | ||
|
|
ce78029933 | ||
|
|
8bd10889c6 | ||
|
|
f53d931890 | ||
|
|
b4f38f7a22 | ||
|
|
2120d7dfaa | ||
|
|
a00c06c58b | ||
|
|
5b61c0fac9 | ||
|
|
44cfc351cb | ||
|
|
f64558da89 | ||
|
|
a216d6e4f7 | ||
|
|
bfd5644ff0 | ||
|
|
f546c8b9e3 | ||
|
|
75b090aff3 | ||
|
|
70c6e47cde | ||
|
|
32ee08caa5 | ||
|
|
b87b1283ea | ||
|
|
551763e768 | ||
|
|
b10f4cffd9 | ||
|
|
7f2f814279 | ||
|
|
c955770c40 | ||
|
|
6804fdad1a | ||
|
|
8cb146becd | ||
|
|
6a52cf0303 | ||
|
|
c99ecdac39 | ||
|
|
f45f7353a5 | ||
|
|
316913ca37 | ||
|
|
1bbaa49bef | ||
|
|
aee2e7a5c9 | ||
|
|
4a3af4caef | ||
|
|
471e97ab76 | ||
|
|
2268c7aa88 | ||
|
|
d4874fc0b3 | ||
|
|
8b514406e3 | ||
|
|
1a82efa5ca | ||
|
|
a820046130 | ||
|
|
5f1da59488 | ||
|
|
9924bbf838 | ||
|
|
7de007100d | ||
|
|
04ad7236e4 | ||
|
|
a83143bbbc | ||
|
|
188e5630b3 | ||
|
|
02dccd9643 | ||
|
|
8497e54e39 | ||
|
|
9f633bc002 | ||
|
|
159d42fda8 | ||
|
|
850b670862 | ||
|
|
610807ebf9 | ||
|
|
f90702cd0c | ||
|
|
0cd0ebe7dc | ||
|
|
9559754b5b | ||
|
|
681aab1ef1 | ||
|
|
9f38c46039 | ||
|
|
2afab58ac8 | ||
|
|
9cb3c94204 | ||
|
|
55332f6971 | ||
|
|
e6b1b1a4e7 | ||
|
|
be0c654fff | ||
|
|
2e284aa017 | ||
|
|
4aa1b62659 | ||
|
|
bb4f0da50e | ||
|
|
5d9d45b597 | ||
|
|
4f1605949e | ||
|
|
217723d321 | ||
|
|
586c7f5218 | ||
|
|
fd7c942403 | ||
|
|
c463b2cc35 | ||
|
|
5e5ec80d04 | ||
|
|
b0e528d14c | ||
|
|
9d03db0503 | ||
|
|
41dd9560c9 | ||
|
|
da3f5528f4 | ||
|
|
6093f11cf0 | ||
|
|
68119768cc | ||
|
|
53d7a20939 | ||
|
|
50e33768a9 | ||
|
|
e15be10faf | ||
|
|
b73e84da9b | ||
|
|
34c2fad636 | ||
|
|
90a36eed0b | ||
|
|
f7e00f645e | ||
|
|
63a32422e5 | ||
|
|
31ba421268 | ||
|
|
227233268d | ||
|
|
339246d316 | ||
|
|
08c63d1e23 | ||
|
|
731505813a | ||
|
|
c19685e0ea | ||
|
|
64d151aa81 | ||
|
|
82d709676a | ||
|
|
49f5ed7764 | ||
|
|
fdcbfc909d | ||
|
|
f250b2fa29 | ||
|
|
ce36d3e2fe | ||
|
|
9a6ad0edb9 | ||
|
|
40a987e059 | ||
|
|
705a6d63a1 | ||
|
|
79289fa708 | ||
|
|
4dccbd8eab | ||
|
|
2ab7c3f182 | ||
|
|
313f2df632 | ||
|
|
d766472d94 | ||
|
|
80e3dfa9be | ||
|
|
626f918597 | ||
|
|
4884e91c49 | ||
|
|
67a482f4e5 | ||
|
|
04eb91dc8e | ||
|
|
e188537c00 | ||
|
|
e26eb5f892 | ||
|
|
1cf1a15d50 | ||
|
|
d7c7b86f31 | ||
|
|
0a70563e44 | ||
|
|
7f1e7a3120 | ||
|
|
8cce0383a1 | ||
|
|
72a846681a | ||
|
|
741ff5c3bb | ||
|
|
6705454b83 | ||
|
|
237c205169 | ||
|
|
acb4cb6859 | ||
|
|
2beb28518c | ||
|
|
28f71921ea | ||
|
|
338733d70f | ||
|
|
dd6c855028 | ||
|
|
60d45d8d37 | ||
|
|
9c0f12c7e8 | ||
|
|
e6a8736b9d | ||
|
|
c393ca700e | ||
|
|
ee58a34175 | ||
|
|
015109b42b | ||
|
|
fafa3b7e51 | ||
|
|
116af77548 | ||
|
|
3fad93e41b | ||
|
|
cc11b95194 | ||
|
|
333e8ffeb2 | ||
|
|
48c7011f67 | ||
|
|
d221458939 | ||
|
|
612bcdf4a6 | ||
|
|
3d578c87be | ||
|
|
f8c1e794da | ||
|
|
22f615200a | ||
|
|
dfe2477b87 | ||
|
|
c4b602e835 | ||
|
|
5f825d8172 | ||
|
|
c9fada3222 | ||
|
|
1abe5495a2 | ||
|
|
d643d113ff | ||
|
|
968e7edec3 | ||
|
|
9a9aa94cfd | ||
|
|
22c313d032 | ||
|
|
540fc211df | ||
|
|
b0593c8a41 | ||
|
|
cf01c8649f | ||
|
|
2ba90f7ff5 | ||
|
|
ee80a2f710 | ||
|
|
c102053f3a | ||
|
|
1444043fd8 | ||
|
|
ce17f19ca0 | ||
|
|
701f35d0eb | ||
|
|
2961dda311 | ||
|
|
6e8e36080e | ||
|
|
41bfb79cb7 | ||
|
|
012969e742 | ||
|
|
fdf0f2e585 | ||
|
|
4cb70b6f16 | ||
|
|
c5bcf57537 | ||
|
|
aa3413b086 | ||
|
|
0d46d07ad1 | ||
|
|
633d064640 | ||
|
|
6ded8588ed | ||
|
|
2a0df4f465 | ||
|
|
5c8ffd473b | ||
|
|
3a28f31fca | ||
|
|
747691f600 | ||
|
|
97fde3a304 | ||
|
|
cffcd0378a | ||
|
|
2b2a6a3d22 | ||
|
|
dff19af744 | ||
|
|
b9e7d853a4 | ||
|
|
3d2ccd8081 | ||
|
|
f05f2dd197 | ||
|
|
91f2dc522f | ||
|
|
107731a988 | ||
|
|
e15773e25b | ||
|
|
6668d48c54 | ||
|
|
72bb377628 | ||
|
|
39456263b5 | ||
|
|
74645b7baf | ||
|
|
e4a1a45b09 | ||
|
|
0f83783709 | ||
|
|
1489903d9d | ||
|
|
33cb4c9bb4 | ||
|
|
5c1257d726 | ||
|
|
83dcc0016f | ||
|
|
cbb46a86b3 | ||
|
|
009f2c8f33 | ||
|
|
34bf3fdb66 | ||
|
|
3d355fde08 | ||
|
|
50c3f89e19 | ||
|
|
ca896092e2 | ||
|
|
c9267469a0 | ||
|
|
bd692bef71 | ||
|
|
78b7cf22a1 | ||
|
|
35e390018c | ||
|
|
58fcee34c1 | ||
|
|
5f2874b292 | ||
|
|
08dd4435df | ||
|
|
7d3cb95f17 | ||
|
|
df1555c6c7 | ||
|
|
7139493258 | ||
|
|
081604e253 | ||
|
|
98232382f1 | ||
|
|
01b98e79d9 | ||
|
|
ba9d75e3bd | ||
|
|
9f2af262ef | ||
|
|
e34fc4a7c4 | ||
|
|
b57c000678 | ||
|
|
b66ab37463 | ||
|
|
0b5d09dd4b | ||
|
|
10cf054b93 | ||
|
|
9c3bf77b92 | ||
|
|
e3e183ea39 | ||
|
|
815baee4d9 | ||
|
|
a243aba422 | ||
|
|
402f3a9afb | ||
|
|
5ccf03f498 | ||
|
|
245deed4b6 | ||
|
|
9cd8f79366 | ||
|
|
935b0e5887 | ||
|
|
e1299bfcc9 | ||
|
|
bb1f157645 | ||
|
|
f606ca23f4 | ||
|
|
5c79e642ba | ||
|
|
4fdad9a2f5 | ||
|
|
0b61b13e56 | ||
|
|
e5c664f7f0 | ||
|
|
7f347ec5f2 | ||
|
|
80017a0f92 | ||
|
|
6391df163b | ||
|
|
2c531a827d | ||
|
|
e41340ac4d | ||
|
|
53a76f0bf7 | ||
|
|
7790046ce2 | ||
|
|
4119c9324a | ||
|
|
f0c82d5aa7 | ||
|
|
16a1feb8fb | ||
|
|
d37c16aeaf | ||
|
|
7bf44c417c | ||
|
|
699978bcf0 | ||
|
|
c3c2c157d0 | ||
|
|
e4bdfb218c | ||
|
|
b70d607b9f | ||
|
|
f6d12c5d88 | ||
|
|
190e2a28a7 | ||
|
|
c27a3a40a7 | ||
|
|
f5153ab950 | ||
|
|
3967f12f3d | ||
|
|
156ff7652c | ||
|
|
313a68c15f | ||
|
|
14417f1614 | ||
|
|
5183592ece | ||
|
|
62eaa4193b | ||
|
|
a9d44593b3 | ||
|
|
a534e4a56a | ||
|
|
5f1d5a17de | ||
|
|
a823400b79 | ||
|
|
3e38e4448c | ||
|
|
d1c39d7ec5 | ||
|
|
9868a4dc59 | ||
|
|
e199a7a301 | ||
|
|
5e4d8f10ac | ||
|
|
053497724d | ||
|
|
939660ec86 | ||
|
|
e12b560329 | ||
|
|
57d36f5b68 | ||
|
|
2da7e29198 | ||
|
|
2325a4438d | ||
|
|
1a428e852a | ||
|
|
df63f2567a | ||
|
|
0d927a18f1 | ||
|
|
8ae2b1f542 | ||
|
|
c2dc6305f3 | ||
|
|
90a12fa3d0 | ||
|
|
22b5f65830 | ||
|
|
8934bbfffa | ||
|
|
dabec4c833 | ||
|
|
48ee1a68c6 | ||
|
|
2cb635e921 | ||
|
|
c53329a27d | ||
|
|
9ff7f31dfe | ||
|
|
75440c47c8 | ||
|
|
7e53cc7f2a | ||
|
|
8d4ede4a5a | ||
|
|
a400014efe | ||
|
|
eda0064e83 | ||
|
|
89bccf5752 | ||
|
|
4c9d03874b | ||
|
|
f955620601 | ||
|
|
3ddc99c28f | ||
|
|
656b5abf65 | ||
|
|
c9c44c173f | ||
|
|
88cab9547b | ||
|
|
60f3e775d0 | ||
|
|
41da9de946 | ||
|
|
44da4125fa | ||
|
|
ac14f44f2b | ||
|
|
569b6539d3 | ||
|
|
454a02b4d9 | ||
|
|
8cdf1c017a | ||
|
|
8f30a14790 | ||
|
|
7379cfa4c2 | ||
|
|
2785d22e5c | ||
|
|
9963e515d1 | ||
|
|
5e9bf9fdc0 | ||
|
|
99bcad6dd6 | ||
|
|
336a6fba42 | ||
|
|
175e0aaa14 | ||
|
|
22ffa61da0 | ||
|
|
54f2abfe47 | ||
|
|
efbb2849dc | ||
|
|
d50cc55d87 | ||
|
|
6a49973bb9 | ||
|
|
d2140490d8 | ||
|
|
dfcaa408c2 | ||
|
|
fb46b8a864 | ||
|
|
d860358f94 | ||
|
|
289dd080b9 | ||
|
|
7cf20f18a1 | ||
|
|
6556b583bd | ||
|
|
f09686d3df | ||
|
|
4f1ad3ef4b | ||
|
|
eb83d6b341 | ||
|
|
f9c56b6eb4 | ||
|
|
6401da2082 | ||
|
|
d2c541b4e2 | ||
|
|
facbe46251 | ||
|
|
be72d1762a | ||
|
|
eb5c7ffc7e | ||
|
|
8ec4d3f64f | ||
|
|
fb2ef64036 | ||
|
|
cd34b624b3 | ||
|
|
835bcabdbc | ||
|
|
937beba421 | ||
|
|
d77c2e8ba7 | ||
|
|
17f7e2f4d2 | ||
|
|
800871166c | ||
|
|
b7e877aeef | ||
|
|
c550cb050b | ||
|
|
64cb9584ce | ||
|
|
55265ac4ef | ||
|
|
677168b007 | ||
|
|
7935651899 | ||
|
|
cf3d611f59 | ||
|
|
a4c07fc0af | ||
|
|
a1e0c41c8b | ||
|
|
d7e97aa996 | ||
|
|
4a3e01ff0b | ||
|
|
3e22b505a3 | ||
|
|
db97c5788e | ||
|
|
1163d8e23d | ||
|
|
5e09660a3e | ||
|
|
9a43e439b3 | ||
|
|
428b07625c | ||
|
|
17c63e52bf | ||
|
|
02faa4bcf1 | ||
|
|
4902c5a4f0 | ||
|
|
8bd8eee573 | ||
|
|
f467df5fe2 | ||
|
|
1dab17eef0 | ||
|
|
e206b4146b | ||
|
|
c3e263f2f2 | ||
|
|
2105a330dd | ||
|
|
6d238a734d | ||
|
|
2c86aebfa3 | ||
|
|
5a10d29796 | ||
|
|
3d76859bbc | ||
|
|
1d50004644 | ||
|
|
ac7865a6fc | ||
|
|
fc98ab7222 | ||
|
|
40afa44673 | ||
|
|
43bc7196ea | ||
|
|
089591ac34 | ||
|
|
f748c4ef17 | ||
|
|
0b6d34d474 | ||
|
|
e2dacde754 | ||
|
|
e797d44c9e | ||
|
|
62d51034c4 | ||
|
|
849ab34189 | ||
|
|
757c57622b | ||
|
|
fd38c347a8 | ||
|
|
54d050324a | ||
|
|
76ee9668ef | ||
|
|
fabec4831c | ||
|
|
7489786d22 | ||
|
|
31267c5648 | ||
|
|
6e1ffb96ca | ||
|
|
5ca5f44a7e | ||
|
|
50416b3a7b | ||
|
|
09e69c385e | ||
|
|
f4c489553f | ||
|
|
95f6f0f14a | ||
|
|
c70b49a709 | ||
|
|
5e7f3cc67e | ||
|
|
edcd1b2609 | ||
|
|
8ab146220e | ||
|
|
6c451865eb | ||
|
|
7d5910faf0 | ||
|
|
7e9fe271ed | ||
|
|
cff24d5dcb | ||
|
|
f9cb1522f3 | ||
|
|
0716d1498f | ||
|
|
f7d1d41220 | ||
|
|
ff509bccd0 | ||
|
|
bff09f8fde | ||
|
|
c7cc8d40c8 | ||
|
|
c2a1fe5b1f | ||
|
|
9c08bb2482 | ||
|
|
02d7292576 | ||
|
|
178ccbee6a | ||
|
|
d3b367ad04 | ||
|
|
ac5050f4ed | ||
|
|
87da7bfe67 | ||
|
|
efd25100a5 | ||
|
|
4ad5830eec | ||
|
|
54b11b2ae3 | ||
|
|
19a7b55a9f | ||
|
|
e3d2754b1d | ||
|
|
58c6900175 | ||
|
|
1855fef437 | ||
|
|
c338569cff | ||
|
|
2c6733b0c8 | ||
|
|
b1f3587e02 | ||
|
|
13fda44fb1 | ||
|
|
8c11676afa | ||
|
|
436d4b1be5 | ||
|
|
3f4f5864fe | ||
|
|
59c0cdf3a2 | ||
|
|
0ca9c69da2 | ||
|
|
8c3081788c | ||
|
|
f7ead77f88 | ||
|
|
ca93757747 | ||
|
|
fca1367085 | ||
|
|
d160016959 | ||
|
|
7bc3d4f222 | ||
|
|
653724b79e | ||
|
|
65293f62d6 | ||
|
|
9c2473ab25 | ||
|
|
3d9b891a26 | ||
|
|
de68e37da2 | ||
|
|
12ce6aba06 | ||
|
|
6bb6c4c243 | ||
|
|
5999aa7414 | ||
|
|
90e952a920 | ||
|
|
78ec790311 | ||
|
|
89ce33f5d8 | ||
|
|
eb90c5b0a0 | ||
|
|
deafd3fcce | ||
|
|
ff30366d22 | ||
|
|
f93f86123e | ||
|
|
ca616647ce | ||
|
|
50d908662e | ||
|
|
bfd5d7c910 | ||
|
|
49acc871b9 | ||
|
|
77d45690c0 | ||
|
|
77dd5af0eb | ||
|
|
939ea047ad | ||
|
|
678168a74e | ||
|
|
1cc9ffdd3e |
@@ -1,38 +1,20 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const packageInfo = require('./package.json');
|
||||
const defaultVars = require('./scripts/default-vars');
|
||||
const darkVars = require('./scripts/dark-vars');
|
||||
const compactVars = require('./scripts/compact-vars');
|
||||
|
||||
function generateThemeFileContent(theme) {
|
||||
return `const { ${theme}ThemeSingle } = require('./theme');\nconst defaultTheme = require('./default-theme');\n
|
||||
module.exports = {
|
||||
...defaultTheme,
|
||||
...${theme}ThemeSingle
|
||||
}`;
|
||||
}
|
||||
|
||||
// We need compile additional content for antd user
|
||||
function finalizeCompile() {
|
||||
if (fs.existsSync(path.join(__dirname, './lib'))) {
|
||||
// Build package.json version to lib/version/index.js
|
||||
// prevent json-loader needing in user-side
|
||||
const versionFilePath = path.join(process.cwd(), 'lib', 'version', 'index.js');
|
||||
const versionFileContent = fs.readFileSync(versionFilePath).toString();
|
||||
fs.writeFileSync(
|
||||
versionFilePath,
|
||||
versionFileContent.replace(
|
||||
/require\(('|")\.\.\/\.\.\/package\.json('|")\)/,
|
||||
`{ version: '${packageInfo.version}' }`,
|
||||
),
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Wrote version into lib/version/index.js');
|
||||
|
||||
// Build package.json version to lib/version/index.d.ts
|
||||
// prevent https://github.com/ant-design/ant-design/issues/4935
|
||||
const versionDefPath = path.join(process.cwd(), 'lib', 'version', 'index.d.ts');
|
||||
fs.writeFileSync(
|
||||
versionDefPath,
|
||||
`declare var _default: "${packageInfo.version}";\nexport default _default;\n`,
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Wrote version into lib/version/index.d.ts');
|
||||
|
||||
// Build a entry less file to dist/antd.less
|
||||
const componentsPath = path.join(process.cwd(), 'components');
|
||||
let componentsLessContent = '';
|
||||
@@ -53,19 +35,34 @@ function finalizeCompile() {
|
||||
|
||||
function buildThemeFile(theme, vars) {
|
||||
// Build less entry file: dist/antd.${theme}.less
|
||||
fs.writeFileSync(
|
||||
path.join(process.cwd(), 'dist', `antd.${theme}.less`),
|
||||
`@import "../lib/style/${theme}.less";\n@import "../lib/style/components.less";`,
|
||||
);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Built a entry less file to dist/antd.${theme}.less`);
|
||||
if (theme !== 'default') {
|
||||
fs.writeFileSync(
|
||||
path.join(process.cwd(), 'dist', `antd.${theme}.less`),
|
||||
`@import "../lib/style/${theme}.less";\n@import "../lib/style/components.less";`,
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Built a entry less file to dist/antd.${theme}.less`);
|
||||
} else {
|
||||
fs.writeFileSync(
|
||||
path.join(process.cwd(), 'dist', `default-theme.js`),
|
||||
`module.exports = ${JSON.stringify(vars, null, 2)};\n`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Build ${theme}.js: dist/${theme}-theme.js, for less-loader
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(process.cwd(), 'dist', `theme.js`),
|
||||
`const ${theme}ThemeSingle = ${JSON.stringify(vars, null, 2)};\n`,
|
||||
{
|
||||
flag: 'a',
|
||||
},
|
||||
);
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(process.cwd(), 'dist', `${theme}-theme.js`),
|
||||
`module.exports = ${JSON.stringify(vars, null, 2)};`,
|
||||
generateThemeFileContent(theme),
|
||||
);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
@@ -80,10 +77,47 @@ function finalizeDist() {
|
||||
'@import "../lib/style/index.less";\n@import "../lib/style/components.less";',
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
fs.writeFileSync(
|
||||
path.join(process.cwd(), 'dist', 'theme.js'),
|
||||
`const defaultTheme = require('./default-theme.js');\n`,
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Built a entry less file to dist/antd.less');
|
||||
buildThemeFile('default', defaultVars);
|
||||
buildThemeFile('dark', darkVars);
|
||||
buildThemeFile('compact', compactVars);
|
||||
fs.writeFileSync(
|
||||
path.join(process.cwd(), 'dist', `theme.js`),
|
||||
`
|
||||
function getThemeVariables(options = {}) {
|
||||
let themeVar = {
|
||||
'hack': \`true;@import "\${require.resolve('antd/lib/style/color/colorPalette.less')}";\`,
|
||||
...defaultTheme
|
||||
};
|
||||
if(options.dark) {
|
||||
themeVar = {
|
||||
...themeVar,
|
||||
...darkThemeSingle
|
||||
}
|
||||
}
|
||||
if(options.compact){
|
||||
themeVar = {
|
||||
...themeVar,
|
||||
...compactThemeSingle
|
||||
}
|
||||
}
|
||||
return themeVar;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
darkThemeSingle,
|
||||
compactThemeSingle,
|
||||
getThemeVariables
|
||||
}`,
|
||||
{
|
||||
flag: 'a',
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,4 +128,5 @@ module.exports = {
|
||||
dist: {
|
||||
finalize: finalizeDist,
|
||||
},
|
||||
generateThemeFileContent,
|
||||
};
|
||||
|
||||
14
.bundle-analyzerrc.json
Normal file
14
.bundle-analyzerrc.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"files": [
|
||||
{
|
||||
"test": "./dist/antd.min.js",
|
||||
"maxSize": "300 kB",
|
||||
"compression": "gzip"
|
||||
},
|
||||
{
|
||||
"test": "./dist/antd.min.css",
|
||||
"maxSize": "65 kB",
|
||||
"compression": "gzip"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -22,10 +22,10 @@ references:
|
||||
ignore: gh-pages
|
||||
- dist:
|
||||
requires:
|
||||
- setup
|
||||
- setup
|
||||
- compile:
|
||||
requires:
|
||||
- setup
|
||||
- setup
|
||||
- lint:
|
||||
requires:
|
||||
- setup
|
||||
@@ -166,7 +166,7 @@ workflows:
|
||||
<<: *workflow
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "0 0 * * *"
|
||||
cron: '0 0 * * *'
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
|
||||
@@ -10,6 +10,10 @@ module.exports = {
|
||||
'**/*.json',
|
||||
],
|
||||
modulePattern: [
|
||||
{
|
||||
pattern: /ConfigContext.*renderEmpty/ms,
|
||||
module: '../empty',
|
||||
},
|
||||
{
|
||||
pattern: /ConfigConsumer.*renderEmpty/ms,
|
||||
module: '../empty',
|
||||
|
||||
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
node_modules/
|
||||
@@ -24,3 +24,5 @@ node_modules
|
||||
_site
|
||||
dist
|
||||
**/*.d.ts
|
||||
# Scripts
|
||||
scripts/previewEditor/**/*
|
||||
59
.eslintrc.js
59
.eslintrc.js
@@ -1,4 +1,4 @@
|
||||
const eslintrc = {
|
||||
module.exports = {
|
||||
extends: [
|
||||
'airbnb',
|
||||
'prettier',
|
||||
@@ -31,6 +31,29 @@ const eslintrc = {
|
||||
'@typescript-eslint/no-unused-expressions': 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.md'],
|
||||
globals: {
|
||||
React: true,
|
||||
ReactDOM: true,
|
||||
mountNode: true,
|
||||
},
|
||||
rules: {
|
||||
indent: 0,
|
||||
'no-console': 0,
|
||||
'no-plusplus': 0,
|
||||
'eol-last': 0,
|
||||
'no-script-url': 0,
|
||||
'prefer-rest-params': 0,
|
||||
'react/no-access-state-in-setstate': 0,
|
||||
'react/destructuring-assignment': 0,
|
||||
'react/no-multi-comp': 0,
|
||||
'jsx-a11y/href-no-hash': 0,
|
||||
'import/no-extraneous-dependencies': 0,
|
||||
'import/no-unresolved': 0,
|
||||
'jsx-a11y/control-has-associated-label': 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
camelcase: 0,
|
||||
@@ -91,38 +114,12 @@ const eslintrc = {
|
||||
'jest/no-test-callback': 0,
|
||||
'jest/expect-expect': 0,
|
||||
'react-hooks/rules-of-hooks': 2, // Checks rules of Hooks
|
||||
"unicorn/better-regex": 2,
|
||||
"unicorn/prefer-trim-start-end": 2,
|
||||
"unicorn/expiring-todo-comments": 2,
|
||||
"unicorn/no-abusive-eslint-disable": 2,
|
||||
'unicorn/better-regex': 2,
|
||||
'unicorn/prefer-trim-start-end': 2,
|
||||
'unicorn/expiring-todo-comments': 2,
|
||||
'unicorn/no-abusive-eslint-disable': 2,
|
||||
},
|
||||
globals: {
|
||||
gtag: true,
|
||||
},
|
||||
};
|
||||
|
||||
if (process.env.RUN_ENV === 'DEMO') {
|
||||
eslintrc.globals = Object.assign(eslintrc.globals, {
|
||||
React: true,
|
||||
ReactDOM: true,
|
||||
mountNode: true,
|
||||
});
|
||||
|
||||
Object.assign(eslintrc.rules, {
|
||||
indent: 0,
|
||||
'no-console': 0,
|
||||
'no-plusplus': 0,
|
||||
'eol-last': 0,
|
||||
'no-script-url': 0,
|
||||
'prefer-rest-params': 0,
|
||||
'react/no-access-state-in-setstate': 0,
|
||||
'react/destructuring-assignment': 0,
|
||||
'react/no-multi-comp': 0,
|
||||
'jsx-a11y/href-no-hash': 0,
|
||||
'import/no-extraneous-dependencies': 0,
|
||||
'import/no-unresolved': 0,
|
||||
'jsx-a11y/control-has-associated-label': 0,
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = eslintrc;
|
||||
|
||||
3
.github/FUNDING.yml
vendored
3
.github/FUNDING.yml
vendored
@@ -4,5 +4,6 @@ github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, u
|
||||
open_collective: ant-design
|
||||
patreon: ant_design
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
issuehunt: ant-design/ant-design
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
custom: # Replace with a single custom sponsorship URL
|
||||
custom: https://www.buymeacoffee.com/antdesign
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
name: '⚠️ Please use new-issue.ant.design ⚠️'
|
||||
about: The issue which is not created via http://new-issue.ant.design will be closed immediately.
|
||||
labels:
|
||||
---
|
||||
|
||||
The issue which is not created via http://new-issue.ant.design will be closed immediately.
|
||||
|
||||
---
|
||||
|
||||
注意:不是用 http://new-issue.ant.design 创建的 issue 会被立即关闭。
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Create new issue
|
||||
url: http://new-issue.ant.design
|
||||
about: The issue which is not created via http://new-issue.ant.design will be closed immediately.
|
||||
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -4,17 +4,20 @@ First of all, thank you for your contribution! 😄
|
||||
New feature please send pull request to feature branch, and rest to master branch.
|
||||
Pull request will be merged after one of collaborators approve.
|
||||
Please makes sure that these form are filled before submitting your pull request, thank you!
|
||||
-->
|
||||
|
||||
[[中文版模板 / Chinese template](https://github.com/ant-design/ant-design/blob/master/.github/PULL_REQUEST_TEMPLATE/pr_cn.md)]
|
||||
-->
|
||||
|
||||
### 🤔 This is a ...
|
||||
|
||||
- [ ] New feature
|
||||
- [ ] Bug fix
|
||||
- [ ] Site / document update
|
||||
- [ ] Site / documentation update
|
||||
- [ ] Demo update
|
||||
- [ ] Component style update
|
||||
- [ ] TypeScript definition update
|
||||
- [ ] Bundle size optimization
|
||||
- [ ] Perfermance optimization
|
||||
- [ ] Refactoring
|
||||
- [ ] Code style optimization
|
||||
- [ ] Test Case
|
||||
@@ -48,7 +51,7 @@ Describe changes from userside, and list all potential break changes or other ri
|
||||
|
||||
### ☑️ Self Check before Merge
|
||||
|
||||
⚠️ Please check all items below before review. ⚠️
|
||||
⚠️ Please check all items below before review. ⚠️
|
||||
|
||||
- [ ] Doc is updated/provided or not needed
|
||||
- [ ] Demo is updated/provided or not needed
|
||||
|
||||
5
.github/PULL_REQUEST_TEMPLATE/pr_cn.md
vendored
5
.github/PULL_REQUEST_TEMPLATE/pr_cn.md
vendored
@@ -13,8 +13,11 @@
|
||||
- [ ] 新特性提交
|
||||
- [ ] 日常 bug 修复
|
||||
- [ ] 站点、文档改进
|
||||
- [ ] 演示代码改进
|
||||
- [ ] 组件样式改进
|
||||
- [ ] TypeScript 定义更新
|
||||
- [ ] 包体积优化
|
||||
- [ ] 性能优化
|
||||
- [ ] 重构
|
||||
- [ ] 代码风格优化
|
||||
- [ ] 测试用例
|
||||
@@ -48,7 +51,7 @@
|
||||
|
||||
### ☑️ 请求合并前的自查清单
|
||||
|
||||
⚠️ 请自检并全部**勾选全部选项**。⚠️
|
||||
⚠️ 请自检并全部**勾选全部选项**。⚠️
|
||||
|
||||
- [ ] 文档已补充或无须补充
|
||||
- [ ] 代码演示已提供或无须提供
|
||||
|
||||
17
.github/workflows/gitleaks.yml
vendored
Normal file
17
.github/workflows/gitleaks.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: gitleaks
|
||||
|
||||
on: [push,pull_request]
|
||||
|
||||
jobs:
|
||||
gitleaks:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: '1'
|
||||
- name: wget
|
||||
uses: wei/wget@v1
|
||||
with:
|
||||
args: -O .gitleaks.toml https://raw.githubusercontent.com/ycjcl868/gitleaks/master/.gitleaks.toml
|
||||
- name: gitleaks-action
|
||||
uses: zricethezav/gitleaks-action@master
|
||||
24
.github/workflows/lighthouse-ci.yml
vendored
24
.github/workflows/lighthouse-ci.yml
vendored
@@ -1,19 +1,11 @@
|
||||
name: Lighthouse
|
||||
on: push
|
||||
name: CI
|
||||
on: [push]
|
||||
jobs:
|
||||
lighthouse:
|
||||
lighthouseci:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Audit URLs using Lighthouse
|
||||
uses: treosh/lighthouse-ci-action@v2
|
||||
with:
|
||||
urls: |
|
||||
https://ant.design
|
||||
https://ant.design/docs/react/introduce-cn
|
||||
https://ant.design/components/button-cn
|
||||
- name: Save results
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: lighthouse-results
|
||||
path: '.lighthouseci' # This will save the Lighthouse results as .json files
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
- run: npm install && npm install -g @lhci/cli@0.4.x
|
||||
- run: npm run site
|
||||
- run: lhci autorun --upload.target=temporary-public-storage
|
||||
|
||||
13
.github/workflows/mirror.yml
vendored
13
.github/workflows/mirror.yml
vendored
@@ -5,11 +5,10 @@ on: [push]
|
||||
jobs:
|
||||
to_gitee:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'ant-design/ant-design'
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: pixta-dev/repository-mirroring-action@v1
|
||||
with:
|
||||
target_repo_url:
|
||||
git@gitee.com:ant-design/ant-design.git
|
||||
ssh_private_key:
|
||||
${{ secrets.GITEE_SSH_PRIVATE_KEY }}
|
||||
- uses: actions/checkout@v1
|
||||
- uses: pixta-dev/repository-mirroring-action@v1
|
||||
with:
|
||||
target_repo_url: git@gitee.com:ant-design/ant-design.git
|
||||
ssh_private_key: ${{ secrets.GITEE_SSH_PRIVATE_KEY }}
|
||||
|
||||
21
.github/workflows/rebase.yml
vendored
21
.github/workflows/rebase.yml
vendored
@@ -1,4 +1,4 @@
|
||||
on:
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
name: Automatic Rebase
|
||||
@@ -8,15 +8,10 @@ jobs:
|
||||
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Automatic Rebase
|
||||
uses: cirrus-actions/rebase@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# https://github.community/t5/GitHub-Actions/Workflow-is-failing-if-no-job-can-be-ran-due-to-condition/m-p/38186#M3250
|
||||
always_job:
|
||||
name: Always run job
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Always run
|
||||
run: echo "This job is used to prevent the workflow to fail when all other jobs are skipped."
|
||||
- uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Automatic Rebase
|
||||
uses: cirrus-actions/rebase@1.3
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -25,6 +25,7 @@ nohup.out
|
||||
_site
|
||||
_data
|
||||
dist
|
||||
report.html
|
||||
/lib
|
||||
/es
|
||||
elasticsearch-*
|
||||
@@ -54,4 +55,10 @@ site/theme/template/Content/Article.jsx
|
||||
site/theme/template/Content/EditButton.jsx
|
||||
site/theme/template/Resources/*.jsx
|
||||
site/theme/template/Resources/**/*.jsx
|
||||
site/theme/template/NotFound.jsx
|
||||
site/theme/template/NotFound.jsx
|
||||
scripts/previewEditor/index.html
|
||||
components/version/version.tsx
|
||||
|
||||
# Image snapshot diff
|
||||
__diff_output__/
|
||||
/jest-stare
|
||||
|
||||
24
.jest.image.js
Normal file
24
.jest.image.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
|
||||
|
||||
// jest config for image snapshots
|
||||
module.exports = {
|
||||
setupFiles: ['./tests/setup.js'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
||||
moduleNameMapper,
|
||||
transform: {
|
||||
'\\.tsx?$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
|
||||
'\\.js$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
|
||||
'\\.md$': './node_modules/@ant-design/tools/lib/jest/demoPreprocessor',
|
||||
'\\.(jpg|png|gif|svg)$': './node_modules/@ant-design/tools/lib/jest/imagePreprocessor',
|
||||
},
|
||||
testRegex: 'image\\.test\\.js$',
|
||||
testEnvironment: 'node',
|
||||
transformIgnorePatterns,
|
||||
snapshotSerializers: ['enzyme-to-json/serializer'],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsConfigFile: './tsconfig.test.json',
|
||||
},
|
||||
},
|
||||
reporters: ['default', 'jest-stare'],
|
||||
};
|
||||
15
.jest.js
15
.jest.js
@@ -1,12 +1,17 @@
|
||||
const libDir = process.env.LIB_DIR;
|
||||
|
||||
const transformIgnorePatterns = [
|
||||
'/dist/',
|
||||
// Ignore modules without es dir.
|
||||
// Update: @babel/runtime should also be transformed
|
||||
'node_modules/(?!.*@babel)[^/]+?/(?!(es|node_modules)/)',
|
||||
'node_modules/(?!.*@(babel|ant-design))[^/]+?/(?!(es|node_modules)/)',
|
||||
];
|
||||
|
||||
function getTestRegex(libDir) {
|
||||
if (libDir === 'dist') {
|
||||
return 'demo\\.test\\.js$';
|
||||
}
|
||||
return '.*\\.test\\.(j|t)sx?$';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
verbose: true,
|
||||
setupFiles: ['./tests/setup.js'],
|
||||
@@ -21,14 +26,14 @@ module.exports = {
|
||||
'^react-dnd-test-backend$': 'react-dnd-test-backend/dist/cjs',
|
||||
'^react-dnd-test-utils$': 'react-dnd-test-utils/dist/cjs',
|
||||
},
|
||||
testPathIgnorePatterns: ['/node_modules/', 'dekko', 'node'],
|
||||
testPathIgnorePatterns: ['/node_modules/', 'dekko', 'node', 'image.test.js'],
|
||||
transform: {
|
||||
'\\.tsx?$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
|
||||
'\\.js$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
|
||||
'\\.md$': './node_modules/@ant-design/tools/lib/jest/demoPreprocessor',
|
||||
'\\.(jpg|png|gif|svg)$': './node_modules/@ant-design/tools/lib/jest/imagePreprocessor',
|
||||
},
|
||||
testRegex: `${libDir === 'dist' ? 'demo' : '.*'}\\.test\\.js$`,
|
||||
testRegex: getTestRegex(process.env.LIB_DIR),
|
||||
collectCoverageFrom: [
|
||||
'components/**/*.{ts,tsx}',
|
||||
'!components/*/style/index.tsx',
|
||||
|
||||
@@ -12,13 +12,8 @@ module.exports = {
|
||||
'\\.md$': './node_modules/@ant-design/tools/lib/jest/demoPreprocessor',
|
||||
'\\.(jpg|png|gif|svg)$': './node_modules/@ant-design/tools/lib/jest/imagePreprocessor',
|
||||
},
|
||||
testRegex: 'demo\\.test\\.js$',
|
||||
testRegex: 'demo\\.test\\.(j|t)s$',
|
||||
testEnvironment: 'node',
|
||||
transformIgnorePatterns,
|
||||
snapshotSerializers: ['enzyme-to-json/serializer'],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsConfigFile: './tsconfig.test.json',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
~*
|
||||
dist/report.html
|
||||
9
.remarkrc.js
Normal file
9
.remarkrc.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const config = {
|
||||
plugins: [
|
||||
'remark-preset-lint-recommended',
|
||||
['remark-lint-list-item-indent', 'space'],
|
||||
['remark-lint-no-literal-urls', false],
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
@@ -1010,7 +1010,6 @@ zytjs <yitongzhao@163.com>
|
||||
郭延豪(708674) <gyh9457@163.com>
|
||||
愚指导-TZ <yutingzhao1991@sina.com>
|
||||
杨小事er <Uiryzd@163.com>
|
||||
杨小事er <uiryzd@163.com>
|
||||
超能刚哥 <margox@foxmail.com>
|
||||
马金花儿 <o.o@mug.dog>
|
||||
रोहन मल्होत्रा <rohan.malhotra@adwyze.com>
|
||||
|
||||
@@ -15,8 +15,327 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 4.3.0
|
||||
|
||||
`2020-05-31`
|
||||
|
||||
- 🔥 Rewrite Tabs for better user experience. [#24552](https://github.com/ant-design/ant-design/pull/24552)
|
||||
- Upload
|
||||
- 🐞 Fix delete icon cannot be navigate via keyboard. [#24604](https://github.com/ant-design/ant-design/pull/24604) [@morenyang](https://github.com/morenyang)
|
||||
- 🆕 `data` could return `Promise` now. [#24546](https://github.com/ant-design/ant-design/pull/24546) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🐞 Fix progress bar override by accident. [#24339](https://github.com/ant-design/ant-design/pull/24339) [@morenyang](https://github.com/morenyang)
|
||||
- 🆕 Support `progress` to customize progress bar. [#24319](https://github.com/ant-design/ant-design/pull/24319) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 Fix Steps `subtitle` transition style. [#24593](https://github.com/ant-design/ant-design/pull/24593)
|
||||
- Table
|
||||
- 🆕 Table support `rowSelection.hideSelectAll` to hide selectAll checkbox. [#24592](https://github.com/ant-design/ant-design/pull/24592) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 `ellipsis` support `showTitle` to config `title` show. [#24056](https://github.com/ant-design/ant-design/pull/24056) [@lijinke666](https://github.com/lijinke666)
|
||||
- 🆕 Table `columns` support `shouldCellUpdate`. [#23872](https://github.com/ant-design/ant-design/pull/23872)
|
||||
- 🐞 Fix List warning about`React does not recognize colStyle prop`. [#24568](https://github.com/ant-design/ant-design/pull/24568)
|
||||
- 🐞 Fix Progress with `steps` don't update `percent` expectedly. [#24534](https://github.com/ant-design/ant-design/pull/24534) [@ChuckJonas](https://github.com/ChuckJonas)
|
||||
- Input
|
||||
- 🐞 Fix Input.Password still show `value` attribute in DOM after blur it. [#24535](https://github.com/ant-design/ant-design/pull/24535)
|
||||
- 🆕 Input.Passowrd support custom icon. [#23792](https://github.com/ant-design/ant-design/pull/23792) [@偏右](https://github.com/偏右)
|
||||
- 💄 Add less variable `@input-disabled-color`. [#23775](https://github.com/ant-design/ant-design/pull/23775) [@alwaysloseall](https://github.com/alwaysloseall)
|
||||
- Form
|
||||
- 🐞 Fix Form.Item inline label collapsed when in narrow space. [#24531](https://github.com/ant-design/ant-design/pull/24531)
|
||||
- 🐞 Fix Form.List field status sync logic and add a nest fields demo. [#24009](https://github.com/ant-design/ant-design/pull/24009)
|
||||
- 🆕 Form support `validateTrigger` to config children fields validate trigger. [#23972](https://github.com/ant-design/ant-design/pull/23972)
|
||||
- 🐞 Fix Cascader expand icon color when disabled. [#24521](https://github.com/ant-design/ant-design/pull/24521)
|
||||
- Menu
|
||||
- 🆕 Adjust text shows the first character when Menu is collapsed in `inline` mode. [#24330](https://github.com/ant-design/ant-design/pull/24330)
|
||||
- 🆕 Menu.Item support `danger` prop. [#23785](https://github.com/ant-design/ant-design/pull/23785)
|
||||
- 🐞 Fix Breadcrumb icon margin missing when using links. [#24490](https://github.com/ant-design/ant-design/pull/24490) [@EscapeB](https://github.com/EscapeB)
|
||||
- Avatar
|
||||
- 🐞 Fix Avatar `onError` trigger twice. [#24506](https://github.com/ant-design/ant-design/pull/24506) [@sanonz](https://github.com/sanonz)
|
||||
- 🆕 Avatar support `gap` to set the unit distance between left and right sides. [#24357](https://github.com/ant-design/ant-design/pull/24357)
|
||||
- 🐞 Fix Alert close icon `padding` style. [#24471](https://github.com/ant-design/ant-design/pull/24471)
|
||||
- 🐞 Fix Tree `@tree-directory-selected-bg` don't work. [#24468](https://github.com/ant-design/ant-design/pull/24468) [@morenyang](https://github.com/morenyang)
|
||||
- Typography
|
||||
- 🆕 Support Typography.Paragraph custom expand style. [#24385](https://github.com/ant-design/ant-design/pull/24385) [@fireairforce](https://github.com/fireairforce)
|
||||
- 🐞 Fix Typography `title` prop support. [#24440](https://github.com/ant-design/ant-design/pull/24440) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 Typography.Text support `keyboard` style. [#24195](https://github.com/ant-design/ant-design/pull/24195)
|
||||
- 🆕 Add Link component. [#24019](https://github.com/ant-design/ant-design/pull/24019)
|
||||
- 🆕 Tooltip support `color` to config background color. [#23155](https://github.com/ant-design/ant-design/pull/23155)
|
||||
- 🆕 Popconfirm can be closed by pressing `ESC` now. [#24420](https://github.com/ant-design/ant-design/pull/24420)
|
||||
- 🆕 Tooltip `destroyTooltipOnHide` support `keepParent` config. [#24362](https://github.com/ant-design/ant-design/pull/24362) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- Button
|
||||
- 💄 Improve button background variable usage. [#24372](https://github.com/ant-design/ant-design/pull/24372) [@morenyang](https://github.com/morenyang)
|
||||
- 🆕 New `type="text"` Button. [#22552](https://github.com/ant-design/ant-design/pull/22552)
|
||||
- 🆕 Notification support to config `prefixCls`. [#24295](https://github.com/ant-design/ant-design/pull/24295) [@tdida](https://github.com/tdida)
|
||||
- 🆕 RangePicker `dateRender` support additional argument to detect is `start` or `end` field. [#24278](https://github.com/ant-design/ant-design/pull/24278)
|
||||
- 🆕 Skeleton add `round` prop to enable paragraph and title show radius. [#24137](https://github.com/ant-design/ant-design/pull/24137) [@xilihuasi](https://github.com/xilihuasi)
|
||||
- 🆕 Transfer support `oneWay` and `pagination`. [#24041](https://github.com/ant-design/ant-design/pull/24041)
|
||||
- 💄 Descriptions add less variables `@descriptions-item-trailing-colon` and etc. [#24032](https://github.com/ant-design/ant-design/pull/24032) [@hengkx](https://github.com/hengkx)
|
||||
- 🆕 Message Support customize `className` and `style`. [#24024](https://github.com/ant-design/ant-design/pull/24024) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 ConfigProvider support `virtual` and `dropdownMatchSelectWidth`. [#23841](https://github.com/ant-design/ant-design/pull/23841) [@hengkx](https://github.com/hengkx)
|
||||
- 🛠 Optimize dependencies to reduce overall package size. [#24584](https://github.com/ant-design/ant-design/pull/24584)
|
||||
- 🐞 Fix `@ant-prefix` don't work in some styles. [#24459](https://github.com/ant-design/ant-design/pull/24459) [@morenyang](https://github.com/morenyang)
|
||||
- 🌐 Localization
|
||||
- 🇫🇮 Improve Typography `fi_FI` locale. [#24591](https://github.com/ant-design/ant-design/pull/24591) [@sagge](https://github.com/sagge)
|
||||
- 🇧🇷 Improve `pt_BR` locale. [#24518](https://github.com/ant-design/ant-design/pull/24518) [@arturpfb](https://github.com/arturpfb)
|
||||
- 🇬🇧 Improve Form `en_GB` locale. [#24404](https://github.com/ant-design/ant-design/pull/24404) [@morenyang](https://github.com/morenyang)
|
||||
- RTL
|
||||
- 💄 Optimize Tree checkbox style in RTL. [#24563](https://github.com/ant-design/ant-design/pull/24563)
|
||||
- 💄 Optimize Calendar notice content text style in RTL. [#24528](https://github.com/ant-design/ant-design/pull/24528)
|
||||
- 💄 Optimize Table filter dropdown style in RTL. [#24529](https://github.com/ant-design/ant-design/pull/24529)
|
||||
- 💄 Fix Cascader dropdown style in RTL. [#24520](https://github.com/ant-design/ant-design/pull/24520)
|
||||
- TypeScript
|
||||
- Form export RuleObject and RuleRender types. [#24541](https://github.com/ant-design/ant-design/pull/24541) [@sorteam](https://github.com/sorteam)
|
||||
|
||||
## 4.2.5
|
||||
|
||||
`2020-05-25`
|
||||
|
||||
- 🐞 Fix Table selection arrow out of column when `size` is `small/middle`. [#24394](https://github.com/ant-design/ant-design/pull/24394)
|
||||
- 🐞 Fix Input.TextArea clear icon disappears in Input.Group when hover it. [#24360](https://github.com/ant-design/ant-design/pull/24360) [@Mr-jiangzhiguo](https://github.com/Mr-jiangzhiguo)
|
||||
- 🐞 Fixed an issue where the `RowSelection.onChange` will still be cached when the Table removes entries in `dataSource`. [#24338](https://github.com/ant-design/ant-design/pull/24338)
|
||||
- 🐞 Adjust `useNotification` api instance to be same instance for each render. [#24337](https://github.com/ant-design/ant-design/pull/24337)
|
||||
- 🐞 Fix Button `loading` transition animation missing and Modal `confirmLoading` not being reset. [#24328](https://github.com/ant-design/ant-design/pull/24328)
|
||||
- 🐞 Fix Drawer cover background elements when it is not visible. [#24290](https://github.com/ant-design/ant-design/pull/24290)
|
||||
- 🐞 Fix Cascader/Select/Table/TreeSelect text color when data empty. [#24279](https://github.com/ant-design/ant-design/pull/24279)
|
||||
- 💄 Fix InputNumber operation button arrow is not centered. [#24266](https://github.com/ant-design/ant-design/pull/24266)
|
||||
- 🐞 Fix Table with empty array `filteredValue` still highlight the filtered icon. [#24263](https://github.com/ant-design/ant-design/pull/24263)
|
||||
- 🐞 Fix Cascader not support `number[]` value. [#24247](https://github.com/ant-design/ant-design/pull/24247)
|
||||
- ⌨️ Fix Switch `autoFocus` trigger when `disabled` removed. Adjust style to avoid switch shaking. Remove blur logic when `onMouseUp` to improve acessibility. [#24254](https://github.com/ant-design/ant-design/pull/24254)
|
||||
- 💄 Add Menu default `text-align` style. [#24253](https://github.com/ant-design/ant-design/pull/24253)
|
||||
- 🛠 Refactor List code. [#24280](https://github.com/ant-design/ant-design/pull/24280) [@hengkx](https://github.com/hengkx)
|
||||
- 🛠 Modify the Alert with hooks to support strict mode. [#24236](https://github.com/ant-design/ant-design/pull/24236) [@hengkx](https://github.com/hengkx)
|
||||
- 🐞Fix Card perfermance bug when use with `react-split`. [#24425](https://github.com/ant-design/ant-design/pull/24425)
|
||||
- TypeScript
|
||||
- 🛠Cascader ts definition update. [#24393](https://github.com/ant-design/ant-design/pull/24393) [@zhangyu1818](https://github.com/zhangyu1818)
|
||||
- 🐞 Fix TS error of `Could not find a declaration rc-upload`. [#24325](https://github.com/ant-design/ant-design/pull/24325)
|
||||
- 🛠 Add children type to BackTop. [#24235](https://github.com/ant-design/ant-design/pull/24235)
|
||||
|
||||
## 4.2.4
|
||||
|
||||
`2020-05-18`
|
||||
|
||||
- 🐞 Revert Switch patch to fix handle position style issue with `unCheckedChildren`. [#24242](https://github.com/ant-design/ant-design/pull/24242)
|
||||
- 💄 Adjust Upload icon default color to red in error status. [#24160](https://github.com/ant-design/ant-design/pull/24160)
|
||||
- 💄 Adjust Dropdown arrow position a little higher. [#24215](https://github.com/ant-design/ant-design/pull/24215)
|
||||
- 🌐 Form `defaultValidateMessages` support `ru_RU`. [#24219](https://github.com/ant-design/ant-design/pull/24219) [@aivinog1](https://github.com/aivinog1)
|
||||
|
||||
## 4.2.3
|
||||
|
||||
`2020-05-16`
|
||||
|
||||
- 🐞 Refactor `rc-progress` to resolve `h3g is not defined` error in `<script src="antd.min.js" />`. [#24127](https://github.com/ant-design/ant-design/pull/24127)
|
||||
- 📖 Rewrote [Use in create-react-app](https://ant.design/docs/react/use-with-create-react-app). [#24184](https://github.com/ant-design/ant-design/pull/24184)
|
||||
- Drawer
|
||||
- 🐞 Fix Drawer `getContainer={false}` height overflow issue. [#24082](https://github.com/ant-design/ant-design/pull/24082)
|
||||
- 🐞 Fix Drawer `mask={false}` animation not working. [#24082](https://github.com/ant-design/ant-design/pull/24082)
|
||||
- BackTop
|
||||
- 🛠 Refactor BackTop with hooks. [#23575](https://github.com/ant-design/ant-design/pull/23575)
|
||||
- 🐞 Fix BackTop not working in iframe of Chrome. [#24194](https://github.com/ant-design/ant-design/pull/24194)
|
||||
- DatePicker
|
||||
- 🐞 Fix DatePicker with `showToday` not working with `disabledDate`. [#24190](https://github.com/ant-design/ant-design/pull/24190)
|
||||
- 🐞 Fix DatePicker `renderExtraFooter` with long content exceed content width. [#24145](https://github.com/ant-design/ant-design/pull/24145)
|
||||
- Button
|
||||
- 🐞 Fix small Button align issue when customize theme. [#24097](https://github.com/ant-design/ant-design/pull/24097)
|
||||
- 🐞 Fix Button children not working with Tooltip. [#24095](https://github.com/ant-design/ant-design/pull/24095)
|
||||
- 🛠 Refactor Tooltip with hooks. [#23699](https://github.com/ant-design/ant-design/pull/23699)
|
||||
- 🐞 Avoid `disabled` Upload.Dragger being triggered by clicking Form `label`. [#24202](https://github.com/ant-design/ant-design/pull/24202)
|
||||
- 🐞 Fix Select selected option not interactive (such as `title` not working). [#24170](https://github.com/ant-design/ant-design/pull/24170)
|
||||
- 🐞 Fix Switch shake in Safari and iOS Chrome. [#24122](https://github.com/ant-design/ant-design/pull/24122) [@lexlexa](https://github.com/lexlexa)
|
||||
- 🐞 Carousel upgrade to `react-slick@0.26.1` to resolve some problems. [#24067](https://github.com/ant-design/ant-design/pull/24067)
|
||||
- 🐞 Cascader will display `defaultValue` instead of empty string when no matched options. [#24058](https://github.com/ant-design/ant-design/pull/24058) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🌎 Improve `zh_TW` localisations. [#24065](https://github.com/ant-design/ant-design/pull/24065) [@wx1322](https://github.com/wx1322)
|
||||
- 🐞 Fix Table `onChange` pagination type. [#24114](https://github.com/ant-design/ant-design/pull/24114) [@sorteam](https://github.com/sorteam)
|
||||
- 💄 Add less variable `@card-head-extra-color`. [#24189](https://github.com/ant-design/ant-design/pull/24189)
|
||||
- 💄 Adjust Pagination simple mode background to transparent. [#24152](https://github.com/ant-design/ant-design/pull/24152)
|
||||
- 💄 Fix dark Menu link color. [#24110](https://github.com/ant-design/ant-design/pull/24110)
|
||||
- RTL
|
||||
- 💄 Fix Dropdown.Button default menu placement in RTL. [#24150](https://github.com/ant-design/ant-design/pull/24150)
|
||||
- 💄 Fix Menu `border` in RTL. [#24101](https://github.com/ant-design/ant-design/pull/24101)
|
||||
- 💄 Optimize Select multiple tag style in RTL. [#24112](https://github.com/ant-design/ant-design/pull/24112)
|
||||
- 💄 Optimize Typography `expand` style in RTL. [#24084](https://github.com/ant-design/ant-design/pull/24084)
|
||||
- 💄 Optimize Pagination slash style in RTL. [#24154](https://github.com/ant-design/ant-design/pull/24154)
|
||||
|
||||
## 4.2.2
|
||||
|
||||
`2020-05-11`
|
||||
|
||||
- 🐞 Fix `npm run version` install error. [#24059](https://github.com/ant-design/ant-design/pull/24059)
|
||||
- 🐞 Fix Menu `@menu-item-font-size` not working. [#24052](https://github.com/ant-design/ant-design/pull/24052)
|
||||
- 💄 Add `@modal-close-color` less variable. [#24053](https://github.com/ant-design/ant-design/pull/24053)
|
||||
|
||||
## 4.2.1
|
||||
|
||||
`2020-05-11`
|
||||
|
||||
- Form
|
||||
- 🐞 Fix Form.Item get React warning for `getValueProps`. [#23875](https://github.com/ant-design/ant-design/pull/23875)
|
||||
- 🐞 Fix Form.Item `help` style issue when `validateStatus` is not `error`. [#23945](https://github.com/ant-design/ant-design/pull/23945)
|
||||
- Table
|
||||
- 🐞 Fix selection column width issue when fix header. [#23806](https://github.com/ant-design/ant-design/pull/23806)
|
||||
- 💄 Adjust selection column css selector priority to enable customize width. [#23914](https://github.com/ant-design/ant-design/pull/23914)
|
||||
- DatePicker
|
||||
- 🐞 Fix miss placeholder when `placeholder` is `undefined`. [#23818](https://github.com/ant-design/ant-design/pull/23818)
|
||||
- 🐞 Fix clear icon color style. [#23811](https://github.com/ant-design/ant-design/pull/23811)
|
||||
- Switch
|
||||
- 🐞 Fix loading style for the dark theme. [#23766](https://github.com/ant-design/ant-design/pull/23766) [@vsn4ik](https://github.com/vsn4ik)
|
||||
- 🐞 Fix `unCheckedChildren` not showing. [#23791](https://github.com/ant-design/ant-design/pull/23791)
|
||||
- 🐞 Fix Upload error message location to scroll in the float layer. [#24001](https://github.com/ant-design/ant-design/pull/24001) [@mraiguo](https://github.com/mraiguo)
|
||||
- 💄 Tweak Comment render unnecessary div style when `avatar` is empty. [#23994](https://github.com/ant-design/ant-design/pull/23994) [@Xuhao](https://github.com/Xuhao)
|
||||
- 🐞 Fix Select `focus` border style in Input.Group. [#23985](https://github.com/ant-design/ant-design/pull/23985)
|
||||
- 🐞 Fix Steps `subTitle` showing `[object Object]` title. [#23989](https://github.com/ant-design/ant-design/pull/23989)
|
||||
- 💄 Tweak Select close icon position. [#23963](https://github.com/ant-design/ant-design/pull/23963)
|
||||
- 🐞 Fix Drawer `width="50%"` hidden problem when no mask. [#23925](https://github.com/ant-design/ant-design/pull/23925)
|
||||
- 🐞 Fix Textarea with `allowClear` has error height style. [#23835](https://github.com/ant-design/ant-design/pull/23835)
|
||||
- 💄 Adjust Modal.xxx function async to avoid block React events. [#23826](https://github.com/ant-design/ant-design/pull/23826)
|
||||
- 🐞 Fix Menu with controlled `openKeys` abnormal behavior when `inlineCollapsed` changed. [#23822](https://github.com/ant-design/ant-design/pull/23822)
|
||||
- 🐞 Fix Button `loading` animation. [#23783](https://github.com/ant-design/ant-design/pull/23783)
|
||||
- 🐞 Fix Slider `marks` selected problem when dragging. [#23773](https://github.com/ant-design/ant-design/pull/23773)
|
||||
- 🛠 Timeline refactors with React Hooks. [#23631](https://github.com/ant-design/ant-design/pull/23631) [@hengkx](https://github.com/hengkx)
|
||||
- 🌎 Localization
|
||||
- 🇮🇷 Add Farsi `fa_IR` default locale template localisations. [#23926](https://github.com/ant-design/ant-design/pull/23926) [@NarimanMov](https://github.com/NarimanMov)
|
||||
- 🇺🇸 Add default `en` default locale template localisations for Form. [#23859](https://github.com/ant-design/ant-design/pull/23859) [@mjfwebb](https://github.com/mjfwebb)
|
||||
- 📦 Reduce bundle size
|
||||
- 🗑 Reduce bundle size via removing `react-lifecycles-compat`. [#23969](https://github.com/ant-design/ant-design/pull/23969)
|
||||
- 🛠 Reduce bundle size via excluding `package.json` from source code. [#23957](https://github.com/ant-design/ant-design/pull/23957)
|
||||
- 🛠 Upgrade `rc-animate` to 3.x to reduce bundle size. [#23937](https://github.com/ant-design/ant-design/pull/23937)
|
||||
- RTL
|
||||
- 🐞 Fix Input clear icon style in RTL. [#23999](https://github.com/ant-design/ant-design/pull/23999)
|
||||
- 🐞 Fix DatePicker panel style in RTL. [#24028](https://github.com/ant-design/ant-design/pull/24028) [@xrkffgg](https://github.com/xrkffgg)
|
||||
- 💄 Optimize DatePicker active bar style in `RTL`. [#23981](https://github.com/ant-design/ant-design/pull/23981)
|
||||
- 🐞 Fix Transfer search padding style in `RTL`. [#23962](https://github.com/ant-design/ant-design/pull/23962)
|
||||
- 💄 Optimize Layout style of RTL. [#23921](https://github.com/ant-design/ant-design/pull/23921)
|
||||
- 💄 Optimize Button `loading` style in RT. [#23776](https://github.com/ant-design/ant-design/pull/23776)
|
||||
- 💄 Optimize Input.Search style in RTL. [#23797](https://github.com/ant-design/ant-design/pull/23797)
|
||||
- TypeScript
|
||||
- 🐞 Fix InputNumber `onChange` type. [#23871](https://github.com/ant-design/ant-design/pull/23871) [@jjhbw](https://github.com/jjhbw)
|
||||
|
||||
## 4.2.0
|
||||
|
||||
`2020-04-29`
|
||||
|
||||
- 🆕 List `grid` support all column count like 5. [#23630](https://github.com/ant-design/ant-design/pull/23630)
|
||||
- 🆕 Divider add `plain` prop which allows a non-heading style divider text. [#23405](https://github.com/ant-design/ant-design/pull/23405)
|
||||
- 🆕 Typography `ellipsis` support `onEllipsis` event handler. [#23414](https://github.com/ant-design/ant-design/pull/23414)
|
||||
- 🆕 Space support `align` prop. [#23306](https://github.com/ant-design/ant-design/pull/23306)
|
||||
- 🆕 Upload support `isImageUrl` to force trade file as image. [#23248](https://github.com/ant-design/ant-design/pull/23248) [@onjuju](https://github.com/onjuju)
|
||||
- 🆕 Form.Item support `initialValue` and `getValueProps` props. [#22993](https://github.com/ant-design/ant-design/pull/22993)
|
||||
- ConfigProvider
|
||||
- 🆕 ConfigProvider support `getTargetContainer` to config Affix `target` props. [#23751](https://github.com/ant-design/ant-design/pull/23751)
|
||||
- 🆕 ConfigProvider support `input` prop to config Input `autoComplete`. [#23455](https://github.com/ant-design/ant-design/pull/23455)
|
||||
- 🐞 Fix ConfigProvider `getPopupContainer` not working on DatePicker and Slider. [#23594](https://github.com/ant-design/ant-design/pull/23594) [@hengkx](https://github.com/hengkx)
|
||||
- Table
|
||||
- 🆕 Table `summary` support fixed columns. [#23647](https://github.com/ant-design/ant-design/pull/23647)
|
||||
- 🆕 Table support responsive columns. [#23298](https://github.com/ant-design/ant-design/pull/23298) [@vbudovski](https://github.com/vbudovski)
|
||||
- 🐞 Fix Table pagination default position in RTL. [#23747](https://github.com/ant-design/ant-design/pull/23747)
|
||||
- 🐞 Fix Table crash when `pageSize` is `undefined`. [#23724](https://github.com/ant-design/ant-design/pull/23724)
|
||||
- 🐞 fix Table nested margin when size is `small` or `middle`. [#23602](https://github.com/ant-design/ant-design/pull/23602) [@hengkx](https://github.com/hengkx)
|
||||
- 🐞 Fix RangePicker `ranges` tag color to primary color. [#23705](https://github.com/ant-design/ant-design/pull/23705)
|
||||
- 🐞 Fix Transfer with custom empty style issue. [#23694](https://github.com/ant-design/ant-design/pull/23694) [@hengkx](https://github.com/hengkx)
|
||||
- Input
|
||||
- 🐞 Fix Password caret position. [#23633](https://github.com/ant-design/ant-design/pull/23633) [@huntdream](https://github.com/huntdream)
|
||||
- 💄 Adjust Input.Search icon style. [#23406](https://github.com/ant-design/ant-design/pull/23406)
|
||||
- Button
|
||||
- 🐞 Fix Button align problem of icon only. [#23671](https://github.com/ant-design/ant-design/pull/23671)
|
||||
- 🐞 Fix Button of icon only wrong `loading` style. [#23614](https://github.com/ant-design/ant-design/pull/23614)
|
||||
- 🐞 fix Button cannot be directly called by `react-dnd`. [#23571](https://github.com/ant-design/ant-design/pull/23571) [@hengkx](https://github.com/hengkx)
|
||||
- Menu
|
||||
- 🆕 Menu Item and SubMenu support `icon` prop. [#23629](https://github.com/ant-design/ant-design/pull/23629)
|
||||
- 🐞 Fix Menu duplicated shadow style. [#23664](https://github.com/ant-design/ant-design/pull/23664)
|
||||
- 🐞 Fix Tag cannot be directly called by `react-dnd`. [#23632](https://github.com/ant-design/ant-design/pull/23632) [@hengkx](https://github.com/hengkx)
|
||||
- Anchor
|
||||
- 🐞 Fix Anchor Link with multiple `#` can not jump correctly. [#23595](https://github.com/ant-design/ant-design/pull/23595) [@wuzekang](https://github.com/wuzekang)
|
||||
- 🐞 Fix Input with `suffix` align problem. [#23606](https://github.com/ant-design/ant-design/pull/23606)
|
||||
- 💄 Select arrow won't rotate when open. [#23468](https://github.com/ant-design/ant-design/pull/23468)
|
||||
- 💄 Rate support `direction`. [#23321](https://github.com/ant-design/ant-design/pull/23321)
|
||||
- 💄 Adjust font-size in compact mode. [#23135](https://github.com/ant-design/ant-design/pull/23135)
|
||||
- RTL
|
||||
- 💄 Optimize Result button style in RTL. [#23733](https://github.com/ant-design/ant-design/pull/23733)
|
||||
- 💄 Add Divider RTL support. [#23734](https://github.com/ant-design/ant-design/pull/23734)
|
||||
- 💄 Fix Alert style in RTL when no-icon. [#23714](https://github.com/ant-design/ant-design/pull/23714)
|
||||
- 💄 Optimize Table expand animation and pagination style in RTL. [#23706](https://github.com/ant-design/ant-design/pull/23706)
|
||||
- 💄 Fix Table filter dropdown position in RTL. [#23695](https://github.com/ant-design/ant-design/pull/23695)
|
||||
- 💄 Fix Table rowSelect icon style in RTL. [#23690](https://github.com/ant-design/ant-design/pull/23690)
|
||||
- 💄 Optimize List style in RTL. [#23676](https://github.com/ant-design/ant-design/pull/23676)
|
||||
- 💄 Add Calendar RTL. [#23394](https://github.com/ant-design/ant-design/pull/23394)
|
||||
- 💄 Optimize Input.Search style in RTL. [#23424](https://github.com/ant-design/ant-design/pull/23424)
|
||||
- 💄 Add Notification RTL config. [#23185](https://github.com/ant-design/ant-design/pull/23185)
|
||||
- TypeScript
|
||||
- 🐞 Fix PageHeader `tag` definition. [#23712](https://github.com/ant-design/ant-design/pull/23712) [@hengkx](https://github.com/hengkx)
|
||||
- 🗑 Remove Button deprecated `type="danger"` TypeScript definition and warn it. [#23709](https://github.com/ant-design/ant-design/pull/23709)
|
||||
- 🐞 Fix Table pagination `position` definition. [#23681](https://github.com/ant-design/ant-design/pull/23681) [@hengkx](https://github.com/hengkx)
|
||||
|
||||
## 4.1.5
|
||||
|
||||
`2020-04-25`
|
||||
|
||||
- 🐞 Fix Button.Group align style. [#23590](https://github.com/ant-design/ant-design/pull/23590)
|
||||
- 🐞 Fix Select cannot trigger open by clicking arrow icon. [#23448](https://github.com/ant-design/ant-design/pull/23448)
|
||||
- 🐞 Fix Form fields shake when `@form-item-margin-bottom` is customize and switching the validing info. [#23436](https://github.com/ant-design/ant-design/pull/23436) [@yoyo837](https://github.com/yoyo837)
|
||||
- 🐞 Fix the first Divider render differently with others. [#23438](https://github.com/ant-design/ant-design/pull/23438)
|
||||
- 🐞 Fix nest ConfigProvider missing `prefixCls` value. [#23423](https://github.com/ant-design/ant-design/pull/23423)
|
||||
- 🐞 Fix Carousel tabbed Radio/Checkbox to non-active slide. [#23380](https://github.com/ant-design/ant-design/pull/23380)
|
||||
- 🐞 Fix Tree with virtual scroll frozen by quick `loadData`. [#23581](https://github.com/ant-design/ant-design/pull/23581)
|
||||
- 🐞 Fix Steps style in IE11 when direction is vertical. [#23561](https://github.com/ant-design/ant-design/pull/23561) [@AdrianoRuberto](https://github.com/AdrianoRuberto)
|
||||
- 🐞 Fix Input.Search height affected by `suffix` and `react key` warning. [#23527](https://github.com/ant-design/ant-design/pull/23527)
|
||||
- 🐞 Fix Menu behavior when hover on submenu gap. [#23511](https://github.com/ant-design/ant-design/pull/23511)
|
||||
- 🐞 Fix Tree custom icon missing when node is loading data. [#23494](https://github.com/ant-design/ant-design/pull/23494)
|
||||
- RTL
|
||||
- 🐞 Fix Alert RTL style when set both `showIcon` and `closable`. [#23526](https://github.com/ant-design/ant-design/pull/23526)
|
||||
- 🐞 Fix Button RTL style when loading. [#23399](https://github.com/ant-design/ant-design/pull/23399)
|
||||
- 🐞 Fix Collapse that icon position is incorrect in RTL. [#23445](https://github.com/ant-design/ant-design/pull/23445)
|
||||
- 🐞 Fix Select group label style in RTL. [#23404](https://github.com/ant-design/ant-design/pull/23404)
|
||||
- 🐞 Fix Statistic RTL style. [#23397](https://github.com/ant-design/ant-design/pull/23397)
|
||||
- TypeScript
|
||||
- 🐞 Fix type definition of `selections` for Table. [#23462](https://github.com/ant-design/ant-design/pull/23462) [@xiaoxintang](https://github.com/xiaoxintang)
|
||||
|
||||
## 4.1.4
|
||||
|
||||
`2020-04-18`
|
||||
|
||||
- 🐞 Fix dark theme and compact theme not working. [#23243](https://github.com/ant-design/ant-design/pull/23243)
|
||||
- 🐞 Fix Modal.info executed only once when has argument. [#23360](https://github.com/ant-design/ant-design/pull/23360)
|
||||
- 🐞 Fix Dropdown submenu background missing. [#23296](https://github.com/ant-design/ant-design/pull/23296)
|
||||
- 💄 Optimize PageHeader responsive behavior. [#23277](https://github.com/ant-design/ant-design/pull/23277)
|
||||
- 🐞 Fix TreeSelect render blank in compact mode. [#23231](https://github.com/ant-design/ant-design/pull/23231)
|
||||
- 🛎 Fix Checkbox and Switch console warning typo (validate -> a valid). [#23240](https://github.com/ant-design/ant-design/pull/23240) [@evancharlton](https://github.com/evancharlton)
|
||||
- 🐞 Fix Table `rowSelection` params issue when `childrenColumnName` configured. [#23205](https://github.com/ant-design/ant-design/pull/23205)
|
||||
- Input
|
||||
- 🐞 Fix Input `type="color"` height issue. [#23351](https://github.com/ant-design/ant-design/pull/23351)
|
||||
- 🐞 Fix Input width shaking when trigger clear icon. [#23259](https://github.com/ant-design/ant-design/pull/23259)
|
||||
- 🐞 Fix Input.Search `size` not affected by ConfigProvider `componentSize`. [#23331](https://github.com/ant-design/ant-design/pull/23331)
|
||||
- Select
|
||||
- 🐞 Fix multiple Select show remove icon when `disabled`. [#23295](https://github.com/ant-design/ant-design/pull/23295)
|
||||
- 🐞 Fix Select custom `suffixIcon` cannot be access. [#23274](https://github.com/ant-design/ant-design/pull/23274)
|
||||
- 🐞 Fix Select search input caret missing in Collapse. [#23250](https://github.com/ant-design/ant-design/pull/23250)
|
||||
- Globalization
|
||||
- 🇨🇳 Form validation messages support internalization and add zh_CN locale. [#23165](https://github.com/ant-design/ant-design/pull/23165) [@hengkx](https://github.com/hengkx)
|
||||
- 🌐 Add missing translations in he_IL. [#23302](https://github.com/ant-design/ant-design/pull/23302) [@MishaKav](https://github.com/MishaKav)
|
||||
- 🌐 Add missing translations in ru_RU. [#23303](https://github.com/ant-design/ant-design/pull/23303) [@MishaKav](https://github.com/MishaKav)
|
||||
- TypeScript
|
||||
- 🔷 Form.Item type upgrade. [#22962](https://github.com/ant-design/ant-design/pull/22962) [@fa93hws](https://github.com/fa93hws)
|
||||
- 🔷 Tree type upgrade. [#23348](https://github.com/ant-design/ant-design/pull/23348) [@yoyo837](https://github.com/yoyo837)
|
||||
- 🐞 Pass `popupClassName` prop to `rc-picker`. [#23214](https://github.com/ant-design/ant-design/pull/23214) [@tanmoyopenroot](https://github.com/tanmoyopenroot)
|
||||
- RTL
|
||||
- 💄 Fix Select RTL style. [#23235](https://github.com/ant-design/ant-design/pull/23235)
|
||||
- 💄 Fix Menu RTL style. [#23319](https://github.com/ant-design/ant-design/pull/23319)
|
||||
|
||||
## 4.1.3
|
||||
|
||||
`2020-04-13`
|
||||
|
||||
- 💄 Adjust Form.Item `label` height style in vertical layout. [#23192](https://github.com/ant-design/ant-design/pull/23192)
|
||||
- 🐞 Fix `Variable is undefined` when importing dark or compact theme and provide a `getThemeVariables` methold for getting theme variables easily. [#23171](https://github.com/ant-design/ant-design/pull/23171)
|
||||
- 🐞 Fix PageHeader style breaks when `title` is too long and improve it's responsive design. [#23133](https://github.com/ant-design/ant-design/pull/23133)
|
||||
- Tabs
|
||||
- 🐞 Fix Tabs `@tabs-card-height` less variable not working. [#23168](https://github.com/ant-design/ant-design/pull/23168)
|
||||
- 🐞 Fix Tabs cannot be displayed in Safari 13. [#23151](https://github.com/ant-design/ant-design/pull/23151) [@imhxc](https://github.com/imhxc)
|
||||
- Table
|
||||
- 🐞 Fix Table fixed columns cannot pin in Safari 12. [#23161](https://github.com/ant-design/ant-design/pull/23161)
|
||||
- 🐞 Fix Table `summary` padding in small size. [#23140](https://github.com/ant-design/ant-design/pull/23140) [@someyoungideas](https://github.com/someyoungideas)
|
||||
- 🐞 Fix Select align style with different size. [#23160](https://github.com/ant-design/ant-design/pull/23160)
|
||||
- 🐞 Fix RangePicker under Input.Group style issue. [#23149](https://github.com/ant-design/ant-design/pull/23149)
|
||||
- 🐞 Fix Pagination missing TypeScript definition of `showTitle`. [#23144](https://github.com/ant-design/ant-design/pull/23144) [@DongchengWang](https://github.com/DongchengWang)
|
||||
|
||||
## 4.1.2
|
||||
|
||||
`2020-04-10`
|
||||
|
||||
- Menu
|
||||
- 🐞 Fix Menu SubMenu background in dark mode. [#22981](https://github.com/ant-design/ant-design/pull/22981) [@AshoneA](https://github.com/AshoneA)
|
||||
- 🐞 Fix long SubMenu title being overlayed by arrow icon. [#23028](https://github.com/ant-design/ant-design/pull/23028) [@wwyx778](https://github.com/wwyx778)
|
||||
@@ -52,6 +371,8 @@ timeline: true
|
||||
|
||||
## 4.1.1
|
||||
|
||||
`2020-04-05`
|
||||
|
||||
- 🐞 Fix Tabs panel focus outline style. [#22752](https://github.com/ant-design/ant-design/pull/22752) [@MrHeer](https://github.com/MrHeer)
|
||||
- 🐞 Fix Input affix with popup element can not get click focus. [#22887](https://github.com/ant-design/ant-design/pull/22887)
|
||||
- Table
|
||||
|
||||
@@ -15,8 +15,327 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 4.3.0
|
||||
|
||||
`2020-05-31`
|
||||
|
||||
- 🔥 重做 Tabs 以提升多标签在不同环境下的用户体验。[#24552](https://github.com/ant-design/ant-design/pull/24552)
|
||||
- Upload
|
||||
- 🐞 解决删除图标键盘无法导航操作的问题。[#24604](https://github.com/ant-design/ant-design/pull/24604) [@morenyang](https://github.com/morenyang)
|
||||
- 🆕 `data` 属性支持返回 `Promise`。[#24546](https://github.com/ant-design/ant-design/pull/24546) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🐞 修复的进度条类型会被意外覆盖的问题。[#24339](https://github.com/ant-design/ant-design/pull/24339) [@morenyang](https://github.com/morenyang)
|
||||
- 🆕 添加 `progress` 属性以支持自定义进度条。[#24319](https://github.com/ant-design/ant-design/pull/24319) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 修复 Steps `subtitle` hover 渐变过渡。[#24593](https://github.com/ant-design/ant-design/pull/24593)
|
||||
- Table
|
||||
- 🆕 Table 新增 `rowSelection.hideSelectAll` 用于隐藏全选框。[#24592](https://github.com/ant-design/ant-design/pull/24592) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 `ellipsis` 支持 `showTitle` 以关闭自动设置 `title` 属性。[#24056](https://github.com/ant-design/ant-design/pull/24056) [@lijinke666](https://github.com/lijinke666)
|
||||
- 🆕 Table `columns` 支持 `shouldCellUpdate` 属性。[#23872](https://github.com/ant-design/ant-design/pull/23872)
|
||||
- 🐞 修复 List 报 `React does not recognize colStyle prop` 的问题。[#24568](https://github.com/ant-design/ant-design/pull/24568)
|
||||
- 🐞 修复步骤 Progress `percent` 样式未正确更新的问题。[#24534](https://github.com/ant-design/ant-design/pull/24534) [@ChuckJonas](https://github.com/ChuckJonas)
|
||||
- Input
|
||||
- 🐞 修复 Input.Password 一个明文显示 `value` 的问题。[#24535](https://github.com/ant-design/ant-design/pull/24535)
|
||||
- 🆕 Input.Passowrd 支持自定义图标。[#23792](https://github.com/ant-design/ant-design/pull/23792) [@偏右](https://github.com/偏右)
|
||||
- 💄 添加 `@input-disabled-color` less 变量。[#23775](https://github.com/ant-design/ant-design/pull/23775) [@alwaysloseall](https://github.com/alwaysloseall)
|
||||
- Form
|
||||
- 🐞 修复 Form.Item 内联样式下 label 在狭窄空间被挤压的问题。[#24531](https://github.com/ant-design/ant-design/pull/24531)
|
||||
- 🐞 修复 Form.List 字段状态同步逻辑并添加嵌套字段示例。[#24009](https://github.com/ant-design/ant-design/pull/24009)
|
||||
- 🆕 Form 添加 `validateTrigger` 支持全局设置子字段校验时机。[#23972](https://github.com/ant-design/ant-design/pull/23972)
|
||||
- 🐞 修复 Cascader 下拉框中扩展按钮在禁用时的颜色。[#24521](https://github.com/ant-design/ant-design/pull/24521)
|
||||
- Menu
|
||||
- 🆕 调整 Menu `inline` 模式下未设置 icon 的菜单收起时文字显示第一个字符。[#24330](https://github.com/ant-design/ant-design/pull/24330)
|
||||
- 🆕 Menu.Item 支持 `danger` 属性。[#23785](https://github.com/ant-design/ant-design/pull/23785)
|
||||
- 🐞 修复 Breadcrumb 内使用链接时图标间距丢失的问题。[#24490](https://github.com/ant-design/ant-design/pull/24490) [@EscapeB](https://github.com/EscapeB)
|
||||
- Avatar
|
||||
- 🐞 修复 Avatar `onError` 会触发两次的问题。[#24506](https://github.com/ant-design/ant-design/pull/24506) [@sanonz](https://github.com/sanonz)
|
||||
- 🆕 Avatar 新增 `gap` 来设置字符类型距离左右两侧边界单位像素。[#24357](https://github.com/ant-design/ant-design/pull/24357)
|
||||
- 🐞 修复 Alert 关闭按钮 `padding` 样式。[#24471](https://github.com/ant-design/ant-design/pull/24471)
|
||||
- 🐞 修复 Tree `@tree-directory-selected-bg` 变量不生效的问题。[#24468](https://github.com/ant-design/ant-design/pull/24468) [@morenyang](https://github.com/morenyang)
|
||||
- Typography
|
||||
- 🆕 Typography.Paragraph 支持自定义展开样式。[#24385](https://github.com/ant-design/ant-design/pull/24385) [@fireairforce](https://github.com/fireairforce)
|
||||
- 🐞 修复 Typography 不支持 `title` 属性的问题。[#24440](https://github.com/ant-design/ant-design/pull/24440) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 Typography.Text 支持 `keyboard` 样式。[#24195](https://github.com/ant-design/ant-design/pull/24195)
|
||||
- 🆕 添加 Link 组件。[#24019](https://github.com/ant-design/ant-design/pull/24019)
|
||||
- 🆕 Tooltip 支持配置背景颜色。[#23155](https://github.com/ant-design/ant-design/pull/23155)
|
||||
- 🆕 Popconfirm 支持按 `ESC` 关闭。[#24420](https://github.com/ant-design/ant-design/pull/24420)
|
||||
- 🆕 Tooltip `destroyTooltipOnHide` 支持 `keepParent` 配置。[#24362](https://github.com/ant-design/ant-design/pull/24362) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- Button
|
||||
- 💄 优化 Button 背景 less 变量的影响范围。[#24372](https://github.com/ant-design/ant-design/pull/24372) [@morenyang](https://github.com/morenyang)
|
||||
- 🆕 新增文本类型按钮 `type="text"`。[#22552](https://github.com/ant-design/ant-design/pull/22552)
|
||||
- 🆕 Notification 支持全局配置 `prefixCls`。[#24295](https://github.com/ant-design/ant-design/pull/24295) [@tdida](https://github.com/tdida)
|
||||
- 🆕 RangePicker `dateRender` 支持额外参数来判断是 `start` 还是 `end` 字段。[#24278](https://github.com/ant-design/ant-design/pull/24278)
|
||||
- 🆕 Skeleton 添加 `round` 属性,允许段落和标题显示圆角。[#24137](https://github.com/ant-design/ant-design/pull/24137) [@xilihuasi](https://github.com/xilihuasi)
|
||||
- 🆕 Transfer 支持 `oneWay` 配置单向选择以及 `pagination` 配置分页。[#24041](https://github.com/ant-design/ant-design/pull/24041)
|
||||
- 💄 Descriptions 新增 `@descriptions-item-trailing-colon` 等 less 变量。[#24032](https://github.com/ant-design/ant-design/pull/24032) [@hengkx](https://github.com/hengkx)
|
||||
- 🆕 Message 支持自定义样式通过使用`className`和`style`。[#24024](https://github.com/ant-design/ant-design/pull/24024) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 ConfigProvider 支持 `virtual` 和 `dropdownMatchSelectWidth` 配置。[#23841](https://github.com/ant-design/ant-design/pull/23841) [@hengkx](https://github.com/hengkx)
|
||||
- 🛠 优化依赖以减少总体打包尺寸。[#24584](https://github.com/ant-design/ant-design/pull/24584)
|
||||
- 🐞 修复 `@ant-prefix` 变量在部分样式里不生效的问题。[#24459](https://github.com/ant-design/ant-design/pull/24459) [@morenyang](https://github.com/morenyang)
|
||||
- 🌐 国际化
|
||||
- 🇫🇮 改进 Typography `fi_FI` 国际化。[#24591](https://github.com/ant-design/ant-design/pull/24591) [@sagge](https://github.com/sagge)
|
||||
- 🇧🇷 改进 `pt_BR` 国际化。[#24518](https://github.com/ant-design/ant-design/pull/24518) [@arturpfb](https://github.com/arturpfb)
|
||||
- 🇬🇧 改进 Form `en_GB` 国际化。[#24404](https://github.com/ant-design/ant-design/pull/24404) [@morenyang](https://github.com/morenyang)
|
||||
- RTL
|
||||
- 💄 优化 Tree RTL 模式下选项框样式。[#24563](https://github.com/ant-design/ant-design/pull/24563)
|
||||
- 💄 优化 Calendar 通知事项文字在 RTL 模式下的样式。[#24528](https://github.com/ant-design/ant-design/pull/24528)
|
||||
- 💄 优化 Table 筛选下拉框在 RTL 模式下样式。[#24529](https://github.com/ant-design/ant-design/pull/24529)
|
||||
- 💄 优化 Cascader RTL 模式下拉框的样式。[#24520](https://github.com/ant-design/ant-design/pull/24520)
|
||||
- TypeScript
|
||||
- Form 导出 RuleObject 与 RuleRender 定义。[#24541](https://github.com/ant-design/ant-design/pull/24541) [@sorteam](https://github.com/sorteam)
|
||||
|
||||
## 4.2.5
|
||||
|
||||
`2020-05-25`
|
||||
|
||||
- 🐞 修复 Table 在 `dataSource` 移除条目时,`rowSelection.onChange` 仍然会缓存的问题。[#24338](https://github.com/ant-design/ant-design/pull/24338)
|
||||
- 🐞 修复 Table 的选中箭头在 `size=small/middle` 时超出的问题。[#24394](https://github.com/ant-design/ant-design/pull/24394)
|
||||
- 🐞 修复 Input.Group 内 Input.TextArea `hover` 时清除图标消失的问题。[#24360](https://github.com/ant-design/ant-design/pull/24360) [@Mr-jiangzhiguo](https://github.com/Mr-jiangzhiguo)
|
||||
- 🐞 修复 Notificiation 使用 `useNotificiation` 时无限 render 的行为。[#24337](https://github.com/ant-design/ant-design/pull/24337)
|
||||
- 🐞 修复 Button `loading` 切换动画丢失和 Modal `confirmLoading` 按钮未复位的问题。[#24328](https://github.com/ant-design/ant-design/pull/24328)
|
||||
- 🐞 修复 Drawer 关闭后依然会遮挡页面元素的问题。[#24290](https://github.com/ant-design/ant-design/pull/24290)
|
||||
- 🐞 修复 Cascader/Select/Table/TreeSelect 空数据时字体的颜色。[#24279](https://github.com/ant-design/ant-design/pull/24279)
|
||||
- 💄 优化 InputNumber 操作按钮居中样式。[#24266](https://github.com/ant-design/ant-design/pull/24266)
|
||||
- 🐞 修复 Table 在 `filteredValue` 使用空数组时仍然会高亮过滤图标的问题。[#24263](https://github.com/ant-design/ant-design/pull/24263)
|
||||
- 🐞 修复 Cascader 不支持 `number[]` 类型 `value` 的问题。[#24247](https://github.com/ant-design/ant-design/pull/24247)
|
||||
- ⌨️ 修复 Switch `autoFocus` 在 `disabled` 移除后会触发的问题,调整样式以避免切换时额外的抖动,并移除鼠标点击失焦逻辑以提升无障碍体验。[#24254](https://github.com/ant-design/ant-design/pull/24254)
|
||||
- 💄 增加 Menu 默认 `text-align` 样式定义以修复被外部样式影响的问题。[#24253](https://github.com/ant-design/ant-design/pull/24253)
|
||||
- 🛠 用 hooks 重构 List。[#24280](https://github.com/ant-design/ant-design/pull/24280) [@hengkx](https://github.com/hengkx)
|
||||
- 🛠 用 hooks 重构 Alert 以支持严格模式。[#24236](https://github.com/ant-design/ant-design/pull/24236) [@hengkx](https://github.com/hengkx)
|
||||
- 🐞 修复 Card 和 `react-split` 一起使用时卡顿的问题。[#24425](https://github.com/ant-design/ant-design/pull/24425)
|
||||
- TypeScript
|
||||
- 🛠 优化 Cascader 的 TypeScript 定义。[#24393](https://github.com/ant-design/ant-design/pull/24393) [@zhangyu1818](https://github.com/zhangyu1818)
|
||||
- 🐞 修复 Upload TypeScript 报错:`Could not find a declaration rc-upload` 的问题。[#24325](https://github.com/ant-design/ant-design/pull/24325)
|
||||
- 🛠 BackTop 增加 `children` 定义。[#24235](https://github.com/ant-design/ant-design/pull/24235)
|
||||
|
||||
## 4.2.4
|
||||
|
||||
`2020-05-18`
|
||||
|
||||
- 🐞 回滚 Switch 以修复配置 `unCheckedChildren` 时,控制点位置样式问题。[#24242](https://github.com/ant-design/ant-design/pull/24242)
|
||||
- 💄 调整 Upload 错误状态图标的颜色默认为红色。[#24160](https://github.com/ant-design/ant-design/pull/24160)
|
||||
- 💄 向上微调 Dropdown 箭头位置。[#24215](https://github.com/ant-design/ant-design/pull/24215)
|
||||
- 🌐 Form `defaultValidateMessages` 支持 `ru_RU`。[#24219](https://github.com/ant-design/ant-design/pull/24219) [@aivinog1](https://github.com/aivinog1)
|
||||
|
||||
## 4.2.3
|
||||
|
||||
`2020-05-16`
|
||||
|
||||
- 🐞 重构 `rc-progress` 以解决 `<script src="antd.min.js" />` 会抛出 `h3g is not defined` 的问题。[#24127](https://github.com/ant-design/ant-design/pull/24127)
|
||||
- 📖 重写了 [在 create-react-app 中使用](https://ant.design/docs/react/use-with-create-react-app-cn)。[#24184](https://github.com/ant-design/ant-design/pull/24184)
|
||||
- Drawer
|
||||
- 🐞 修复 Drawer `getContainer={false}` 时的高度问题。[#24082](https://github.com/ant-design/ant-design/pull/24082)
|
||||
- 🐞 修复 Drawer `mask={false}` 时隐藏动画不生效的问题。[#24082](https://github.com/ant-design/ant-design/pull/24082)
|
||||
- BackTop
|
||||
- 🛠 BackTop 使用 hooks 重构。[#23575](https://github.com/ant-design/ant-design/pull/23575)
|
||||
- 🐞 修复 BackTop 在 Chrome 的 iframe 里不生效的问题。[#24194](https://github.com/ant-design/ant-design/pull/24194)
|
||||
- DatePicker
|
||||
- 🐞 修复 DatePicker `disabledDate` 不会作用到 `showToday` 上的问题。[#24190](https://github.com/ant-design/ant-design/pull/24190)
|
||||
- 🐞 修复 DatePicker `renderExtraFooter` 内容过长超出容器宽度的问题。[#24145](https://github.com/ant-design/ant-design/pull/24145)
|
||||
- Button
|
||||
- 🐞 修复 Button 内图标无法使用 Tooltip 的问题。[#24095](https://github.com/ant-design/ant-design/pull/24095)
|
||||
- 🐞 修复定制主题时小号 Button 错位的问题。[#24097](https://github.com/ant-design/ant-design/pull/24097)
|
||||
- 🛠 Tooltip 使用 hooks 重构。[#23699](https://github.com/ant-design/ant-design/pull/23699)
|
||||
- 🐞 修复 Upload.Dragger 禁用时依然会被 Form `label` 触发的问题。[#24202](https://github.com/ant-design/ant-design/pull/24202)
|
||||
- 🐞 修复 Select 回填选项无法进行交互的问题(如 `title` 不生效)。[#24170](https://github.com/ant-design/ant-design/pull/24170)
|
||||
- 🐞 修复 Switch 在 Safari 和 iOS Chrome 上点击时错位的问题。[#24122](https://github.com/ant-design/ant-design/pull/24122) [@lexlexa](https://github.com/lexlexa)
|
||||
- 🐞 Carousel 更新依赖到 `react-slick@0.26.1` 以修正一些问题。[#24067](https://github.com/ant-design/ant-design/pull/24067)
|
||||
- 🐞 Cascader 没有匹配任何选项时展示 `defaultValue` 而不是空字符串。[#24058](https://github.com/ant-design/ant-design/pull/24058) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🌎 完善繁体中文国际化。[#24065](https://github.com/ant-design/ant-design/pull/24065) [@wx1322](https://github.com/wx1322)
|
||||
- 🐞 修复 Table `onChange` pagination 参数定义。[#24114](https://github.com/ant-design/ant-design/pull/24114) [@sorteam](https://github.com/sorteam)
|
||||
- 💄 新增 less 变量 `@card-head-extra-color`。[#24189](https://github.com/ant-design/ant-design/pull/24189)
|
||||
- 💄 调整 Pagination 简洁模式下按钮的背景色为透明。[#24152](https://github.com/ant-design/ant-design/pull/24152)
|
||||
- 💄 修复暗色 Menu 内的链接颜色。[#24110](https://github.com/ant-design/ant-design/pull/24110)
|
||||
- RTL
|
||||
- 💄 修复 Dropdown.Button 下拉框在 RTL 模式下默认位置。[#24150](https://github.com/ant-design/ant-design/pull/24150)
|
||||
- 💄 优化 Pagination 分隔符在 RTL 下的样式。[#24154](https://github.com/ant-design/ant-design/pull/24154)
|
||||
- 💄 修复 Menu 在 RTL 下的 `border` 样式。[#24101](https://github.com/ant-design/ant-design/pull/24101)
|
||||
- 💄 优化 Select 多选项在 RTL 模式下样式。[#24112](https://github.com/ant-design/ant-design/pull/24112)
|
||||
- 💄 优化 Typography `expand` 在 RTL 下的样式。[#24084](https://github.com/ant-design/ant-design/pull/24084)
|
||||
|
||||
## 4.2.2
|
||||
|
||||
`2020-05-11`
|
||||
|
||||
- 🐞 修复安装 antd `npm run version` 报错的问题。[#24059](https://github.com/ant-design/ant-design/pull/24059)
|
||||
- 🐞 修复 Menu `@menu-item-font-size` 变量失效的问题。[#24052](https://github.com/ant-design/ant-design/pull/24052)
|
||||
- 💄 新增 `@modal-close-color` less 变量。[#24053](https://github.com/ant-design/ant-design/pull/24053)
|
||||
|
||||
## 4.2.1
|
||||
|
||||
`2020-05-11`
|
||||
|
||||
- Form
|
||||
- 🐞 修复 Form.Item 使用 `getValueProps` React 会报警的问题。[#23875](https://github.com/ant-design/ant-design/pull/23875)
|
||||
- 🐞 修复 Form.Item `help` 在 `validateStatus` 不是 `error` 时的样式问题。[#23945](https://github.com/ant-design/ant-design/pull/23945)
|
||||
- Table
|
||||
- 🐞 修复 Table 固定表头时选择列的宽度问题。[#23806](https://github.com/ant-design/ant-design/pull/23806)
|
||||
- 💄 调整 Table 选择列 css 选择器优先级以支持自定义宽度。[#23914](https://github.com/ant-design/ant-design/pull/23914)
|
||||
- DatePicker
|
||||
- 🐞 修复在 `placeholder` 为 `undefined` 时不展示的问题。[#23818](https://github.com/ant-design/ant-design/pull/23818)
|
||||
- 🐞 修复清除图标的颜色。[#23811](https://github.com/ant-design/ant-design/pull/23811)
|
||||
- Switch
|
||||
- 🐞 修复暗色主题下的加载样式。[#23766](https://github.com/ant-design/ant-design/pull/23766) [@vsn4ik](https://github.com/vsn4ik)
|
||||
- 🐞 修复 `unCheckedChildren` 不显示的问题。[#23791](https://github.com/ant-design/ant-design/pull/23791)
|
||||
- 🐞 修复 Upload 在浮层中错误提示滚动定位问题。[#24001](https://github.com/ant-design/ant-design/pull/24001) [@mraiguo](https://github.com/mraiguo)
|
||||
- 💄 调整 Comment 中 `avatar` 为空时不必要的 div 样式[#23994](https://github.com/ant-design/ant-design/pull/23994) [@Xuhao](https://github.com/Xuhao)
|
||||
- 🐞 修复 Input.Group 中 Select 选项 `focus` 边框样式[#23985](https://github.com/ant-design/ant-design/pull/23985)
|
||||
- 🐞 修复 Steps `subTitle` 上会显示 `[object Object]` 提示的问题。[#23989](https://github.com/ant-design/ant-design/pull/23989)
|
||||
- 💄 微调 Select 移除图标的位置。[#23963](https://github.com/ant-design/ant-design/pull/23963)
|
||||
- 🐞 修复无遮罩的 Drawer 设置 `50%` 宽度时不显示的问题。[#23925](https://github.com/ant-design/ant-design/pull/23925)
|
||||
- 🐞 修复 Textarea 开启 `allowClear` 时高度错误的问题。[#23835](https://github.com/ant-design/ant-design/pull/23835)
|
||||
- 💄 调整 Modal.xxx 方法为异步以防止其影响 React 事件响应。[#23826](https://github.com/ant-design/ant-design/pull/23826)
|
||||
- 🐞 修复受控模式 Menu `inlineCollapsed` 折叠时的表现。[#23822](https://github.com/ant-design/ant-design/pull/23822)
|
||||
- 🐞 修复 Button `loading` 动画切换不平滑的问题。[#23783](https://github.com/ant-design/ant-design/pull/23783)
|
||||
- 🐞 修复 Slider 拖拽中选中 `marks` 文本的问题。[#23773](https://github.com/ant-design/ant-design/pull/23773)
|
||||
- 🛠 Timeline 使用 React Hooks 重构。[#23631](https://github.com/ant-design/ant-design/pull/23631) [@hengkx](https://github.com/hengkx)
|
||||
- 🌎 国际化
|
||||
- 🇮🇷 增加波斯语 `fa_IR` 国际化默认提示模板。[#23926](https://github.com/ant-design/ant-design/pull/23926) [@NarimanMov](https://github.com/NarimanMov)
|
||||
- 🇺🇸 增加 Form `en` 国际化默认提示模板[#23859](https://github.com/ant-design/ant-design/pull/23859) [@mjfwebb](https://github.com/mjfwebb)
|
||||
- 📦 包体积优化
|
||||
- 🗑 移除 `react-lifecycles-compat` 依赖以优化包体积。[#23969](https://github.com/ant-design/ant-design/pull/23969)
|
||||
- 🛠 源码中不再引用 `package.json` 从而优化了一点包体积。[#23957](https://github.com/ant-design/ant-design/pull/23957)
|
||||
- 🛠 更新 `rc-animate` 到 3.x 以优化包体积。[#23937](https://github.com/ant-design/ant-design/pull/23937)
|
||||
- RTL
|
||||
- 🐞 修复 Input 在 RTL 模式下清空按钮的样式。[#23999](https://github.com/ant-design/ant-design/pull/23999)
|
||||
- 🐞 修复 DatePicker 下拉框在 RTL 模式下样式。[#24028](https://github.com/ant-design/ant-design/pull/24028) [@xrkffgg](https://github.com/xrkffgg)
|
||||
- 💄 优化 DatePick 在 `RTL` 模式下的激活条样式。[#23981](https://github.com/ant-design/ant-design/pull/23981)
|
||||
- 🐞 修复 Transfer 查询框在 `RTL` 模式下的边距样式。[#23962](https://github.com/ant-design/ant-design/pull/23962)
|
||||
- 💄 优化 Layout RTL 样式。[#23921](https://github.com/ant-design/ant-design/pull/23921)
|
||||
- 💄 优化 Button `loading` 状态在 RTL 下样式。[#23776](https://github.com/ant-design/ant-design/pull/23776)
|
||||
- 💄 优化 Input.Search RTL 样式。[#23797](https://github.com/ant-design/ant-design/pull/23797)
|
||||
- TypeScript
|
||||
- 🐞 修复 InputNumber `onChange` 类型。[#23871](https://github.com/ant-design/ant-design/pull/23871) [@jjhbw](https://github.com/jjhbw)
|
||||
|
||||
## 4.2.0
|
||||
|
||||
`2020-04-29`
|
||||
|
||||
- 🆕 List `grid` 支持所有分栏数字,比如分为 5 栏。[#23630](https://github.com/ant-design/ant-design/pull/23630)
|
||||
- 🆕 Divider 新增 `plain` 属性,可用于设置一个非标题样式的分割文字。[#23405](https://github.com/ant-design/ant-design/pull/23405)
|
||||
- 🆕 Typography `ellipsis` 支持 `onEllipsis` 事件。[#23414](https://github.com/ant-design/ant-design/pull/23414)
|
||||
- 🆕 Space 支持 `align` 属性。[#23306](https://github.com/ant-design/ant-design/pull/23306)
|
||||
- 🆕 Upload 添加 `isImageUrl` 属性以强制将文件作为图标文件。[#23248](https://github.com/ant-design/ant-design/pull/23248) [@onjuju](https://github.com/onjuju)
|
||||
- 🆕 Form.Item 支持 `initialValue` 和 `getValueProps` 属性。[#22993](https://github.com/ant-design/ant-design/pull/22993)
|
||||
- ConfigProvider
|
||||
- 🆕 ConfigProvider 支持 `getTargetContainer` 以配置 Affix `target` 属性。[#23751](https://github.com/ant-design/ant-design/pull/23751)
|
||||
- 🆕 ConfigProvider 添加 `input` 属性以支持全局化配置 Input `autoComplete` 的默认值。[#23455](https://github.com/ant-design/ant-design/pull/23455)
|
||||
- 🐞 修复 ConfigProvider `getPopupContainer` 对 DatePicker 和 Slider 不生效的问题。[#23594](https://github.com/ant-design/ant-design/pull/23594) [@hengkx](https://github.com/hengkx)
|
||||
- Table
|
||||
- 🆕 Table `summary` 支持固定列。[#23647](https://github.com/ant-design/ant-design/pull/23647)
|
||||
- 🆕 Table 支持响应式展现列。[#23298](https://github.com/ant-design/ant-design/pull/23298) [@vbudovski](https://github.com/vbudovski)
|
||||
- 🐞 修复 Table pagination 在 RTL 下默认位置。[#23747](https://github.com/ant-design/ant-design/pull/23747)
|
||||
- 🐞 修复 Table 在 `pageSize` 是 `undefined` 时崩溃的问题。[#23724](https://github.com/ant-design/ant-design/pull/23724)
|
||||
- 🐞 修复 Table 大小为 `small` 和 `middle` 时嵌套表格错位的问题。[#23602](https://github.com/ant-design/ant-design/pull/23602) [@hengkx](https://github.com/hengkx)
|
||||
- 🐞 修正 RangePicker 范围标签的颜色为主色。[#23705](https://github.com/ant-design/ant-design/pull/23705)
|
||||
- 🐞 修复 Transfer 为空自定义图片样式问题。[#23694](https://github.com/ant-design/ant-design/pull/23694) [@hengkx](https://github.com/hengkx)
|
||||
- Input
|
||||
- 🐞 修复 Password 组件输入光标位置。[#23633](https://github.com/ant-design/ant-design/pull/23633) [@huntdream](https://github.com/huntdream)
|
||||
- 💄 调整 Input.Search 的搜索图标样式。[#23406](https://github.com/ant-design/ant-design/pull/23406)
|
||||
- Button
|
||||
- 🐞 修复 Button 图标类型按钮的对齐问题。[#23671](https://github.com/ant-design/ant-design/pull/23671)
|
||||
- 🐞 修复 Button 图标按钮 `loading` 样式错误的问题。[#23614](https://github.com/ant-design/ant-design/pull/23614)
|
||||
- 🐞 解决 Button 无法直接被 `react-dnd` 调用的问题。[#23571](https://github.com/ant-design/ant-design/pull/23571) [@hengkx](https://github.com/hengkx)
|
||||
- Menu
|
||||
- 🆕 Menu Item 和 SubMenu 新增 `icon` 属性。[#23629](https://github.com/ant-design/ant-design/pull/23629)
|
||||
- 🐞 修复 Menu 菜单重复阴影的问题。[#23664](https://github.com/ant-design/ant-design/pull/23664)
|
||||
- 🐞 解决 Tag 无法直接被 `react-dnd` 调用的问题。[#23632](https://github.com/ant-design/ant-design/pull/23632) [@hengkx](https://github.com/hengkx)
|
||||
- Anchor
|
||||
- 🐞 修复 Anchor Link 包含多个 `#` 时无法跳转的问题。[#23595](https://github.com/ant-design/ant-design/pull/23595) [@wuzekang](https://github.com/wuzekang)
|
||||
- 🐞 修复 Input 带 `suffix` 时的元素对齐问题。[#23606](https://github.com/ant-design/ant-design/pull/23606)
|
||||
- 💄 Select 箭头打开时不再翻转。[#23468](https://github.com/ant-design/ant-design/pull/23468)
|
||||
- 💄 新增 Rate 的 `direction` 支持优化。[#23321](https://github.com/ant-design/ant-design/pull/23321)
|
||||
- 💄 调整紧凑模式下默认的字体大小。[#23135](https://github.com/ant-design/ant-design/pull/23135)
|
||||
- RTL
|
||||
- 💄 优化 Result RTL 下按钮样式。[#23733](https://github.com/ant-design/ant-design/pull/23733)
|
||||
- 💄 新增 Divider RTL 支持。[#23734](https://github.com/ant-design/ant-design/pull/23734)
|
||||
- 💄 修复 Alert 在 RTL 下无 icon 的间隔问题。[#23714](https://github.com/ant-design/ant-design/pull/23714)
|
||||
- 💄 优化 Table RTL 模式下扩展按钮动画与分页样式问题。[#23706](https://github.com/ant-design/ant-design/pull/23706)
|
||||
- 💄 修复 Table 筛选下拉框在 RTL 下的位置。[#23695](https://github.com/ant-design/ant-design/pull/23695)
|
||||
- 💄 修复 Table 勾选框图标 RTL 样式。[#23690](https://github.com/ant-design/ant-design/pull/23690)
|
||||
- 💄 优化 List RTL 样式。[#23676](https://github.com/ant-design/ant-design/pull/23676)
|
||||
- 💄 新增 Calendar RTL 支持。[#23394](https://github.com/ant-design/ant-design/pull/23394)
|
||||
- 💄 优化 Input.Search RTL 样式。[#23424](https://github.com/ant-design/ant-design/pull/23424)
|
||||
- 💄 增加 Notification RTL 设置。[#23185](https://github.com/ant-design/ant-design/pull/23185)
|
||||
- TypeScript
|
||||
- 🐞 修复 PageHeader `tag` 属性定义错误。[#23712](https://github.com/ant-design/ant-design/pull/23712) [@hengkx](https://github.com/hengkx)
|
||||
- 🗑 移除已废弃的 Button `type="danger"` TypeScript 定义并增加警告信息。[#23709](https://github.com/ant-design/ant-design/pull/23709)
|
||||
- 🐞 修复 Table pagination `position` Typescript 定义错误。[#23681](https://github.com/ant-design/ant-design/pull/23681) [@hengkx](https://github.com/hengkx)
|
||||
|
||||
## 4.1.5
|
||||
|
||||
`2020-04-25`
|
||||
|
||||
- 🐞 修复 Button.Group 中按钮没有对齐的问题。[#23590](https://github.com/ant-design/ant-design/pull/23590)
|
||||
- 🐞 修复 Select 箭头图标点击无法触发下拉的问题。[#23448](https://github.com/ant-design/ant-design/pull/23448)
|
||||
- 🐞 修复 Form 自定义 `@form-item-margin-bottom` 变量时表单校验抖动的问题。[#23436](https://github.com/ant-design/ant-design/pull/23436) [@yoyo837](https://github.com/yoyo837)
|
||||
- 🐞 修复第一个 Divider 渲染时样式不一致的问题。[#23438](https://github.com/ant-design/ant-design/pull/23438)
|
||||
- 🐞 修复嵌套 ConfigProvider 会丢失 `prefixCls` 值的问题。[#23423](https://github.com/ant-design/ant-design/pull/23423)
|
||||
- 🐞 修复 Carousel 键盘切换到非活跃 slide 上的 Radio/Checkbox 的问题。[#23380](https://github.com/ant-design/ant-design/pull/23380)
|
||||
- 🐞 修复 Tree 使用虚拟滚动时会因为 `loadData` 更新过快而锁死的问题。[#23581](https://github.com/ant-design/ant-design/pull/23581)
|
||||
- 🐞 修复 Steps 组件竖直展示时在 IE11 下样式错误的问题。[#23561](https://github.com/ant-design/ant-design/pull/23561) [@AdrianoRuberto](https://github.com/AdrianoRuberto)
|
||||
- 🐞 修复 Input.Search 高度被 `suffix` 撑高的问题和报 `react key` 重复警告的问题。[#23527](https://github.com/ant-design/ant-design/pull/23527)
|
||||
- 🐞 修复 Menu 鼠标移到缝隙处子菜单会消失的问题。[#23511](https://github.com/ant-design/ant-design/pull/23511)
|
||||
- 🐞 修复 Tree 自定义图标在加载状态下消失的问题。[#23494](https://github.com/ant-design/ant-design/pull/23494)
|
||||
- RTL
|
||||
- 🐞 修复 Alert 在 `showIcon` 和 `closable` 都存在时的 RTL 样式问题。[#23526](https://github.com/ant-design/ant-design/pull/23526)
|
||||
- 🐞 修复 Button 在 RTL 下 loading 样式不正确的问题。[#23399](https://github.com/ant-design/ant-design/pull/23399)
|
||||
- 🐞 修复 Collapse 在 RTL 下切换图标位置不正确的问题。[#23445](https://github.com/ant-design/ant-design/pull/23445)
|
||||
- 🐞 修复 Select 分组名称的 RTL 样式问题。[#23404](https://github.com/ant-design/ant-design/pull/23404)
|
||||
- 🐞 修复 Statistic 的 RTL 样式不正确的问题。[#23397](https://github.com/ant-design/ant-design/pull/23397)
|
||||
- TypeScript
|
||||
- 🐞 修复 Table 的 `selections` 类型定义。[#23462](https://github.com/ant-design/ant-design/pull/23462) [@xiaoxintang](https://github.com/xiaoxintang)
|
||||
|
||||
## 4.1.4
|
||||
|
||||
`2020-04-18`
|
||||
|
||||
- 🐞 修复暗黑主题和紧凑主题不生效的问题。[#23243](https://github.com/ant-design/ant-design/pull/23243)
|
||||
- 🐞 修复 Modal.info 等方法的 `onOk` 函数有参数时只触发一次的问题。[#23360](https://github.com/ant-design/ant-design/pull/23360)
|
||||
- 🐞 修复 Dropdown 弹出菜单背景样式问题。[#23296](https://github.com/ant-design/ant-design/pull/23296)
|
||||
- 💄 优化 PageHeader 的响应式表现。[#23277](https://github.com/ant-design/ant-design/pull/23277)
|
||||
- 🐞 修复紧凑模式下树选择出现空白。[#23231](https://github.com/ant-design/ant-design/pull/23231)
|
||||
- 🛎 修改 Checkbox 和 Switch 中控制台输出的错别字 (validate -> a valid)。[#23240](https://github.com/ant-design/ant-design/pull/23240) [@evancharlton](https://github.com/evancharlton)
|
||||
- 🐞 修复 Table `rowSelection` 在设置 `childrenColumnName` 时事件参数不正确的问题。[#23205](https://github.com/ant-design/ant-design/pull/23205)
|
||||
- Input
|
||||
- 🐞 修复 Input `type="color"` 的高度问题。[#23351](https://github.com/ant-design/ant-design/pull/23351)
|
||||
- 🐞 修复 Input 设置 `allowClear` 内联展示时,触发清除按钮样式抖动的问题。[#23259](https://github.com/ant-design/ant-design/pull/23259)
|
||||
- 🐞 修复 Input.Search 全局设置 `size` 不生效问题。[#23331](https://github.com/ant-design/ant-design/pull/23331)
|
||||
- Select
|
||||
- 🐞 修复 Select 多选时设置 `disabled` 选项仍然会展示移除按钮的问题。[#23295](https://github.com/ant-design/ant-design/pull/23295)
|
||||
- 🐞 修复 Select 自定义 `suffixIcon` 无法交互的问题。[#23274](https://github.com/ant-design/ant-design/pull/23274)
|
||||
- 🐞 修复 Select 输入光标在 Collapse 内不显示的问题。[#23250](https://github.com/ant-design/ant-design/pull/23250)
|
||||
- 国际化
|
||||
- 🌐 Form 校验信息支持国际化并增加中文文案。[#23165](https://github.com/ant-design/ant-design/pull/23165) [@hengkx](https://github.com/hengkx)
|
||||
- 🌐 完善希伯来语(以色列) 国际化。[#23302](https://github.com/ant-design/ant-design/pull/23302) [@MishaKav](https://github.com/MishaKav)
|
||||
- 🌐 完善俄语国际化。[#23303](https://github.com/ant-design/ant-design/pull/23303) [@MishaKav](https://github.com/MishaKav)
|
||||
- TypeScript
|
||||
- 🔷 更新 Tree 的类型定义。[#23348](https://github.com/ant-design/ant-design/pull/23348) [@yoyo837](https://github.com/yoyo837)
|
||||
- 🔷 更新 Form Item 的类型定义。[#22962](https://github.com/ant-design/ant-design/pull/22962) [@fa93hws](https://github.com/fa93hws)
|
||||
- 🐞 修复 Slider 组件 `value` 和 `defaultValue` 文档与 TypeScript 定义不一致的问题。[#23252](https://github.com/ant-design/ant-design/pull/23252) [@DongchengWang](https://github.com/DongchengWang)
|
||||
- RTL
|
||||
- 🐞 修复 Menu RTL 样式。[#23319](https://github.com/ant-design/ant-design/pull/23319)
|
||||
- 💄 修复 Select 的 RTL 样式。[#23235](https://github.com/ant-design/ant-design/pull/23235)
|
||||
|
||||
## 4.1.3
|
||||
|
||||
`2020-04-13`
|
||||
|
||||
- 💄 调整 Form.Item `label` 在垂直布局下的高度样式。[#23192](https://github.com/ant-design/ant-design/pull/23192)
|
||||
- 🐞 修复引用暗黑或紧凑主题时提示 `Variable is undefined` 的问题,并提供 `getThemeVariables` 方便获取对应主题变量。[#23171](https://github.com/ant-design/ant-design/pull/23171)
|
||||
- 🐞 修复 PageHeader `title` 超长时布局被破坏的问题并优化响应式表现。[#23133](https://github.com/ant-design/ant-design/pull/23133)
|
||||
- Tabs
|
||||
- 🐞 修复 Tabs `@tabs-card-height` less 变量无效的问题。[#23168](https://github.com/ant-design/ant-design/pull/23168)
|
||||
- 🐞 修复 Tabs 在 Safair 浏览器下无法显示的问题。[#23151](https://github.com/ant-design/ant-design/pull/23151) [@imhxc](https://github.com/imhxc)
|
||||
- Table
|
||||
- 🐞 修复 Table 固定列在 Safari 12 中不能固定的问题。[#23161](https://github.com/ant-design/ant-design/pull/23161)
|
||||
- 🐞 修复 Table `summary` 在小尺寸下的内边距样式。[#23140](https://github.com/ant-design/ant-design/pull/23140) [@someyoungideas](https://github.com/someyoungideas)
|
||||
- 🐞 修复 Select 不同尺寸下的对齐样式问题。[#23160](https://github.com/ant-design/ant-design/pull/23160)
|
||||
- 🐞 修复 RangePicker 在 Input.Group 内的样式问题。[#23149](https://github.com/ant-design/ant-design/pull/23149)
|
||||
- 🐞 修复 Pagination 缺少 `showTitle` TypeScript 定义的问题。[#23144](https://github.com/ant-design/ant-design/pull/23144) [@DongchengWang](https://github.com/DongchengWang)
|
||||
|
||||
## 4.1.2
|
||||
|
||||
`2020-04-10`
|
||||
|
||||
- Menu
|
||||
- 🐞 修复暗色 Menu 弹出菜单背景色为白色的问题。[#22981](https://github.com/ant-design/ant-design/pull/22981) [@AshoneA](https://github.com/AshoneA)
|
||||
- 🐞 修复 SubMenu 标题过长而导致被箭头图标部分覆盖的问题。[#23028](https://github.com/ant-design/ant-design/pull/23028) [@wwyx778](https://github.com/wwyx778)
|
||||
@@ -52,6 +371,8 @@ timeline: true
|
||||
|
||||
## 4.1.1
|
||||
|
||||
`2020-04-05`
|
||||
|
||||
- 🐞 移除 Tabs 的内容区域的 focus 蓝色轮廓线。[#22752](https://github.com/ant-design/ant-design/pull/22752) [@MrHeer](https://github.com/MrHeer)
|
||||
- 🐞 修复 Input 前后缀添加弹出元素不能点击获得焦点的问题。[#22887](https://github.com/ant-design/ant-design/pull/22887)
|
||||
- Table
|
||||
|
||||
@@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at xingmin.zhu@alipay.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [xingmin.zhu@alipay.com.](mailto:xingmin.zhu@alipay.com.) The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
|
||||
7
Dockerfile.ui-test
Normal file
7
Dockerfile.ui-test
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM buildkite/puppeteer:latest
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
COPY package.json ./
|
||||
RUN npm install
|
||||
ENV PATH="${PATH}:/app/node_modules/.bin"
|
||||
COPY . .
|
||||
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<a href="http://ant.design">
|
||||
<a href="https://ant.design">
|
||||
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
</a>
|
||||
</p>
|
||||
@@ -10,15 +10,44 @@
|
||||
|
||||
Uma solução empresarial de design e biblioteca UI para React.
|
||||
|
||||
[](https://circleci.com/gh/ant-design/ant-design)  [](https://codecov.io/gh/ant-design/ant-design/branch/master) [](https://www.npmjs.com/package/antd) [](http://npmjs.com/antd)
|
||||
[![CircleCI status][circleci-image]][circleci-url] [![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
|
||||
|
||||
[](https://david-dm.org/ant-design/ant-design) [](https://david-dm.org/ant-design/ant-design?type=dev) [](https://lgtm.com/projects/g/ant-design/ant-design/alerts/) [](https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield) [](https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![FOSSA Status][fossa-image]][fossa-url] [![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
|
||||
[](https://twitter.com/AntDesignUI) [](https://gitter.im/ant-design/ant-design-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![Gitter][gitter-english-image]][gitter-english-url] [![Gitter][gitter-chinese-image]][gitter-chinese-url] [![[SemVer stability]][semver-stability-image]][semver-stability-url]
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/antd
|
||||
[circleci-image]: https://img.shields.io/travis/com/ant-design/ant-design.svg?style=flat-square
|
||||
[circleci-url]: https://travis-ci.com/ant-design/ant-design
|
||||
[github-action-image]: https://github.com/ant-design/ant-design/workflows/test/badge.svg
|
||||
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3Atest
|
||||
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
|
||||
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
|
||||
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
|
||||
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
|
||||
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
|
||||
[david-url]: https://david-dm.org/ant-design/ant-design
|
||||
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/antd
|
||||
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
|
||||
[lgtm-url]: https://lgtm.com/projects/g/ant-design/ant-design/alerts/
|
||||
[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield
|
||||
[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield
|
||||
[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open
|
||||
[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22
|
||||
[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design&style=social
|
||||
[twitter-url]: https://twitter.com/AntDesignUI
|
||||
[gitter-english-image]: https://img.shields.io/gitter/room/ant-design/ant-design-english.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D
|
||||
[gitter-english-url]: https://gitter.im/ant-design/ant-design-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
|
||||
[gitter-chinese-image]: https://img.shields.io/gitter/room/ant-design/ant-design.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D
|
||||
[gitter-chinese-url]: https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
[semver-stability-url]: https://dependabot.com/compatibility-score.html/?dependency-name=antd&package-manager=npm_and_yarn&new-version=latest
|
||||
[semver-stability-image]: https://api.dependabot.com/badges/compatibility_score?dependency-name=antd&package-manager=npm_and_yarn&target-version=latest&version-scheme=semver
|
||||
|
||||
</div>
|
||||
|
||||
[](http://ant.design)
|
||||
[](https://ant.design)
|
||||
|
||||
[English](./README.md) | Português | [简体中文](./README-zh_CN.md)
|
||||
|
||||
@@ -33,7 +62,7 @@ Uma solução empresarial de design e biblioteca UI para React.
|
||||
|
||||
## 🖥 Suporte aos ambientes
|
||||
|
||||
- Navegadores modernos e Internet Explorer 11+ (com [polyfills](https://ant.design/docs/react/getting-started#Compatibility))
|
||||
- Navegadores modernos e Internet Explorer 11 (com [polyfills](https://ant.design/docs/react/getting-started#Compatibility))
|
||||
- Renderização no lado do servidor (server-side)
|
||||
- [Electron](https://www.electronjs.org/)
|
||||
|
||||
@@ -70,21 +99,20 @@ Importe o estilo manualmente:
|
||||
import 'antd/dist/antd.css'; // ou 'antd/dist/antd.less'
|
||||
```
|
||||
|
||||
Ou use [babel-plugin-import](https://ant.design/docs/react/getting-started#Import-on-Demand).
|
||||
|
||||
### TypeScript
|
||||
|
||||
Veja [Uso no Typescript](https://ant.design/docs/react/use-in-typescript).
|
||||
|
||||
## 🌍 Internacionalização
|
||||
|
||||
Veja [i18n](http://ant.design/docs/react/i18n).
|
||||
Veja [i18n](https://ant.design/docs/react/i18n).
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
- [Página inicial](http://ant.design/)
|
||||
- [Componentes](http://ant.design/docs/react/introduce)
|
||||
- [Página inicial](https://ant.design/)
|
||||
- [Componentes](https://ant.design/components/overview)
|
||||
- [Ant Design Pro](http://pro.ant.design/)
|
||||
- [Ant Design Charts](https://charts.ant.design)
|
||||
- [Change Log](CHANGELOG.en-US.md)
|
||||
- [rc-components](http://react-component.github.io/)
|
||||
- [Mobile UI](http://mobile.ant.design)
|
||||
@@ -101,7 +129,7 @@ Veja [i18n](http://ant.design/docs/react/i18n).
|
||||
- [FAQ](https://ant.design/docs/react/faq)
|
||||
- [CodeSandbox Template](https://u.ant.design/codesandbox-repro) para relatório de erros
|
||||
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
|
||||
- [Customize Theme](http://ant.design/docs/react/customize-theme)
|
||||
- [Customize Theme](https://ant.design/docs/react/customize-theme)
|
||||
- [How to Apply for Being A Collaborator](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator)
|
||||
|
||||
## ⌨️ Desenvolvimento
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<a href="http://ant.design">
|
||||
<a href="https://ant.design">
|
||||
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
</a>
|
||||
</p>
|
||||
@@ -10,15 +10,44 @@
|
||||
|
||||
一套企业级 UI 设计语言和 React 组件库。
|
||||
|
||||
[](https://circleci.com/gh/ant-design/ant-design)  [](https://codecov.io/gh/ant-design/ant-design/branch/master) [](https://www.npmjs.com/package/antd) [](http://npmjs.com/antd)
|
||||
[![CircleCI status][circleci-image]][circleci-url] [![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
|
||||
|
||||
[](https://david-dm.org/ant-design/ant-design) [](https://david-dm.org/ant-design/ant-design?type=dev) [](https://lgtm.com/projects/g/ant-design/ant-design/alerts/) [](https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield) [](https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![FOSSA Status][fossa-image]][fossa-url] [![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
|
||||
[](https://twitter.com/AntDesignUI) [](https://gitter.im/ant-design/ant-design-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![Gitter][gitter-english-image]][gitter-english-url] [![Gitter][gitter-chinese-image]][gitter-chinese-url] [![[SemVer stability]][semver-stability-image]][semver-stability-url]
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/antd
|
||||
[circleci-image]: https://img.shields.io/travis/com/ant-design/ant-design.svg?style=flat-square
|
||||
[circleci-url]: https://travis-ci.com/ant-design/ant-design
|
||||
[github-action-image]: https://github.com/ant-design/ant-design/workflows/test/badge.svg
|
||||
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3Atest
|
||||
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
|
||||
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
|
||||
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
|
||||
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
|
||||
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
|
||||
[david-url]: https://david-dm.org/ant-design/ant-design
|
||||
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/antd
|
||||
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
|
||||
[lgtm-url]: https://lgtm.com/projects/g/ant-design/ant-design/alerts/
|
||||
[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield
|
||||
[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield
|
||||
[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open
|
||||
[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22
|
||||
[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design&style=social
|
||||
[twitter-url]: https://twitter.com/AntDesignUI
|
||||
[gitter-english-image]: https://img.shields.io/gitter/room/ant-design/ant-design-english.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D
|
||||
[gitter-english-url]: https://gitter.im/ant-design/ant-design-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
|
||||
[gitter-chinese-image]: https://img.shields.io/gitter/room/ant-design/ant-design.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D
|
||||
[gitter-chinese-url]: https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
[semver-stability-url]: https://dependabot.com/compatibility-score.html/?dependency-name=antd&package-manager=npm_and_yarn&new-version=latest
|
||||
[semver-stability-image]: https://api.dependabot.com/badges/compatibility_score?dependency-name=antd&package-manager=npm_and_yarn&target-version=latest&version-scheme=semver
|
||||
|
||||
</div>
|
||||
|
||||
[](http://ant.design/index-cn)
|
||||
[](https://ant.design/index-cn)
|
||||
|
||||
[English](./README.md) | [Português](./README-pt_BR.md) | 简体中文
|
||||
|
||||
@@ -31,9 +60,9 @@
|
||||
- 🌍 数十个国际化语言支持。
|
||||
- 🎨 深入每个细节的主题定制能力。
|
||||
|
||||
## 🖥 支持环境
|
||||
## 🖥 兼容环境
|
||||
|
||||
- 现代浏览器和 IE11 及以上。
|
||||
- 现代浏览器和 IE11(需要 [polyfills](https://ant.design/docs/react/getting-started-cn#兼容性))。
|
||||
- 支持服务端渲染。
|
||||
- [Electron](https://www.electronjs.org/)
|
||||
|
||||
@@ -70,8 +99,6 @@ const App = () => (
|
||||
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
```
|
||||
|
||||
你也可以使用 [babel-plugin-import](https://ant.design/docs/react/getting-started-cn#按需加载)。
|
||||
|
||||
### 🌈 定制主题
|
||||
|
||||
参考 [定制主题](https://ant.design/docs/react/customize-theme-cn) 文档。
|
||||
@@ -82,13 +109,14 @@ import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
|
||||
## 🌍 国际化
|
||||
|
||||
参考 [国际化文档](http://ant.design/docs/react/i18n-cn)。
|
||||
参考 [国际化文档](https://ant.design/docs/react/i18n-cn)。
|
||||
|
||||
## 🔗 链接
|
||||
|
||||
- [首页](http://ant.design/)
|
||||
- [组件库](http://ant.design/docs/react/introduce)
|
||||
- [首页](https://ant.design/)
|
||||
- [组件库](https://ant.design/components/overview-cn)
|
||||
- [Ant Design Pro](http://pro.ant.design/)
|
||||
- [Ant Design Charts](https://charts.ant.design)
|
||||
- [更新日志](CHANGELOG.en-US.md)
|
||||
- [React 底层基础组件](http://react-component.github.io/)
|
||||
- [移动端组件](http://mobile.ant.design)
|
||||
@@ -106,7 +134,7 @@ import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
- [常见问题](https://ant.design/docs/react/faq-cn)
|
||||
- [CodeSandbox 模板](https://u.ant.design/codesandbox-repro) for bug reports
|
||||
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
|
||||
- [定制主题](http://ant.design/docs/react/customize-theme-cn)
|
||||
- [定制主题](https://ant.design/docs/react/customize-theme-cn)
|
||||
- [成为社区协作成员](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator)
|
||||
|
||||
## ⌨️ 本地开发
|
||||
|
||||
35
README.md
35
README.md
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<a href="http://ant.design">
|
||||
<a href="https://ant.design">
|
||||
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
</a>
|
||||
</p>
|
||||
@@ -14,7 +14,7 @@ An enterprise-class UI design language and React UI library.
|
||||
|
||||
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![FOSSA Status][fossa-image]][fossa-url] [![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![Gitter][gitter-english-image]][gitter-english-url] [![Gitter][gitter-chinese-image]][gitter-chinese-url]
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![Gitter][gitter-english-image]][gitter-english-url] [![Gitter][gitter-chinese-image]][gitter-chinese-url] [![[SemVer stability]][semver-stability-image]][semver-stability-url]
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/antd
|
||||
@@ -24,30 +24,30 @@ An enterprise-class UI design language and React UI library.
|
||||
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3Atest
|
||||
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
|
||||
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
|
||||
[david-image]: https://david-dm.org/ant-design/ant-design/status.svg?style=flat-square
|
||||
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
|
||||
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
|
||||
[david-dev-image]: https://david-dm.org/ant-design/ant-design/dev-status.svg?style=flat-square
|
||||
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
|
||||
[david-url]: https://david-dm.org/ant-design/ant-design
|
||||
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/antd
|
||||
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
|
||||
[lgtm-url]: https://lgtm.com/projects/g/ant-design/ant-design/alerts/
|
||||
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
|
||||
[lgtm-url]: https://lgtm.com/projects/g/ant-design/ant-design/alerts/
|
||||
[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield
|
||||
[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield
|
||||
[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open
|
||||
[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22
|
||||
[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design&style=social
|
||||
[twitter-url]: https://twitter.com/AntDesignUI
|
||||
[gitter-english-image]: https://img.shields.io/gitter/room/ant-design/ant-design-english.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D
|
||||
[gitter-english-image]: https://img.shields.io/gitter/room/ant-design/ant-design-english.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D
|
||||
[gitter-english-url]: https://gitter.im/ant-design/ant-design-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
|
||||
[gitter-chinese-image]: https://img.shields.io/gitter/room/ant-design/ant-design.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D
|
||||
[gitter-chinese-image]: https://img.shields.io/gitter/room/ant-design/ant-design.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D
|
||||
[gitter-chinese-url]: https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
[semver-stability-url]: https://dependabot.com/compatibility-score.html/?dependency-name=antd&package-manager=npm_and_yarn&new-version=latest
|
||||
[semver-stability-image]: https://api.dependabot.com/badges/compatibility_score?dependency-name=antd&package-manager=npm_and_yarn&target-version=latest&version-scheme=semver
|
||||
|
||||
</div>
|
||||
|
||||
[](http://ant.design)
|
||||
[](https://ant.design)
|
||||
|
||||
English | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md)
|
||||
|
||||
@@ -62,7 +62,7 @@ English | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md)
|
||||
|
||||
## 🖥 Environment Support
|
||||
|
||||
- Modern browsers and Internet Explorer 11+ (with [polyfills](https://ant.design/docs/react/getting-started#Compatibility))
|
||||
- Modern browsers and Internet Explorer 11 (with [polyfills](https://stackoverflow.com/questions/57020976/polyfills-in-2019-for-ie11))
|
||||
- Server-side Rendering
|
||||
- [Electron](https://www.electronjs.org/)
|
||||
|
||||
@@ -88,7 +88,7 @@ import { Button, DatePicker } from 'antd';
|
||||
const App = () => (
|
||||
<>
|
||||
<Button type="primary">PRESS ME</Button>
|
||||
<DatePicker />
|
||||
<DatePicker placeholder="select date" />
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -99,21 +99,20 @@ And import style manually:
|
||||
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
```
|
||||
|
||||
Or use [babel-plugin-import](https://ant.design/docs/react/getting-started#Import-on-Demand).
|
||||
|
||||
### TypeScript
|
||||
|
||||
See [Use in TypeScript](https://ant.design/docs/react/use-in-typescript).
|
||||
`antd` is written in TypeScript with complete definitions, check [Use in TypeScript](https://ant.design/docs/react/use-in-typescript) to getting started.
|
||||
|
||||
## 🌍 Internationalization
|
||||
|
||||
See [i18n](http://ant.design/docs/react/i18n).
|
||||
Dozens of languages supported in `antd`, see [i18n](https://ant.design/docs/react/i18n).
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
- [Home page](http://ant.design/)
|
||||
- [Components](http://ant.design/docs/react/introduce)
|
||||
- [Home page](https://ant.design/)
|
||||
- [Components](https://ant.design/components/overview)
|
||||
- [Ant Design Pro](http://pro.ant.design/)
|
||||
- [Ant Design Charts](https://charts.ant.design)
|
||||
- [Change Log](CHANGELOG.en-US.md)
|
||||
- [rc-components](http://react-component.github.io/)
|
||||
- [Mobile UI](http://mobile.ant.design)
|
||||
@@ -130,7 +129,7 @@ See [i18n](http://ant.design/docs/react/i18n).
|
||||
- [FAQ](https://ant.design/docs/react/faq)
|
||||
- [CodeSandbox Template](https://u.ant.design/codesandbox-repro) for bug reports
|
||||
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
|
||||
- [Customize Theme](http://ant.design/docs/react/customize-theme)
|
||||
- [Customize Theme](https://ant.design/docs/react/customize-theme)
|
||||
- [How to Apply for Being A Collaborator](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator)
|
||||
|
||||
## ⌨️ Development
|
||||
|
||||
@@ -12,50 +12,106 @@ pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
|
||||
stages:
|
||||
- stage: site
|
||||
jobs:
|
||||
- job: Build_Site
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.13.1'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js "[](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
- script: npm run site
|
||||
displayName: 'Build sites'
|
||||
- script: ls -al _site/
|
||||
displayName: 'List build'
|
||||
- script: |
|
||||
export DEPLOY_DOMAIN=https://preview-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
|
||||
echo "Deploy to $DEPLOY_DOMAIN"
|
||||
npx surge --project ./_site --domain $DEPLOY_DOMAIN
|
||||
displayName: 'Deploy Site'
|
||||
- script: |
|
||||
export DEPLOY_DOMAIN=https://preview-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
|
||||
node ./scripts/azure-github-comment.js "[<img width="306" src="https://user-images.githubusercontent.com/5378891/72400743-23dbb200-3785-11ea-9d13-1a2d92743846.png">]($DEPLOY_DOMAIN)"
|
||||
displayName: 'Update comment on github'
|
||||
- job: Build_Site_Failed
|
||||
dependsOn: Build_Site
|
||||
condition: failed()
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.13.1'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js "[<img width="534" src="https://user-images.githubusercontent.com/5378891/75333447-1e63a280-58c1-11ea-975d-235367fd1522.png">](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
- stage: site
|
||||
jobs:
|
||||
- job: Build_Site
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.13.1'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js "[](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
- script: npm run site
|
||||
displayName: 'Build sites'
|
||||
- script: ls -al _site/
|
||||
displayName: 'List build'
|
||||
- script: |
|
||||
export DEPLOY_DOMAIN=https://preview-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
|
||||
echo "Deploy to $DEPLOY_DOMAIN"
|
||||
npx surge --project ./_site --domain $DEPLOY_DOMAIN
|
||||
displayName: 'Deploy Site'
|
||||
- script: |
|
||||
export DEPLOY_DOMAIN=https://preview-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
|
||||
node ./scripts/azure-github-comment.js "[<img width="306" src="https://user-images.githubusercontent.com/5378891/72400743-23dbb200-3785-11ea-9d13-1a2d92743846.png">]($DEPLOY_DOMAIN)"
|
||||
displayName: 'Update comment on github'
|
||||
- job: Build_Site_Failed
|
||||
dependsOn: Build_Site
|
||||
condition: failed()
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.13.1'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js "[<img width="534" src="https://user-images.githubusercontent.com/5378891/75333447-1e63a280-58c1-11ea-975d-235367fd1522.png">](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
- stage: ui
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- job: UI_Test
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.16.3'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js -ui "[](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
- script: npm run test-image
|
||||
displayName: 'UI Test'
|
||||
- task: PublishPipelineArtifact@1
|
||||
inputs:
|
||||
targetPath: $(System.DefaultWorkingDirectory)/jest-stare
|
||||
artifactName: jestStare
|
||||
condition: failed()
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js -ui "[<img width="306" src="https://user-images.githubusercontent.com/14831261/82744259-6e5ee200-9da8-11ea-8479-685f6e280b77.jpg">](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Update comment on github'
|
||||
- job: UI_Test_Failed
|
||||
dependsOn: UI_Test
|
||||
condition: failed()
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.13.1'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
artifact: jestStare
|
||||
path: './jest-stare'
|
||||
- script: ls -al ./jest-stare
|
||||
displayName: 'List report'
|
||||
- script: |
|
||||
export DEPLOY_DOMAIN=https://ui-test-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
|
||||
echo "Deploy to $DEPLOY_DOMAIN"
|
||||
npx surge --project ./jest-stare --domain $DEPLOY_DOMAIN
|
||||
displayName: 'Deploy Report Site'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js -ui "[<img width="306" src="https://user-images.githubusercontent.com/14831261/82744257-6dc64b80-9da8-11ea-80cf-05b2279a5602.jpg">](https://ui-test-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh)"
|
||||
displayName: 'Update comment on github'
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
const __NULL__ = { notExist: true };
|
||||
|
||||
export function spyElementPrototypes(Element, properties) {
|
||||
const propNames = Object.keys(properties);
|
||||
const originDescriptors = {};
|
||||
|
||||
propNames.forEach(propName => {
|
||||
const originDescriptor = Object.getOwnPropertyDescriptor(Element.prototype, propName);
|
||||
originDescriptors[propName] = originDescriptor || __NULL__;
|
||||
|
||||
const spyProp = properties[propName];
|
||||
|
||||
if (typeof spyProp === 'function') {
|
||||
// If is a function
|
||||
Element.prototype[propName] = function spyFunc(...args) {
|
||||
return spyProp.call(this, originDescriptor, ...args);
|
||||
};
|
||||
} else {
|
||||
// Otherwise tread as a property
|
||||
Object.defineProperty(Element.prototype, propName, {
|
||||
...spyProp,
|
||||
set(value) {
|
||||
if (spyProp.set) {
|
||||
return spyProp.set.call(this, originDescriptor, value);
|
||||
}
|
||||
return originDescriptor.set(value);
|
||||
},
|
||||
get() {
|
||||
if (spyProp.get) {
|
||||
return spyProp.get.call(this, originDescriptor);
|
||||
}
|
||||
return originDescriptor.get();
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
mockRestore() {
|
||||
propNames.forEach(propName => {
|
||||
const originDescriptor = originDescriptors[propName];
|
||||
if (originDescriptor === __NULL__) {
|
||||
delete Element.prototype[propName];
|
||||
} else if (typeof originDescriptor === 'function') {
|
||||
Element.prototype[propName] = originDescriptor;
|
||||
} else {
|
||||
Object.defineProperty(Element.prototype, propName, originDescriptor);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function spyElementPrototype(Element, propName, property) {
|
||||
return spyElementPrototypes(Element, {
|
||||
[propName]: property,
|
||||
});
|
||||
}
|
||||
@@ -1,11 +1,57 @@
|
||||
/**
|
||||
* @jest-environment node
|
||||
*/
|
||||
import getScroll from '../getScroll';
|
||||
|
||||
describe('getScroll', () => {
|
||||
it('getScroll return 0 in node envioronment', async () => {
|
||||
it('getScroll target null', async () => {
|
||||
expect(getScroll(null, true)).toBe(0);
|
||||
expect(getScroll(null, false)).toBe(0);
|
||||
});
|
||||
|
||||
it('getScroll window', async () => {
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
window.pageXOffset = x;
|
||||
window.pageYOffset = y;
|
||||
});
|
||||
window.scrollTo(200, 400);
|
||||
expect(getScroll(window, true)).toBe(400);
|
||||
expect(getScroll(window, false)).toBe(200);
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('getScroll document', async () => {
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
document.documentElement.scrollLeft = x;
|
||||
document.documentElement.scrollTop = y;
|
||||
});
|
||||
window.scrollTo(200, 400);
|
||||
expect(getScroll(document, true)).toBe(400);
|
||||
expect(getScroll(document, false)).toBe(200);
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('getScroll div', async () => {
|
||||
const div = document.createElement('div');
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
div.scrollLeft = x;
|
||||
div.scrollTop = y;
|
||||
});
|
||||
window.scrollTo(200, 400);
|
||||
expect(getScroll(div, true)).toBe(400);
|
||||
expect(getScroll(div, false)).toBe(200);
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('getScroll documentElement', async () => {
|
||||
const div = {};
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
div.scrollLeft = null;
|
||||
div.scrollTop = null;
|
||||
div.documentElement = {};
|
||||
div.documentElement.scrollLeft = x;
|
||||
div.documentElement.scrollTop = y;
|
||||
});
|
||||
window.scrollTo(200, 400);
|
||||
expect(getScroll(div, true)).toBe(400);
|
||||
expect(getScroll(div, false)).toBe(200);
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
11
components/_util/__tests__/getScrollNode.test.ts
Normal file
11
components/_util/__tests__/getScrollNode.test.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* @jest-environment node
|
||||
*/
|
||||
import getScroll from '../getScroll';
|
||||
|
||||
describe('getScroll node', () => {
|
||||
it('getScroll return 0 in node environment', async () => {
|
||||
expect(getScroll(null, true)).toBe(0);
|
||||
expect(getScroll(null, false)).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -46,4 +46,21 @@ describe('Test ScrollTo function', () => {
|
||||
await sleep(20);
|
||||
expect(div.scrollTop).toBe(1000);
|
||||
});
|
||||
|
||||
it('test getContainer document - option', async () => {
|
||||
scrollTo(1000, {
|
||||
getContainer: () => document,
|
||||
});
|
||||
await sleep(20);
|
||||
expect(document.documentElement.scrollTop).toBe(1000);
|
||||
});
|
||||
|
||||
it('test duration - option', async () => {
|
||||
scrollTo(1000, {
|
||||
duration: 1100,
|
||||
getContainer: () => document,
|
||||
});
|
||||
await sleep(20);
|
||||
expect(document.documentElement.scrollTop).toBe(1000);
|
||||
});
|
||||
});
|
||||
|
||||
12
components/_util/__tests__/transButton.test.js
Normal file
12
components/_util/__tests__/transButton.test.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import TransButton from '../transButton';
|
||||
|
||||
describe('transButton component', () => {
|
||||
it('disabled should update style', () => {
|
||||
const wrapper = mount(<TransButton disabled />);
|
||||
expect(wrapper.find('div').first().props().style).toEqual(
|
||||
expect.objectContaining({ pointerEvents: 'none' }),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -18,24 +18,42 @@ describe('Wave component', () => {
|
||||
it('isHidden works', () => {
|
||||
const TEST_NODE_ENV = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'development';
|
||||
const wrapper = mount(<Wave><button type="button">button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button">button</button>
|
||||
</Wave>,
|
||||
);
|
||||
expect(wrapper.find('button').getDOMNode().className).toBe('');
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
expect(wrapper.find('button').getDOMNode().hasAttribute('ant-click-animating-without-extra-node')).toBe(false);
|
||||
expect(
|
||||
wrapper.find('button').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe(false);
|
||||
wrapper.unmount();
|
||||
process.env.NODE_ENV = TEST_NODE_ENV;
|
||||
});
|
||||
|
||||
it('isHidden is mocked', () => {
|
||||
const wrapper = mount(<Wave><button type="button">button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button">button</button>
|
||||
</Wave>,
|
||||
);
|
||||
expect(wrapper.find('button').getDOMNode().className).toBe('');
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
expect(wrapper.find('button').getDOMNode().getAttribute('ant-click-animating-without-extra-node')).toBe('false');
|
||||
expect(
|
||||
wrapper.find('button').getDOMNode().getAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe('false');
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it('wave color is grey', async () => {
|
||||
const wrapper = mount(<Wave><button type="button" style={{ borderColor: 'rgb(0, 0, 0)' }}>button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" style={{ borderColor: 'rgb(0, 0, 0)' }}>
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -44,7 +62,13 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('wave color is not grey', async () => {
|
||||
const wrapper = mount(<Wave><button type="button" style={{ borderColor: 'red' }}>button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" style={{ borderColor: 'red' }}>
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
await sleep(200);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -54,7 +78,11 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('read wave color from border-top-color', async () => {
|
||||
const wrapper = mount(<Wave><div style={{ borderTopColor: 'blue' }}>button</div></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<div style={{ borderTopColor: 'blue' }}>button</div>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('div').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -64,7 +92,11 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('read wave color from background color', async () => {
|
||||
const wrapper = mount(<Wave><div style={{ backgroundColor: 'green' }}>button</div></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<div style={{ backgroundColor: 'green' }}>button</div>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('div').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -74,7 +106,11 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('read wave color from border firstly', async () => {
|
||||
const wrapper = mount(<Wave><div style={{ borderColor: 'yellow', backgroundColor: 'green' }}>button</div></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<div style={{ borderColor: 'yellow', backgroundColor: 'green' }}>button</div>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('div').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -84,7 +120,13 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('hidden element with -leave className', async () => {
|
||||
const wrapper = mount(<Wave><button type="button" className="xx-leave">button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" className="xx-leave">
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -95,7 +137,9 @@ describe('Wave component', () => {
|
||||
it('ConfigProvider csp', async () => {
|
||||
const wrapper = mount(
|
||||
<ConfigProvider csp={{ nonce: 'YourNonceCode' }}>
|
||||
<Wave><button type="button">button</button></Wave>
|
||||
<Wave>
|
||||
<button type="button">button</button>
|
||||
</Wave>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { tuple } from './type';
|
||||
import { ElementOf, tuple } from './type';
|
||||
|
||||
export const PresetStatusColorTypes = tuple('success', 'processing', 'error', 'default', 'warning');
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
@@ -18,5 +18,5 @@ export const PresetColorTypes = tuple(
|
||||
'lime',
|
||||
);
|
||||
|
||||
export type PresetColorType = typeof PresetColorTypes[number];
|
||||
export type PresetStatusColorType = typeof PresetStatusColorTypes[number];
|
||||
export type PresetColorType = ElementOf<typeof PresetColorTypes>;
|
||||
export type PresetStatusColorType = ElementOf<typeof PresetStatusColorTypes>;
|
||||
|
||||
7
components/_util/devWarning.ts
Normal file
7
components/_util/devWarning.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import devWarning, { resetWarned } from 'rc-util/lib/warning';
|
||||
|
||||
export { resetWarned };
|
||||
|
||||
export default (valid: boolean, component: string, message: string): void => {
|
||||
devWarning(valid, `[antd: ${component}] ${message}`);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import * as React from 'react';
|
||||
|
||||
export type RenderFunction = () => React.ReactNode;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ interface Motion {
|
||||
motionEnter?: boolean;
|
||||
motionLeave?: boolean;
|
||||
motionLeaveImmediately?: boolean; // Trigger leave motion immediately
|
||||
motionDeadline?: number;
|
||||
removeOnLeave?: boolean;
|
||||
leavedClassName?: string;
|
||||
onAppearStart?: MotionFunc;
|
||||
@@ -35,6 +36,7 @@ const collapseMotion: Motion = {
|
||||
onEnterActive: getRealHeight,
|
||||
onLeaveStart: getCurrentHeight,
|
||||
onLeaveActive: getCollapsedHeight,
|
||||
motionDeadline: 500,
|
||||
};
|
||||
|
||||
export default collapseMotion;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Deprecated. We should replace the animation with pure react motion instead of modify style directly.
|
||||
* If you are creating new component with animation, please use `./motion`.
|
||||
*/
|
||||
import cssAnimation from 'css-animation';
|
||||
import cssAnimation from '@ant-design/css-animation';
|
||||
import raf from 'raf';
|
||||
|
||||
function animate(node: HTMLElement, show: boolean, done: () => void) {
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
import * as React from 'react';
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function cloneElement(element: React.ReactNode, ...restArgs: any[]) {
|
||||
if (!React.isValidElement(element)) return element;
|
||||
export const isValidElement = React.isValidElement;
|
||||
|
||||
return React.cloneElement(element, ...restArgs);
|
||||
export function replaceElement(
|
||||
element: React.ReactNode,
|
||||
replacement: React.ReactNode,
|
||||
props: any,
|
||||
): React.ReactNode {
|
||||
if (!isValidElement(element)) return replacement;
|
||||
|
||||
return React.cloneElement(element, typeof props === 'function' ? props() : props);
|
||||
}
|
||||
|
||||
export function cloneElement(element: React.ReactNode, props?: any): React.ReactElement {
|
||||
return replaceElement(element, element, props) as React.ReactElement;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import * as React from 'react';
|
||||
|
||||
export function fillRef<T>(ref: React.Ref<T>, node: T) {
|
||||
if (typeof ref === 'function') {
|
||||
|
||||
@@ -26,15 +26,10 @@ const responsiveObserve = {
|
||||
matchHandlers: {},
|
||||
dispatch(pointMap: ScreenMap) {
|
||||
screens = pointMap;
|
||||
if (subscribers.length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
subscribers.forEach(item => {
|
||||
item.func(screens);
|
||||
});
|
||||
|
||||
return true;
|
||||
return subscribers.length >= 1;
|
||||
},
|
||||
subscribe(func: SubscribeFunc) {
|
||||
if (subscribers.length === 0) {
|
||||
|
||||
@@ -24,8 +24,8 @@ export default function scrollTo(y: number, options: ScrollToOptions = {}) {
|
||||
const nextScrollTop = easeInOutCubic(time > duration ? duration : time, scrollTop, y, duration);
|
||||
if (isWindow(container)) {
|
||||
(container as Window).scrollTo(window.pageXOffset, nextScrollTop);
|
||||
} else if (container instanceof Document) {
|
||||
container.documentElement.scrollTop = nextScrollTop;
|
||||
} else if (container instanceof HTMLDocument || container.constructor.name === 'HTMLDocument') {
|
||||
(container as HTMLDocument).documentElement.scrollTop = nextScrollTop;
|
||||
} else {
|
||||
(container as HTMLElement).scrollTop = nextScrollTop;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ interface TransButtonProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
onClick?: (e?: React.MouseEvent<HTMLDivElement>) => void;
|
||||
noStyle?: boolean;
|
||||
autoFocus?: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const inlineStyle: React.CSSProperties = {
|
||||
@@ -63,7 +64,24 @@ class TransButton extends React.Component<TransButtonProps> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { style, noStyle, ...restProps } = this.props;
|
||||
const { style, noStyle, disabled, ...restProps } = this.props;
|
||||
|
||||
let mergedStyle: React.CSSProperties = {};
|
||||
|
||||
if (!noStyle) {
|
||||
mergedStyle = {
|
||||
...inlineStyle,
|
||||
};
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
mergedStyle.pointerEvents = 'none';
|
||||
}
|
||||
|
||||
mergedStyle = {
|
||||
...mergedStyle,
|
||||
...style,
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -73,7 +91,7 @@ class TransButton extends React.Component<TransButtonProps> {
|
||||
{...restProps}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={this.onKeyUp}
|
||||
style={{ ...(!noStyle ? inlineStyle : null), ...style }}
|
||||
style={mergedStyle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import warning, { resetWarned } from 'rc-util/lib/warning';
|
||||
|
||||
export { resetWarned };
|
||||
|
||||
export default (valid: boolean, component: string, message: string): void => {
|
||||
warning(valid, `[antd: ${component}] ${message}`);
|
||||
};
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import TransitionEvents from 'css-animation/lib/Event';
|
||||
import TransitionEvents from '@ant-design/css-animation/lib/Event';
|
||||
import raf from './raf';
|
||||
import { ConfigConsumer, ConfigConsumerProps, CSPConfig } from '../config-provider';
|
||||
import { ConfigConsumer, ConfigConsumerProps, CSPConfig, ConfigContext } from '../config-provider';
|
||||
|
||||
let styleForPesudo: HTMLStyleElement | null;
|
||||
|
||||
@@ -24,6 +24,8 @@ function isNotGrey(color: string) {
|
||||
}
|
||||
|
||||
export default class Wave extends React.Component<{ insertExtraNode?: boolean }> {
|
||||
static contextType = ConfigContext;
|
||||
|
||||
private instance?: {
|
||||
cancel: () => void;
|
||||
};
|
||||
@@ -40,6 +42,8 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
|
||||
private csp?: CSPConfig;
|
||||
|
||||
context: ConfigConsumerProps;
|
||||
|
||||
componentDidMount() {
|
||||
const node = findDOMNode(this) as HTMLElement;
|
||||
if (!node || node.nodeType !== 1) {
|
||||
@@ -66,7 +70,8 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
const { insertExtraNode } = this.props;
|
||||
this.extraNode = document.createElement('div');
|
||||
const { extraNode } = this;
|
||||
extraNode.className = 'ant-click-animating-node';
|
||||
const { getPrefixCls } = this.context;
|
||||
extraNode.className = `${getPrefixCls('')}-click-animating-node`;
|
||||
const attributeName = this.getAttributeName();
|
||||
node.setAttribute(attributeName, 'true');
|
||||
// Not white or transparnt or grey
|
||||
@@ -86,7 +91,9 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
|
||||
extraNode.style.borderColor = waveColor;
|
||||
styleForPesudo.innerHTML = `
|
||||
[ant-click-animating-without-extra-node='true']::after, .ant-click-animating-node {
|
||||
[${getPrefixCls('')}-click-animating-without-extra-node='true']::after, .${getPrefixCls(
|
||||
'',
|
||||
)}-click-animating-node {
|
||||
--antd-wave-shadow-color: ${waveColor};
|
||||
}`;
|
||||
if (!document.body.contains(styleForPesudo)) {
|
||||
@@ -121,8 +128,11 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
};
|
||||
|
||||
getAttributeName() {
|
||||
const { getPrefixCls } = this.context;
|
||||
const { insertExtraNode } = this.props;
|
||||
return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node';
|
||||
return insertExtraNode
|
||||
? `${getPrefixCls('')}-click-animating`
|
||||
: `${getPrefixCls('')}-click-animating-without-extra-node`;
|
||||
}
|
||||
|
||||
bindAnimationEvent = (node: HTMLElement) => {
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Affix from '..';
|
||||
import { getObserverEntities } from '../utils';
|
||||
import Button from '../../button';
|
||||
import { spyElementPrototype } from '../../__tests__/util/domHook';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
|
||||
const events = {};
|
||||
|
||||
class AffixMounter extends React.Component {
|
||||
componentDidMount() {
|
||||
this.container.addEventListener = jest.fn().mockImplementation((event, cb) => {
|
||||
events[event] = cb;
|
||||
});
|
||||
}
|
||||
|
||||
getTarget = () => this.container;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
ref={node => {
|
||||
this.container = node;
|
||||
}}
|
||||
className="container"
|
||||
>
|
||||
<Affix
|
||||
className="fixed"
|
||||
target={this.getTarget}
|
||||
ref={ele => {
|
||||
this.affix = ele;
|
||||
}}
|
||||
{...this.props}
|
||||
>
|
||||
<Button type="primary">Fixed at the top of container</Button>
|
||||
</Affix>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
describe('Affix Render', () => {
|
||||
rtlTest(Affix);
|
||||
|
||||
let wrapper;
|
||||
let domMock;
|
||||
|
||||
const classRect = {
|
||||
container: {
|
||||
top: 0,
|
||||
bottom: 100,
|
||||
},
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
domMock = spyElementPrototype(HTMLElement, 'getBoundingClientRect', function mockBounding() {
|
||||
return (
|
||||
classRect[this.className] || {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
domMock.mockRestore();
|
||||
});
|
||||
|
||||
const movePlaceholder = async top => {
|
||||
classRect.fixed = {
|
||||
top,
|
||||
bottom: top,
|
||||
};
|
||||
events.scroll({
|
||||
type: 'scroll',
|
||||
});
|
||||
await sleep(20);
|
||||
};
|
||||
|
||||
it('Anchor render perfectly', async () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
wrapper = mount(<AffixMounter />, { attachTo: document.getElementById('mounter') });
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(0);
|
||||
expect(wrapper.instance().affix.state.affixStyle).toBeFalsy();
|
||||
|
||||
await movePlaceholder(-100);
|
||||
expect(wrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
|
||||
await movePlaceholder(0);
|
||||
expect(wrapper.instance().affix.state.affixStyle).toBeFalsy();
|
||||
});
|
||||
|
||||
it('support offsetBottom', async () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
wrapper = mount(<AffixMounter offsetBottom={0} />, {
|
||||
attachTo: document.getElementById('mounter'),
|
||||
});
|
||||
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(300);
|
||||
expect(wrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
|
||||
await movePlaceholder(0);
|
||||
expect(wrapper.instance().affix.state.affixStyle).toBeFalsy();
|
||||
|
||||
await movePlaceholder(300);
|
||||
expect(wrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
});
|
||||
|
||||
it('updatePosition when offsetTop changed', async () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
wrapper = mount(<AffixMounter offsetTop={0} />, {
|
||||
attachTo: document.getElementById('mounter'),
|
||||
});
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(-100);
|
||||
expect(wrapper.instance().affix.state.affixStyle.top).toBe(0);
|
||||
wrapper.setProps({
|
||||
offsetTop: 10,
|
||||
});
|
||||
await sleep(20);
|
||||
expect(wrapper.instance().affix.state.affixStyle.top).toBe(10);
|
||||
});
|
||||
|
||||
describe('updatePosition when target changed', () => {
|
||||
it('function change', () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
const container = document.querySelector('#id');
|
||||
const getTarget = () => container;
|
||||
wrapper = mount(<Affix target={getTarget} />);
|
||||
wrapper.setProps({ target: null });
|
||||
expect(wrapper.instance().state.status).toBe(0);
|
||||
expect(wrapper.instance().state.affixStyle).toBe(undefined);
|
||||
expect(wrapper.instance().state.placeholderStyle).toBe(undefined);
|
||||
});
|
||||
|
||||
it('instance change', async () => {
|
||||
const getObserverLength = () => Object.keys(getObserverEntities()).length;
|
||||
|
||||
const container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
let target = container;
|
||||
|
||||
const originLength = getObserverLength();
|
||||
const getTarget = () => target;
|
||||
wrapper = mount(<Affix target={getTarget} />);
|
||||
await sleep(50);
|
||||
|
||||
expect(getObserverLength()).toBe(originLength + 1);
|
||||
target = null;
|
||||
wrapper.setProps({});
|
||||
wrapper.update();
|
||||
await sleep(50);
|
||||
expect(getObserverLength()).toBe(originLength);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updatePosition when size changed', () => {
|
||||
function test(name, index) {
|
||||
it(name, async () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
const updateCalled = jest.fn();
|
||||
wrapper = mount(<AffixMounter offsetBottom={0} onTestUpdatePosition={updateCalled} />, {
|
||||
attachTo: document.getElementById('mounter'),
|
||||
});
|
||||
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(300);
|
||||
expect(wrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
|
||||
// Mock trigger resize
|
||||
updateCalled.mockReset();
|
||||
wrapper
|
||||
.find('ResizeObserver')
|
||||
.at(index)
|
||||
.instance()
|
||||
.onResize([{ target: { getBoundingClientRect: () => ({ width: 99, height: 99 }) } }]);
|
||||
await sleep(20);
|
||||
|
||||
expect(updateCalled).toHaveBeenCalled();
|
||||
});
|
||||
}
|
||||
|
||||
test('inner', 0);
|
||||
test('outer', 1);
|
||||
});
|
||||
});
|
||||
230
components/affix/__tests__/Affix.test.tsx
Normal file
230
components/affix/__tests__/Affix.test.tsx
Normal file
@@ -0,0 +1,230 @@
|
||||
import React from 'react';
|
||||
import { mount, ReactWrapper, HTMLAttributes } from 'enzyme';
|
||||
import ResizeObserverImpl from 'rc-resize-observer';
|
||||
import Affix, { AffixProps, AffixState } from '..';
|
||||
import { getObserverEntities } from '../utils';
|
||||
import Button from '../../button';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
|
||||
const events: Partial<Record<keyof HTMLElementEventMap, (ev: Partial<Event>) => void>> = {};
|
||||
|
||||
class AffixMounter extends React.Component<{
|
||||
offsetBottom?: number;
|
||||
offsetTop?: number;
|
||||
onTestUpdatePosition?(): void;
|
||||
}> {
|
||||
private container: HTMLDivElement;
|
||||
|
||||
public affix: Affix;
|
||||
|
||||
componentDidMount() {
|
||||
this.container.addEventListener = jest
|
||||
.fn()
|
||||
.mockImplementation((event: keyof HTMLElementEventMap, cb: (ev: Partial<Event>) => void) => {
|
||||
events[event] = cb;
|
||||
});
|
||||
}
|
||||
|
||||
getTarget = () => this.container;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
ref={node => {
|
||||
this.container = node!;
|
||||
}}
|
||||
className="container"
|
||||
>
|
||||
<Affix
|
||||
className="fixed"
|
||||
target={this.getTarget}
|
||||
ref={ele => {
|
||||
this.affix = ele!;
|
||||
}}
|
||||
{...this.props}
|
||||
>
|
||||
<Button type="primary">Fixed at the top of container</Button>
|
||||
</Affix>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
describe('Affix Render', () => {
|
||||
rtlTest(Affix);
|
||||
|
||||
const domMock = jest.spyOn(HTMLElement.prototype, 'getBoundingClientRect');
|
||||
let affixMounterWrapper: ReactWrapper<unknown, unknown, AffixMounter>;
|
||||
let affixWrapper: ReactWrapper<AffixProps, AffixState, Affix>;
|
||||
|
||||
const classRect: Record<string, DOMRect> = {
|
||||
container: {
|
||||
top: 0,
|
||||
bottom: 100,
|
||||
} as DOMRect,
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
domMock.mockImplementation(function fn(this: HTMLElement) {
|
||||
return (
|
||||
classRect[this.className] || {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
domMock.mockRestore();
|
||||
});
|
||||
|
||||
const movePlaceholder = async (top: number) => {
|
||||
classRect.fixed = {
|
||||
top,
|
||||
bottom: top,
|
||||
} as DOMRect;
|
||||
if (events.scroll == null) {
|
||||
throw new Error('scroll should be set');
|
||||
}
|
||||
events.scroll({
|
||||
type: 'scroll',
|
||||
});
|
||||
await sleep(20);
|
||||
};
|
||||
|
||||
it('Anchor render perfectly', async () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
affixMounterWrapper = mount(<AffixMounter />, { attachTo: document.getElementById('mounter') });
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(0);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeFalsy();
|
||||
|
||||
await movePlaceholder(-100);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
|
||||
await movePlaceholder(0);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeFalsy();
|
||||
});
|
||||
|
||||
it('support offsetBottom', async () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
affixMounterWrapper = mount(<AffixMounter offsetBottom={0} />, {
|
||||
attachTo: document.getElementById('mounter'),
|
||||
});
|
||||
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(300);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
|
||||
await movePlaceholder(0);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeFalsy();
|
||||
|
||||
await movePlaceholder(300);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
});
|
||||
|
||||
it('updatePosition when offsetTop changed', async () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
affixMounterWrapper = mount(<AffixMounter offsetTop={0} />, {
|
||||
attachTo: document.getElementById('mounter'),
|
||||
});
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(-100);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle?.top).toBe(0);
|
||||
affixMounterWrapper.setProps({
|
||||
offsetTop: 10,
|
||||
});
|
||||
await sleep(20);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle?.top).toBe(10);
|
||||
});
|
||||
|
||||
describe('updatePosition when target changed', () => {
|
||||
it('function change', () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
const container = document.querySelector('#id') as HTMLDivElement;
|
||||
const getTarget = () => container;
|
||||
affixWrapper = mount(<Affix target={getTarget}>{null}</Affix>);
|
||||
affixWrapper.setProps({ target: () => null });
|
||||
expect(affixWrapper.instance().state.status).toBe(0);
|
||||
expect(affixWrapper.instance().state.affixStyle).toBe(undefined);
|
||||
expect(affixWrapper.instance().state.placeholderStyle).toBe(undefined);
|
||||
});
|
||||
|
||||
it('instance change', async () => {
|
||||
const getObserverLength = () => Object.keys(getObserverEntities()).length;
|
||||
|
||||
const container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
let target: HTMLDivElement | null = container;
|
||||
|
||||
const originLength = getObserverLength();
|
||||
const getTarget = () => target;
|
||||
affixWrapper = mount(<Affix target={getTarget}>{null}</Affix>);
|
||||
await sleep(50);
|
||||
|
||||
expect(getObserverLength()).toBe(originLength + 1);
|
||||
target = null;
|
||||
affixWrapper.setProps({});
|
||||
affixWrapper.update();
|
||||
await sleep(50);
|
||||
expect(getObserverLength()).toBe(originLength);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updatePosition when size changed', () => {
|
||||
it.each([
|
||||
{ name: 'inner', index: 0 },
|
||||
{ name: 'outer', index: 1 },
|
||||
])(name, async ({ index }) => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
const updateCalled = jest.fn();
|
||||
affixMounterWrapper = mount(
|
||||
<AffixMounter offsetBottom={0} onTestUpdatePosition={updateCalled} />,
|
||||
{
|
||||
attachTo: document.getElementById('mounter'),
|
||||
},
|
||||
);
|
||||
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(300);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
await sleep(20);
|
||||
affixMounterWrapper.update();
|
||||
|
||||
// Mock trigger resize
|
||||
updateCalled.mockReset();
|
||||
const resizeObserverInstance: ReactWrapper<
|
||||
HTMLAttributes,
|
||||
unknown,
|
||||
ResizeObserverImpl
|
||||
> = affixMounterWrapper.find('ResizeObserver') as any;
|
||||
resizeObserverInstance
|
||||
.at(index)
|
||||
.instance()
|
||||
.onResize(
|
||||
[
|
||||
{
|
||||
target: {
|
||||
getBoundingClientRect: () => ({ width: 99, height: 99 }),
|
||||
} as Element,
|
||||
contentRect: {} as DOMRect,
|
||||
},
|
||||
],
|
||||
({} as unknown) as ResizeObserver,
|
||||
);
|
||||
await sleep(20);
|
||||
|
||||
expect(updateCalled).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2,6 +2,7 @@
|
||||
category: Components
|
||||
type: Navigation
|
||||
title: Affix
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/SQGCQ7gOO/Affix.svg
|
||||
---
|
||||
|
||||
Wrap Affix around another component to make it stick the viewport.
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import ResizeObserver from 'rc-resize-observer';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext, ConfigConsumerProps } from '../config-provider';
|
||||
import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationFrame';
|
||||
|
||||
import {
|
||||
@@ -32,7 +32,7 @@ export interface AffixProps {
|
||||
target?: () => Window | HTMLElement | null;
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
children: React.ReactElement;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
enum AffixStatus {
|
||||
@@ -50,9 +50,7 @@ export interface AffixState {
|
||||
}
|
||||
|
||||
class Affix extends React.Component<AffixProps, AffixState> {
|
||||
static defaultProps = {
|
||||
target: getDefaultTarget,
|
||||
};
|
||||
static contextType = ConfigContext;
|
||||
|
||||
state: AffixState = {
|
||||
status: AffixStatus.None,
|
||||
@@ -66,14 +64,27 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
|
||||
private timeout: number;
|
||||
|
||||
context: ConfigConsumerProps;
|
||||
|
||||
private getTargetFunc() {
|
||||
const { getTargetContainer } = this.context;
|
||||
const { target } = this.props;
|
||||
|
||||
if (target !== undefined) {
|
||||
return target;
|
||||
}
|
||||
|
||||
return getTargetContainer || getDefaultTarget;
|
||||
}
|
||||
|
||||
// Event handler
|
||||
componentDidMount() {
|
||||
const { target } = this.props;
|
||||
if (target) {
|
||||
const targetFunc = this.getTargetFunc();
|
||||
if (targetFunc) {
|
||||
// [Legacy] Wait for parent component ref has its value.
|
||||
// We should use target as directly element instead of function which makes element check hard.
|
||||
this.timeout = setTimeout(() => {
|
||||
addObserveTarget(target(), this);
|
||||
addObserveTarget(targetFunc(), this);
|
||||
// Mock Event object.
|
||||
this.updatePosition();
|
||||
});
|
||||
@@ -82,10 +93,10 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
|
||||
componentDidUpdate(prevProps: AffixProps) {
|
||||
const { prevTarget } = this.state;
|
||||
const { target } = this.props;
|
||||
const targetFunc = this.getTargetFunc();
|
||||
let newTarget = null;
|
||||
if (target) {
|
||||
newTarget = target() || null;
|
||||
if (targetFunc) {
|
||||
newTarget = targetFunc() || null;
|
||||
}
|
||||
|
||||
if (prevTarget !== newTarget) {
|
||||
@@ -141,15 +152,16 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
// =================== Measure ===================
|
||||
measure = () => {
|
||||
const { status, lastAffix } = this.state;
|
||||
const { target, onChange } = this.props;
|
||||
if (status !== AffixStatus.Prepare || !this.fixedNode || !this.placeholderNode || !target) {
|
||||
const { onChange } = this.props;
|
||||
const targetFunc = this.getTargetFunc();
|
||||
if (status !== AffixStatus.Prepare || !this.fixedNode || !this.placeholderNode || !targetFunc) {
|
||||
return;
|
||||
}
|
||||
|
||||
const offsetTop = this.getOffsetTop();
|
||||
const offsetBottom = this.getOffsetBottom();
|
||||
|
||||
const targetNode = target();
|
||||
const targetNode = targetFunc();
|
||||
if (!targetNode) {
|
||||
return;
|
||||
}
|
||||
@@ -220,15 +232,15 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
|
||||
@throttleByAnimationFrameDecorator()
|
||||
lazyUpdatePosition() {
|
||||
const { target } = this.props;
|
||||
const targetFunc = this.getTargetFunc();
|
||||
const { affixStyle } = this.state;
|
||||
|
||||
// Check position change before measure to make Safari smooth
|
||||
if (target && affixStyle) {
|
||||
if (targetFunc && affixStyle) {
|
||||
const offsetTop = this.getOffsetTop();
|
||||
const offsetBottom = this.getOffsetBottom();
|
||||
|
||||
const targetNode = target();
|
||||
const targetNode = targetFunc();
|
||||
if (targetNode && this.placeholderNode) {
|
||||
const targetRect = getTargetRect(targetNode);
|
||||
const placeholderReact = getTargetRect(this.placeholderNode);
|
||||
@@ -249,7 +261,8 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
}
|
||||
|
||||
// =================== Render ===================
|
||||
renderAffix = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
render = () => {
|
||||
const { getPrefixCls } = this.context;
|
||||
const { affixStyle, placeholderStyle } = this.state;
|
||||
const { prefixCls, children } = this.props;
|
||||
const className = classNames({
|
||||
@@ -283,10 +296,6 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
</ResizeObserver>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderAffix}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
|
||||
export default Affix;
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
subtitle: 固钉
|
||||
type: 导航
|
||||
title: Affix
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/SQGCQ7gOO/Affix.svg
|
||||
---
|
||||
|
||||
将页面元素钉在可视范围。
|
||||
|
||||
@@ -163,7 +163,7 @@ exports[`renders ./components/alert/demo/basic.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/closable.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-closable"
|
||||
data-show="true"
|
||||
@@ -202,7 +202,7 @@ exports[`renders ./components/alert/demo/closable.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon ant-alert-closable"
|
||||
data-show="true"
|
||||
@@ -243,8 +243,8 @@ exports[`renders ./components/alert/demo/closable.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/close-text.md correctly 1`] = `
|
||||
@@ -275,7 +275,7 @@ exports[`renders ./components/alert/demo/close-text.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-alert ant-alert-success ant-alert-no-icon"
|
||||
data-show="true"
|
||||
@@ -288,7 +288,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-success"
|
||||
data-show="true"
|
||||
@@ -321,7 +321,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-info"
|
||||
data-show="true"
|
||||
@@ -354,7 +354,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-warning"
|
||||
data-show="true"
|
||||
@@ -387,7 +387,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-error"
|
||||
data-show="true"
|
||||
@@ -420,7 +420,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-success ant-alert-with-description"
|
||||
data-show="true"
|
||||
@@ -455,7 +455,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
>
|
||||
Detailed description and advices about successful copywriting.
|
||||
</span>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-info ant-alert-with-description"
|
||||
data-show="true"
|
||||
@@ -490,7 +490,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
>
|
||||
Additional description and informations about copywriting.
|
||||
</span>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-with-description"
|
||||
data-show="true"
|
||||
@@ -525,7 +525,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
>
|
||||
This is a warning notice about copywriting.
|
||||
</span>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-error ant-alert-with-description"
|
||||
data-show="true"
|
||||
@@ -560,12 +560,12 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
>
|
||||
This is an error message about copywriting.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/description.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-alert ant-alert-success ant-alert-with-description ant-alert-no-icon"
|
||||
data-show="true"
|
||||
@@ -580,7 +580,7 @@ exports[`renders ./components/alert/demo/description.md correctly 1`] = `
|
||||
>
|
||||
Success Description Success Description Success Description
|
||||
</span>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-info ant-alert-with-description ant-alert-no-icon"
|
||||
data-show="true"
|
||||
@@ -595,7 +595,7 @@ exports[`renders ./components/alert/demo/description.md correctly 1`] = `
|
||||
>
|
||||
Info Description Info Description Info Description Info Description
|
||||
</span>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-with-description ant-alert-no-icon"
|
||||
data-show="true"
|
||||
@@ -610,7 +610,7 @@ exports[`renders ./components/alert/demo/description.md correctly 1`] = `
|
||||
>
|
||||
Warning Description Warning Description Warning Description Warning Description
|
||||
</span>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon"
|
||||
data-show="true"
|
||||
@@ -625,8 +625,8 @@ exports[`renders ./components/alert/demo/description.md correctly 1`] = `
|
||||
>
|
||||
Error Description Error Description Error Description Error Description
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/error-boundary.md correctly 1`] = `
|
||||
@@ -641,7 +641,7 @@ exports[`renders ./components/alert/demo/error-boundary.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-alert ant-alert-success"
|
||||
data-show="true"
|
||||
@@ -674,7 +674,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-info"
|
||||
data-show="true"
|
||||
@@ -707,9 +707,9 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-warning"
|
||||
class="ant-alert ant-alert-warning ant-alert-closable"
|
||||
data-show="true"
|
||||
>
|
||||
<span
|
||||
@@ -740,7 +740,33 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
class="ant-alert-close-icon"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="close"
|
||||
class="anticon anticon-close"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="close"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-error"
|
||||
data-show="true"
|
||||
@@ -773,7 +799,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-success ant-alert-with-description"
|
||||
data-show="true"
|
||||
@@ -811,7 +837,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
>
|
||||
Detailed description and advice about successful copywriting.
|
||||
</span>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-info ant-alert-with-description"
|
||||
data-show="true"
|
||||
@@ -849,9 +875,9 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
>
|
||||
Additional description and information about copywriting.
|
||||
</span>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-with-description"
|
||||
class="ant-alert ant-alert-warning ant-alert-with-description ant-alert-closable"
|
||||
data-show="true"
|
||||
>
|
||||
<span
|
||||
@@ -887,7 +913,33 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
>
|
||||
This is a warning notice about copywriting.
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
class="ant-alert-close-icon"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="close"
|
||||
class="anticon anticon-close"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="close"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-error ant-alert-with-description"
|
||||
data-show="true"
|
||||
@@ -925,8 +977,8 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
>
|
||||
This is an error message about copywriting.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/loop-banner.md correctly 1`] = `
|
||||
@@ -1028,7 +1080,7 @@ exports[`renders ./components/alert/demo/smooth-closed.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/style.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-alert ant-alert-success ant-alert-no-icon"
|
||||
data-show="true"
|
||||
@@ -1041,7 +1093,7 @@ exports[`renders ./components/alert/demo/style.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-info ant-alert-no-icon"
|
||||
data-show="true"
|
||||
@@ -1054,7 +1106,7 @@ exports[`renders ./components/alert/demo/style.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-no-icon"
|
||||
data-show="true"
|
||||
@@ -1067,7 +1119,7 @@ exports[`renders ./components/alert/demo/style.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-error ant-alert-no-icon"
|
||||
data-show="true"
|
||||
@@ -1080,6 +1132,6 @@ exports[`renders ./components/alert/demo/style.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
@@ -22,6 +22,27 @@ exports[`Alert ErrorBoundary 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Alert could accept none react element icon 1`] = `
|
||||
<div
|
||||
class="ant-alert ant-alert-success"
|
||||
data-show="true"
|
||||
>
|
||||
<span
|
||||
class="ant-alert-icon"
|
||||
>
|
||||
icon
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Success Tips
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Alert rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-alert ant-alert-info ant-alert-no-icon ant-alert-rtl"
|
||||
@@ -39,20 +39,20 @@ describe('Alert', () => {
|
||||
|
||||
describe('data and aria props', () => {
|
||||
it('sets data attributes on input', () => {
|
||||
const wrapper = mount(<Alert data-test="test-id" data-id="12345" />);
|
||||
const wrapper = mount(<Alert data-test="test-id" data-id="12345" message={null} />);
|
||||
const input = wrapper.find('.ant-alert').getDOMNode();
|
||||
expect(input.getAttribute('data-test')).toBe('test-id');
|
||||
expect(input.getAttribute('data-id')).toBe('12345');
|
||||
});
|
||||
|
||||
it('sets aria attributes on input', () => {
|
||||
const wrapper = mount(<Alert aria-describedby="some-label" />);
|
||||
const wrapper = mount(<Alert aria-describedby="some-label" message={null} />);
|
||||
const input = wrapper.find('.ant-alert').getDOMNode();
|
||||
expect(input.getAttribute('aria-describedby')).toBe('some-label');
|
||||
});
|
||||
|
||||
it('sets role attribute on input', () => {
|
||||
const wrapper = mount(<Alert role="status" />);
|
||||
const wrapper = mount(<Alert role="status" message={null} />);
|
||||
const input = wrapper.find('.ant-alert').getDOMNode();
|
||||
expect(input.getAttribute('role')).toBe('status');
|
||||
});
|
||||
@@ -60,6 +60,7 @@ describe('Alert', () => {
|
||||
|
||||
const testIt = process.env.REACT === '15' ? it.skip : it;
|
||||
testIt('ErrorBoundary', () => {
|
||||
// @ts-expect-error
|
||||
// eslint-disable-next-line react/jsx-no-undef
|
||||
const ThrowError = () => <NotExisted />;
|
||||
const wrapper = mount(
|
||||
@@ -72,9 +73,10 @@ describe('Alert', () => {
|
||||
});
|
||||
|
||||
it('could be used with Tooltip', async () => {
|
||||
const ref = React.createRef<any>();
|
||||
jest.useRealTimers();
|
||||
const wrapper = mount(
|
||||
<Tooltip title="xxx" mouseEnterDelay={0}>
|
||||
<Tooltip title="xxx" mouseEnterDelay={0} ref={ref}>
|
||||
<Alert
|
||||
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
||||
type="warning"
|
||||
@@ -83,19 +85,15 @@ describe('Alert', () => {
|
||||
);
|
||||
wrapper.find('.ant-alert').simulate('mouseenter');
|
||||
await sleep(0);
|
||||
expect(
|
||||
wrapper
|
||||
.find(Tooltip)
|
||||
.instance()
|
||||
.getPopupDomNode(),
|
||||
).toBeTruthy();
|
||||
expect(ref.current.getPopupDomNode()).toBeTruthy();
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
it('could be used with Popconfirm', async () => {
|
||||
const ref = React.createRef<any>();
|
||||
jest.useRealTimers();
|
||||
const wrapper = mount(
|
||||
<Popconfirm title="xxx">
|
||||
<Popconfirm ref={ref} title="xxx">
|
||||
<Alert
|
||||
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
||||
type="warning"
|
||||
@@ -104,12 +102,12 @@ describe('Alert', () => {
|
||||
);
|
||||
wrapper.find('.ant-alert').simulate('click');
|
||||
await sleep(0);
|
||||
expect(
|
||||
wrapper
|
||||
.find(Popconfirm)
|
||||
.instance()
|
||||
.getPopupDomNode(),
|
||||
).toBeTruthy();
|
||||
expect(ref.current.getPopupDomNode()).toBeTruthy();
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
it('could accept none react element icon', () => {
|
||||
const wrapper = mount(<Alert message="Success Tips" type="success" showIcon icon="icon" />);
|
||||
expect(wrapper).toMatchRenderedSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -21,7 +21,7 @@ const onClose = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<Alert
|
||||
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
||||
type="warning"
|
||||
@@ -35,7 +35,7 @@ ReactDOM.render(
|
||||
closable
|
||||
onClose={onClose}
|
||||
/>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
@@ -21,7 +21,7 @@ import { SmileOutlined } from '@ant-design/icons';
|
||||
const icon = <SmileOutlined />;
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<Alert icon={icon} message="showIcon = false" type="success" />
|
||||
<Alert icon={icon} message="Success Tips" type="success" showIcon />
|
||||
<Alert icon={icon} message="Informational Notes" type="info" showIcon />
|
||||
@@ -55,7 +55,7 @@ ReactDOM.render(
|
||||
type="error"
|
||||
showIcon
|
||||
/>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
@@ -17,7 +17,7 @@ Additional description for alert message.
|
||||
import { Alert } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<Alert
|
||||
message="Success Text"
|
||||
description="Success Description Success Description Success Description"
|
||||
@@ -38,7 +38,7 @@ ReactDOM.render(
|
||||
description="Error Description Error Description Error Description Error Description"
|
||||
type="error"
|
||||
/>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
@@ -17,10 +17,10 @@ A relevant icon will make information clearer and more friendly.
|
||||
import { Alert } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<Alert message="Success Tips" type="success" showIcon />
|
||||
<Alert message="Informational Notes" type="info" showIcon />
|
||||
<Alert message="Warning" type="warning" showIcon />
|
||||
<Alert message="Warning" type="warning" showIcon closable />
|
||||
<Alert message="Error" type="error" showIcon />
|
||||
<Alert
|
||||
message="Success Tips"
|
||||
@@ -39,6 +39,7 @@ ReactDOM.render(
|
||||
description="This is a warning notice about copywriting."
|
||||
type="warning"
|
||||
showIcon
|
||||
closable
|
||||
/>
|
||||
<Alert
|
||||
message="Error"
|
||||
@@ -46,7 +47,7 @@ ReactDOM.render(
|
||||
type="error"
|
||||
showIcon
|
||||
/>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
@@ -17,12 +17,18 @@ There are 4 types of Alert: `success`, `info`, `warning`, `error`.
|
||||
import { Alert } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<Alert message="Success Text" type="success" />
|
||||
<Alert message="Info Text" type="info" />
|
||||
<Alert message="Warning Text" type="warning" />
|
||||
<Alert message="Error Text" type="error" />
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
<style>
|
||||
[data-theme="compact"] .code-box-demo .ant-alert {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
category: Components
|
||||
type: Feedback
|
||||
title: Alert
|
||||
cover: https://gw.alipayobjects.com/zos/antfincdn/nuhf3vdRno/Alert.svg
|
||||
---
|
||||
|
||||
Alert component for feedback.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import CloseOutlined from '@ant-design/icons/CloseOutlined';
|
||||
import CheckCircleOutlined from '@ant-design/icons/CheckCircleOutlined';
|
||||
import ExclamationCircleOutlined from '@ant-design/icons/ExclamationCircleOutlined';
|
||||
@@ -12,11 +11,10 @@ import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
|
||||
import Animate from 'rc-animate';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import getDataOrAriaProps from '../_util/getDataOrAriaProps';
|
||||
import ErrorBoundary from './ErrorBoundary';
|
||||
|
||||
function noop() {}
|
||||
import { replaceElement } from '../_util/reactNode';
|
||||
|
||||
export interface AlertProps {
|
||||
/**
|
||||
@@ -37,6 +35,8 @@ export interface AlertProps {
|
||||
afterClose?: () => void;
|
||||
/** Whether to show icon */
|
||||
showIcon?: boolean;
|
||||
/** https://www.w3.org/TR/2014/REC-html5-20141028/dom.html#aria-role-attribute */
|
||||
role?: string;
|
||||
style?: React.CSSProperties;
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
@@ -47,11 +47,6 @@ export interface AlertProps {
|
||||
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
||||
}
|
||||
|
||||
export interface AlertState {
|
||||
closing: boolean;
|
||||
closed: boolean;
|
||||
}
|
||||
|
||||
const iconMapFilled = {
|
||||
success: CheckCircleFilled,
|
||||
info: InfoCircleFilled,
|
||||
@@ -66,86 +61,82 @@ const iconMapOutlined = {
|
||||
warning: ExclamationCircleOutlined,
|
||||
};
|
||||
|
||||
export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
static ErrorBoundary = ErrorBoundary;
|
||||
interface AlertInterface extends React.FC<AlertProps> {
|
||||
ErrorBoundary: typeof ErrorBoundary;
|
||||
}
|
||||
|
||||
state = {
|
||||
closing: false,
|
||||
closed: false,
|
||||
};
|
||||
const Alert: AlertInterface = ({
|
||||
description,
|
||||
prefixCls: customizePrefixCls,
|
||||
message,
|
||||
banner,
|
||||
className = '',
|
||||
style,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
onClick,
|
||||
showIcon,
|
||||
closable,
|
||||
closeText,
|
||||
...props
|
||||
}) => {
|
||||
const [closing, setClosing] = React.useState(false);
|
||||
const [closed, setClosed] = React.useState(false);
|
||||
|
||||
handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const ref = React.useRef<HTMLElement>();
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('alert', customizePrefixCls);
|
||||
|
||||
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
const dom = ReactDOM.findDOMNode(this) as HTMLElement;
|
||||
const dom = ref.current as HTMLElement;
|
||||
dom.style.height = `${dom.offsetHeight}px`;
|
||||
// Magic code
|
||||
// 重复一次后才能正确设置 height
|
||||
dom.style.height = `${dom.offsetHeight}px`;
|
||||
|
||||
this.setState({
|
||||
closing: true,
|
||||
});
|
||||
(this.props.onClose || noop)(e);
|
||||
setClosing(true);
|
||||
props.onClose?.(e);
|
||||
};
|
||||
|
||||
animationEnd = () => {
|
||||
this.setState({
|
||||
closing: false,
|
||||
closed: true,
|
||||
});
|
||||
(this.props.afterClose || noop)();
|
||||
const animationEnd = () => {
|
||||
setClosing(false);
|
||||
setClosed(true);
|
||||
props.afterClose?.();
|
||||
};
|
||||
|
||||
renderAlert = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
description,
|
||||
prefixCls: customizePrefixCls,
|
||||
message,
|
||||
closeText,
|
||||
banner,
|
||||
className = '',
|
||||
style,
|
||||
icon,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
onClick,
|
||||
} = this.props;
|
||||
let { closable, type, showIcon } = this.props;
|
||||
const { closing, closed } = this.state;
|
||||
const getType = () => {
|
||||
const { type } = props;
|
||||
if (type !== undefined) {
|
||||
return type;
|
||||
}
|
||||
// banner 模式默认为警告
|
||||
return banner ? 'warning' : 'info';
|
||||
};
|
||||
|
||||
const prefixCls = getPrefixCls('alert', customizePrefixCls);
|
||||
|
||||
// banner模式默认有 Icon
|
||||
showIcon = banner && showIcon === undefined ? true : showIcon;
|
||||
// banner模式默认为警告
|
||||
type = banner && type === undefined ? 'warning' : type || 'info';
|
||||
// closeable when closeText is assigned
|
||||
const isClosable = closeText ? true : closable;
|
||||
const type = getType();
|
||||
|
||||
const renderIconNode = () => {
|
||||
const { icon } = props;
|
||||
// use outline icon in alert with description
|
||||
const iconType = (description ? iconMapOutlined : iconMapFilled)[type] || null;
|
||||
|
||||
// closeable when closeText is assigned
|
||||
if (closeText) {
|
||||
closable = true;
|
||||
if (icon) {
|
||||
return replaceElement(icon, <span className={`${prefixCls}-icon`}>{icon}</span>, () => ({
|
||||
className: classNames(`${prefixCls}-icon`, {
|
||||
[(icon as any).props.className]: (icon as any).props.className,
|
||||
}),
|
||||
}));
|
||||
}
|
||||
return React.createElement(iconType, { className: `${prefixCls}-icon` });
|
||||
};
|
||||
|
||||
const alertCls = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-${type}`,
|
||||
{
|
||||
[`${prefixCls}-closing`]: closing,
|
||||
[`${prefixCls}-with-description`]: !!description,
|
||||
[`${prefixCls}-no-icon`]: !showIcon,
|
||||
[`${prefixCls}-banner`]: !!banner,
|
||||
[`${prefixCls}-closable`]: closable,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
||||
const closeIcon = closable ? (
|
||||
const renderCloseIcon = () => {
|
||||
return isClosable ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={this.handleClose}
|
||||
onClick={handleClose}
|
||||
className={`${prefixCls}-close-icon`}
|
||||
tabIndex={0}
|
||||
>
|
||||
@@ -156,48 +147,53 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
)}
|
||||
</button>
|
||||
) : null;
|
||||
|
||||
const dataOrAriaProps = getDataOrAriaProps(this.props);
|
||||
|
||||
const iconNode =
|
||||
(icon &&
|
||||
(React.isValidElement<{ className?: string }>(icon) ? (
|
||||
React.cloneElement(icon, {
|
||||
className: classNames(`${prefixCls}-icon`, {
|
||||
[icon.props.className as string]: icon.props.className,
|
||||
}),
|
||||
})
|
||||
) : (
|
||||
<span className={`${prefixCls}-icon`}>{icon}</span>
|
||||
))) ||
|
||||
React.createElement(iconType, { className: `${prefixCls}-icon` });
|
||||
|
||||
return closed ? null : (
|
||||
<Animate
|
||||
component=""
|
||||
showProp="data-show"
|
||||
transitionName={`${prefixCls}-slide-up`}
|
||||
onEnd={this.animationEnd}
|
||||
>
|
||||
<div
|
||||
data-show={!closing}
|
||||
className={alertCls}
|
||||
style={style}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={onClick}
|
||||
{...dataOrAriaProps}
|
||||
>
|
||||
{showIcon ? iconNode : null}
|
||||
<span className={`${prefixCls}-message`}>{message}</span>
|
||||
<span className={`${prefixCls}-description`}>{description}</span>
|
||||
{closeIcon}
|
||||
</div>
|
||||
</Animate>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderAlert}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
// banner 模式默认有 Icon
|
||||
const isShowIcon = banner && showIcon === undefined ? true : showIcon;
|
||||
|
||||
const alertCls = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-${type}`,
|
||||
{
|
||||
[`${prefixCls}-closing`]: closing,
|
||||
[`${prefixCls}-with-description`]: !!description,
|
||||
[`${prefixCls}-no-icon`]: !isShowIcon,
|
||||
[`${prefixCls}-banner`]: !!banner,
|
||||
[`${prefixCls}-closable`]: isClosable,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
||||
const dataOrAriaProps = getDataOrAriaProps(props);
|
||||
|
||||
return closed ? null : (
|
||||
<Animate
|
||||
component=""
|
||||
showProp="data-show"
|
||||
transitionName={`${prefixCls}-slide-up`}
|
||||
onEnd={animationEnd}
|
||||
>
|
||||
<div
|
||||
ref={ref}
|
||||
data-show={!closing}
|
||||
className={alertCls}
|
||||
style={style}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={onClick}
|
||||
{...dataOrAriaProps}
|
||||
>
|
||||
{isShowIcon ? renderIconNode() : null}
|
||||
<span className={`${prefixCls}-message`}>{message}</span>
|
||||
<span className={`${prefixCls}-description`}>{description}</span>
|
||||
{renderCloseIcon()}
|
||||
</div>
|
||||
</Animate>
|
||||
);
|
||||
};
|
||||
|
||||
Alert.ErrorBoundary = ErrorBoundary;
|
||||
|
||||
export default Alert;
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
subtitle: 警告提示
|
||||
type: 反馈
|
||||
title: Alert
|
||||
cover: https://gw.alipayobjects.com/zos/antfincdn/nuhf3vdRno/Alert.svg
|
||||
---
|
||||
|
||||
警告提示,展现需要关注的信息。
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
|
||||
&&-no-icon {
|
||||
padding: @alert-no-icon-padding-vertical 15px;
|
||||
.@{alert-prefix-cls}-close-icon {
|
||||
top: @alert-no-icon-padding-vertical + @font-size-base * @line-height-base / 2 -
|
||||
@font-size-base / 2;
|
||||
}
|
||||
}
|
||||
|
||||
&&-closable {
|
||||
@@ -21,14 +25,14 @@
|
||||
|
||||
&-icon {
|
||||
position: absolute;
|
||||
top: 8px + @font-size-base * @line-height-base / 2 - @font-size-base / 2;
|
||||
top: @alert-icon-top;
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
&-description {
|
||||
display: none;
|
||||
font-size: @font-size-base;
|
||||
line-height: 22px;
|
||||
line-height: @font-size-base + 8px;
|
||||
}
|
||||
|
||||
&-success {
|
||||
@@ -71,12 +75,12 @@
|
||||
|
||||
&-close-icon {
|
||||
position: absolute;
|
||||
top: @padding-xs;
|
||||
right: 16px;
|
||||
top: 8px + @font-size-base * @line-height-base / 2 - @font-size-base / 2;
|
||||
right: @padding-md;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
font-size: @font-size-sm;
|
||||
line-height: 22px;
|
||||
line-height: @font-size-sm;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
@@ -101,7 +105,7 @@
|
||||
|
||||
&-with-description {
|
||||
position: relative;
|
||||
padding: 15px 15px 15px 64px;
|
||||
padding: @alert-with-description-padding;
|
||||
color: @alert-text-color;
|
||||
line-height: @line-height-base;
|
||||
border-radius: @border-radius-base;
|
||||
@@ -113,15 +117,15 @@
|
||||
|
||||
&-with-description &-icon {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 24px;
|
||||
font-size: 24px;
|
||||
top: @alert-with-description-icon-top;
|
||||
left: @alert-with-description-icon-size;
|
||||
font-size: @alert-with-description-icon-size;
|
||||
}
|
||||
|
||||
&-with-description &-close-icon {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
top: @padding-md;
|
||||
right: @padding-md;
|
||||
font-size: @font-size-base;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -188,4 +192,4 @@
|
||||
}
|
||||
}
|
||||
|
||||
@import './rtl.less';
|
||||
@import './rtl';
|
||||
|
||||
@@ -4,13 +4,26 @@
|
||||
@alert-prefix-cls: ~'@{ant-prefix}-alert';
|
||||
|
||||
.@{alert-prefix-cls} {
|
||||
&-rtl {
|
||||
&&-rtl {
|
||||
padding: 8px 37px 8px 15px;
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&&-closable {
|
||||
&&-no-icon {
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
padding: @alert-no-icon-padding-vertical 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&&-closable {
|
||||
.@{alert-prefix-cls}.@{alert-prefix-cls}-rtl& {
|
||||
padding-right: 37px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
&&-no-icon&-closable {
|
||||
.@{alert-prefix-cls}.@{alert-prefix-cls}-rtl& {
|
||||
padding-right: 15px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
@@ -18,7 +31,7 @@
|
||||
|
||||
&-icon {
|
||||
.@{alert-prefix-cls}-rtl & {
|
||||
right: 16px;
|
||||
right: @padding-md;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
@@ -26,25 +39,28 @@
|
||||
&-close-icon {
|
||||
.@{alert-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 16px;
|
||||
left: @padding-md;
|
||||
}
|
||||
}
|
||||
|
||||
&-with-description {
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
padding: 15px 64px 15px 15px;
|
||||
&-with-description,
|
||||
&-with-description&-closable {
|
||||
.@{alert-prefix-cls}.@{alert-prefix-cls}-rtl& {
|
||||
padding: @alert-with-description-padding-vertical @alert-with-description-icon-size * 2 +
|
||||
@alert-with-description-padding-vertical @alert-with-description-no-icon-padding-vertical
|
||||
15px;
|
||||
}
|
||||
}
|
||||
|
||||
&-with-description&-no-icon {
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
.@{alert-prefix-cls}.@{alert-prefix-cls}-rtl& {
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&-with-description &-icon {
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
right: 24px;
|
||||
right: @alert-with-description-icon-size;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
@@ -52,7 +68,7 @@
|
||||
&-with-description &-close-icon {
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
right: auto;
|
||||
left: 16px;
|
||||
left: @padding-md;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import Affix from '../affix';
|
||||
import AnchorLink from './AnchorLink';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext, ConfigConsumerProps } from '../config-provider';
|
||||
import scrollTo from '../_util/scrollTo';
|
||||
import getScroll from '../_util/getScroll';
|
||||
import AnchorContext from './context';
|
||||
|
||||
function getDefaultContainer() {
|
||||
return window;
|
||||
}
|
||||
|
||||
function getOffsetTop(element: HTMLElement, container: AnchorContainer): number {
|
||||
if (!element) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!element.getClientRects().length) {
|
||||
return 0;
|
||||
}
|
||||
@@ -35,7 +31,7 @@ function getOffsetTop(element: HTMLElement, container: AnchorContainer): number
|
||||
return rect.top;
|
||||
}
|
||||
|
||||
const sharpMatcherRegx = /#([^#]+)$/;
|
||||
const sharpMatcherRegx = /#(\S+)$/;
|
||||
|
||||
type Section = {
|
||||
link: string;
|
||||
@@ -88,23 +84,22 @@ export interface AntAnchor {
|
||||
) => void;
|
||||
}
|
||||
|
||||
export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
export default class Anchor extends React.Component<AnchorProps, AnchorState, ConfigConsumerProps> {
|
||||
static Link: typeof AnchorLink;
|
||||
|
||||
static defaultProps = {
|
||||
affix: true,
|
||||
showInkInFixed: false,
|
||||
getContainer: getDefaultContainer,
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
antAnchor: PropTypes.object,
|
||||
};
|
||||
static contextType = ConfigContext;
|
||||
|
||||
state = {
|
||||
activeLink: null,
|
||||
};
|
||||
|
||||
content: ConfigConsumerProps;
|
||||
|
||||
private inkNode: HTMLSpanElement;
|
||||
|
||||
// scroll scope's container
|
||||
@@ -118,37 +113,38 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
|
||||
private prefixCls?: string;
|
||||
|
||||
getChildContext() {
|
||||
const antAnchor: AntAnchor = {
|
||||
registerLink: (link: string) => {
|
||||
if (!this.links.includes(link)) {
|
||||
this.links.push(link);
|
||||
}
|
||||
},
|
||||
unregisterLink: (link: string) => {
|
||||
const index = this.links.indexOf(link);
|
||||
if (index !== -1) {
|
||||
this.links.splice(index, 1);
|
||||
}
|
||||
},
|
||||
activeLink: this.state.activeLink,
|
||||
scrollTo: this.handleScrollTo,
|
||||
onClick: this.props.onClick,
|
||||
};
|
||||
return { antAnchor };
|
||||
}
|
||||
// Context
|
||||
registerLink = (link: string) => {
|
||||
if (!this.links.includes(link)) {
|
||||
this.links.push(link);
|
||||
}
|
||||
};
|
||||
|
||||
unregisterLink = (link: string) => {
|
||||
const index = this.links.indexOf(link);
|
||||
if (index !== -1) {
|
||||
this.links.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
getContainer = () => {
|
||||
const { getTargetContainer } = this.context;
|
||||
const { getContainer } = this.props;
|
||||
|
||||
const getFunc = getContainer || getTargetContainer || getDefaultContainer;
|
||||
|
||||
return getFunc();
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { getContainer } = this.props as AnchorDefaultProps;
|
||||
this.scrollContainer = getContainer();
|
||||
this.scrollContainer = this.getContainer();
|
||||
this.scrollEvent = addEventListener(this.scrollContainer, 'scroll', this.handleScroll);
|
||||
this.handleScroll();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.scrollEvent) {
|
||||
const { getContainer } = this.props as AnchorDefaultProps;
|
||||
const currentContainer = getContainer();
|
||||
const currentContainer = this.getContainer();
|
||||
if (this.scrollContainer !== currentContainer) {
|
||||
this.scrollContainer = currentContainer;
|
||||
this.scrollEvent.remove();
|
||||
@@ -172,14 +168,8 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
return getCurrentAnchor();
|
||||
}
|
||||
|
||||
const activeLink = '';
|
||||
if (typeof document === 'undefined') {
|
||||
return activeLink;
|
||||
}
|
||||
|
||||
const linkSections: Array<Section> = [];
|
||||
const { getContainer } = this.props as AnchorDefaultProps;
|
||||
const container = getContainer();
|
||||
const container = this.getContainer();
|
||||
this.links.forEach(link => {
|
||||
const sharpLinkMatch = sharpMatcherRegx.exec(link.toString());
|
||||
if (!sharpLinkMatch) {
|
||||
@@ -205,10 +195,10 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
}
|
||||
|
||||
handleScrollTo = (link: string) => {
|
||||
const { offsetTop, getContainer, targetOffset } = this.props as AnchorDefaultProps;
|
||||
const { offsetTop, targetOffset } = this.props;
|
||||
|
||||
this.setCurrentActiveLink(link);
|
||||
const container = getContainer();
|
||||
const container = this.getContainer();
|
||||
const scrollTop = getScroll(container, true);
|
||||
const sharpLinkMatch = sharpMatcherRegx.exec(link);
|
||||
if (!sharpLinkMatch) {
|
||||
@@ -228,7 +218,7 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
callback: () => {
|
||||
this.animating = false;
|
||||
},
|
||||
getContainer,
|
||||
getContainer: this.getContainer,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -263,9 +253,6 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
};
|
||||
|
||||
updateInk = () => {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
const { prefixCls } = this;
|
||||
const anchorNode = ReactDOM.findDOMNode(this) as Element;
|
||||
const linkNode = anchorNode.getElementsByClassName(`${prefixCls}-link-title-active`)[0];
|
||||
@@ -274,7 +261,9 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
}
|
||||
};
|
||||
|
||||
renderAnchor = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
render = () => {
|
||||
const { getPrefixCls, direction } = this.context;
|
||||
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className = '',
|
||||
@@ -283,7 +272,6 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
affix,
|
||||
showInkInFixed,
|
||||
children,
|
||||
getContainer,
|
||||
} = this.props;
|
||||
const { activeLink } = this.state;
|
||||
|
||||
@@ -322,16 +310,24 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
</div>
|
||||
);
|
||||
|
||||
return !affix ? (
|
||||
anchorContent
|
||||
) : (
|
||||
<Affix offsetTop={offsetTop} target={getContainer}>
|
||||
{anchorContent}
|
||||
</Affix>
|
||||
return (
|
||||
<AnchorContext.Provider
|
||||
value={{
|
||||
registerLink: this.registerLink,
|
||||
unregisterLink: this.unregisterLink,
|
||||
activeLink: this.state.activeLink,
|
||||
scrollTo: this.handleScrollTo,
|
||||
onClick: this.props.onClick,
|
||||
}}
|
||||
>
|
||||
{!affix ? (
|
||||
anchorContent
|
||||
) : (
|
||||
<Affix offsetTop={offsetTop} target={this.getContainer}>
|
||||
{anchorContent}
|
||||
</Affix>
|
||||
)}
|
||||
</AnchorContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderAnchor}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { AntAnchor } from './Anchor';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import AnchorContext from './context';
|
||||
|
||||
export interface AnchorLinkProps {
|
||||
prefixCls?: string;
|
||||
@@ -13,37 +13,33 @@ export interface AnchorLinkProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
class AnchorLink extends React.Component<AnchorLinkProps, any> {
|
||||
class AnchorLink extends React.Component<AnchorLinkProps, any, AntAnchor> {
|
||||
static defaultProps = {
|
||||
href: '#',
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
antAnchor: PropTypes.object,
|
||||
};
|
||||
static contextType = AnchorContext;
|
||||
|
||||
context: {
|
||||
antAnchor: AntAnchor;
|
||||
};
|
||||
context: AntAnchor;
|
||||
|
||||
componentDidMount() {
|
||||
this.context.antAnchor.registerLink(this.props.href);
|
||||
this.context.registerLink(this.props.href);
|
||||
}
|
||||
|
||||
componentDidUpdate({ href: prevHref }: AnchorLinkProps) {
|
||||
const { href } = this.props;
|
||||
if (prevHref !== href) {
|
||||
this.context.antAnchor.unregisterLink(prevHref);
|
||||
this.context.antAnchor.registerLink(href);
|
||||
this.context.unregisterLink(prevHref);
|
||||
this.context.registerLink(href);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.context.antAnchor.unregisterLink(this.props.href);
|
||||
this.context.unregisterLink(this.props.href);
|
||||
}
|
||||
|
||||
handleClick = (e: React.MouseEvent<HTMLElement>) => {
|
||||
const { scrollTo, onClick } = this.context.antAnchor;
|
||||
const { scrollTo, onClick } = this.context;
|
||||
const { href, title } = this.props;
|
||||
if (onClick) {
|
||||
onClick(e, { title, href });
|
||||
@@ -54,7 +50,7 @@ class AnchorLink extends React.Component<AnchorLinkProps, any> {
|
||||
renderAnchorLink = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, href, title, children, className, target } = this.props;
|
||||
const prefixCls = getPrefixCls('anchor', customizePrefixCls);
|
||||
const active = this.context.antAnchor.activeLink === href;
|
||||
const active = this.context.activeLink === href;
|
||||
const wrapperClassName = classNames(className, `${prefixCls}-link`, {
|
||||
[`${prefixCls}-link-active`]: active,
|
||||
});
|
||||
|
||||
@@ -1,336 +0,0 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Anchor from '..';
|
||||
import { spyElementPrototypes } from '../../__tests__/util/domHook';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
|
||||
const { Link } = Anchor;
|
||||
|
||||
describe('Anchor Render', () => {
|
||||
const getBoundingClientRectMock = jest.fn(() => ({
|
||||
width: 100,
|
||||
height: 100,
|
||||
top: 1000,
|
||||
}));
|
||||
const getClientRectsMock = jest.fn(() => ({
|
||||
length: 1,
|
||||
}));
|
||||
const headingSpy = spyElementPrototypes(HTMLHeadingElement, {
|
||||
getBoundingClientRect: getBoundingClientRectMock,
|
||||
getClientRects: getClientRectsMock,
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
headingSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('Anchor render perfectly', () => {
|
||||
const wrapper = mount(
|
||||
<Anchor>
|
||||
<Link href="#API" title="API" />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.find('a[href="#API"]').simulate('click');
|
||||
|
||||
wrapper.instance().handleScroll();
|
||||
expect(wrapper.instance().state).not.toBe(null);
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - click', () => {
|
||||
const wrapper = mount(
|
||||
<Anchor>
|
||||
<Link href="http://www.example.com/#API" title="API" />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.find('a[href="http://www.example.com/#API"]').simulate('click');
|
||||
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - scroll', () => {
|
||||
let root = document.getElementById('root');
|
||||
if (!root) {
|
||||
root = document.createElement('div', { id: 'root' });
|
||||
root.id = 'root';
|
||||
document.body.appendChild(root);
|
||||
}
|
||||
mount(<div id="API">Hello</div>, { attachTo: root });
|
||||
const wrapper = mount(
|
||||
<Anchor>
|
||||
<Link href="http://www.example.com/#API" title="API" />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScroll();
|
||||
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
||||
});
|
||||
|
||||
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' });
|
||||
root.id = 'root';
|
||||
document.body.appendChild(root);
|
||||
}
|
||||
mount(<div id="API">Hello</div>, { attachTo: root });
|
||||
const wrapper = mount(
|
||||
<Anchor>
|
||||
<Link href="##API" title="API" />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo('##API');
|
||||
expect(wrapper.instance().state.activeLink).toBe('##API');
|
||||
expect(scrollToSpy).not.toHaveBeenCalled();
|
||||
await sleep(1000);
|
||||
expect(scrollToSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
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([]);
|
||||
});
|
||||
|
||||
it('should update links when link href update', async () => {
|
||||
let anchorInstance = null;
|
||||
function AnchorUpdate({ href }) {
|
||||
return (
|
||||
<Anchor
|
||||
ref={c => {
|
||||
anchorInstance = c;
|
||||
}}
|
||||
>
|
||||
<Link href={href} title="API" />
|
||||
</Anchor>
|
||||
);
|
||||
}
|
||||
const wrapper = mount(<AnchorUpdate href="#API" />);
|
||||
|
||||
expect(anchorInstance.links).toEqual(['#API']);
|
||||
wrapper.setProps({ href: '#API_1' });
|
||||
expect(anchorInstance.links).toEqual(['#API_1']);
|
||||
});
|
||||
|
||||
it('Anchor onClick event', () => {
|
||||
let event;
|
||||
let link;
|
||||
const handleClick = (...arg) => {
|
||||
[event, link] = arg;
|
||||
};
|
||||
|
||||
const href = '#API';
|
||||
const title = 'API';
|
||||
|
||||
const wrapper = mount(
|
||||
<Anchor onClick={handleClick}>
|
||||
<Link href={href} title={title} />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.find(`a[href="${href}"]`).simulate('click');
|
||||
|
||||
wrapper.instance().handleScroll();
|
||||
expect(event).not.toBe(undefined);
|
||||
expect(link).toEqual({ href, title });
|
||||
});
|
||||
|
||||
it('Different function returns the same DOM', async () => {
|
||||
let root = document.getElementById('root');
|
||||
if (!root) {
|
||||
root = document.createElement('div', { id: 'root' });
|
||||
root.id = 'root';
|
||||
document.body.appendChild(root);
|
||||
}
|
||||
mount(<div id="API">Hello</div>, { attachTo: root });
|
||||
const getContainerA = () => {
|
||||
return document.getElementById('API');
|
||||
};
|
||||
const getContainerB = () => {
|
||||
return document.getElementById('API');
|
||||
};
|
||||
|
||||
const wrapper = mount(
|
||||
<Anchor getContainer={getContainerA}>
|
||||
<Link href="#API" title="API" />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn(wrapper.instance().scrollEvent, 'remove');
|
||||
await sleep(1000);
|
||||
wrapper.setProps({ getContainer: getContainerB });
|
||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Different function returns different DOM', async () => {
|
||||
let root = document.getElementById('root');
|
||||
if (!root) {
|
||||
root = document.createElement('div', { id: 'root' });
|
||||
root.id = 'root';
|
||||
document.body.appendChild(root);
|
||||
}
|
||||
mount(
|
||||
<div>
|
||||
<div id="API1">Hello</div>
|
||||
<div id="API2">World</div>
|
||||
</div>,
|
||||
{ attachTo: root },
|
||||
);
|
||||
const getContainerA = () => {
|
||||
return document.getElementById('API1');
|
||||
};
|
||||
const getContainerB = () => {
|
||||
return document.getElementById('API2');
|
||||
};
|
||||
const wrapper = mount(
|
||||
<Anchor getContainer={getContainerA}>
|
||||
<Link href="#API1" title="API1" />
|
||||
<Link href="#API2" title="API2" />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn(wrapper.instance().scrollEvent, 'remove');
|
||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||
await sleep(1000);
|
||||
wrapper.setProps({ getContainer: getContainerB });
|
||||
expect(removeListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Same function returns the same DOM', () => {
|
||||
let root = document.getElementById('root');
|
||||
if (!root) {
|
||||
root = document.createElement('div', { id: 'root' });
|
||||
root.id = 'root';
|
||||
document.body.appendChild(root);
|
||||
}
|
||||
mount(<div id="API">Hello</div>, { attachTo: root });
|
||||
const getContainer = () => document.getElementById('API');
|
||||
const wrapper = mount(
|
||||
<Anchor getContainer={getContainer}>
|
||||
<Link href="#API" title="API" />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.find('a[href="#API"]').simulate('click');
|
||||
wrapper.instance().handleScroll();
|
||||
expect(wrapper.instance().state).not.toBe(null);
|
||||
});
|
||||
|
||||
it('Same function returns different DOM', async () => {
|
||||
let root = document.getElementById('root');
|
||||
if (!root) {
|
||||
root = document.createElement('div', { id: 'root' });
|
||||
root.id = 'root';
|
||||
document.body.appendChild(root);
|
||||
}
|
||||
mount(
|
||||
<div>
|
||||
<div id="API1">Hello</div>
|
||||
<div id="API2">World</div>
|
||||
</div>,
|
||||
{ attachTo: root },
|
||||
);
|
||||
const holdContainer = {
|
||||
container: document.getElementById('API1'),
|
||||
};
|
||||
const getContainer = () => {
|
||||
return holdContainer.container;
|
||||
};
|
||||
const wrapper = mount(
|
||||
<Anchor getContainer={getContainer}>
|
||||
<Link href="#API1" title="API1" />
|
||||
<Link href="#API2" title="API2" />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn(wrapper.instance().scrollEvent, 'remove');
|
||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||
await sleep(1000);
|
||||
holdContainer.container = document.getElementById('API2');
|
||||
wrapper.setProps({ 'data-only-trigger-re-render': true });
|
||||
expect(removeListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Anchor getCurrentAnchor prop', () => {
|
||||
const getCurrentAnchor = () => '#API2';
|
||||
const wrapper = mount(
|
||||
<Anchor getCurrentAnchor={getCurrentAnchor}>
|
||||
<Link href="#API1" title="API1" />
|
||||
<Link href="#API2" title="API2" />
|
||||
</Anchor>,
|
||||
);
|
||||
expect(wrapper.instance().state.activeLink).toBe('#API2');
|
||||
});
|
||||
|
||||
it('Anchor targetOffset prop', async () => {
|
||||
let dateNowMock;
|
||||
|
||||
function dataNowMockFn() {
|
||||
let start = 0;
|
||||
|
||||
const handler = () => {
|
||||
return (start += 1000);
|
||||
};
|
||||
|
||||
return jest.spyOn(Date, 'now').mockImplementation(handler);
|
||||
}
|
||||
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
let root = document.getElementById('root');
|
||||
if (!root) {
|
||||
root = document.createElement('div', { id: 'root' });
|
||||
root.id = 'root';
|
||||
document.body.appendChild(root);
|
||||
}
|
||||
mount(<h1 id="API">Hello</h1>, { attachTo: root });
|
||||
const wrapper = mount(
|
||||
<Anchor>
|
||||
<Link href="#API" title="API" />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo('#API');
|
||||
await sleep(20);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ offsetTop: 100 });
|
||||
wrapper.instance().handleScrollTo('#API');
|
||||
await sleep(20);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ targetOffset: 200 });
|
||||
wrapper.instance().handleScrollTo('#API');
|
||||
await sleep(20);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
|
||||
dateNowMock.mockRestore();
|
||||
});
|
||||
|
||||
it('Anchor onChange prop', async () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Anchor onChange={onChange}>
|
||||
<Link href="#API1" title="API1" />
|
||||
<Link href="#API2" title="API2" />
|
||||
</Anchor>,
|
||||
);
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
wrapper.instance().handleScrollTo('#API2');
|
||||
expect(onChange).toHaveBeenCalledTimes(2);
|
||||
expect(onChange).toHaveBeenCalledWith('#API2');
|
||||
});
|
||||
});
|
||||
469
components/anchor/__tests__/Anchor.test.tsx
Normal file
469
components/anchor/__tests__/Anchor.test.tsx
Normal file
@@ -0,0 +1,469 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Anchor from '..';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
|
||||
const { Link } = Anchor;
|
||||
|
||||
function createGetContainer(id: string) {
|
||||
return () => {
|
||||
const container = document.getElementById(id);
|
||||
if (container == null) {
|
||||
throw new Error();
|
||||
}
|
||||
return container;
|
||||
};
|
||||
}
|
||||
|
||||
function createDiv() {
|
||||
const root = document.createElement('div');
|
||||
document.body.appendChild(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
let idCounter = 0;
|
||||
const getHashUrl = () => `Anchor-API-${idCounter++}`;
|
||||
|
||||
describe('Anchor Render', () => {
|
||||
const getBoundingClientRectMock = jest.spyOn(
|
||||
HTMLHeadingElement.prototype,
|
||||
'getBoundingClientRect',
|
||||
);
|
||||
const getClientRectsMock = jest.spyOn(HTMLHeadingElement.prototype, 'getClientRects');
|
||||
|
||||
beforeAll(() => {
|
||||
getBoundingClientRectMock.mockReturnValue({
|
||||
width: 100,
|
||||
height: 100,
|
||||
top: 1000,
|
||||
} as DOMRect);
|
||||
getClientRectsMock.mockReturnValue({ length: 1 } as DOMRectList);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
getBoundingClientRectMock.mockRestore();
|
||||
getClientRectsMock.mockRestore();
|
||||
});
|
||||
|
||||
it('Anchor render perfectly', () => {
|
||||
const hash = getHashUrl();
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.find(`a[href="#${hash}"]`).simulate('click');
|
||||
|
||||
wrapper.instance().handleScroll();
|
||||
expect(wrapper.instance().state).not.toBe(null);
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - click', () => {
|
||||
const hash = getHashUrl();
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
<Link href={`http://www.example.com/#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.find(`a[href="http://www.example.com/#${hash}"]`).simulate('click');
|
||||
expect(wrapper.instance().state.activeLink).toBe(`http://www.example.com/#${hash}`);
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - hash router', async () => {
|
||||
const root = createDiv();
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
mount(<div id="/faq?locale=en#Q1">Q1</div>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
<Link href="/#/faq?locale=en#Q1" title="Q1" />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.instance().handleScrollTo('/#/faq?locale=en#Q1');
|
||||
expect(wrapper.instance().state.activeLink).toBe('/#/faq?locale=en#Q1');
|
||||
expect(scrollToSpy).not.toHaveBeenCalled();
|
||||
await sleep(1000);
|
||||
expect(scrollToSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - scroll', () => {
|
||||
const hash = getHashUrl();
|
||||
const root = createDiv();
|
||||
mount(<div id={hash}>Hello</div>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
<Link href={`http://www.example.com/#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScroll();
|
||||
expect(wrapper.instance().state.activeLink).toBe(`http://www.example.com/#${hash}`);
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - scrollTo', async () => {
|
||||
const hash = getHashUrl();
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
const root = createDiv();
|
||||
mount(<div id={`#${hash}`}>Hello</div>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
<Link href={`##${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo(`##${hash}`);
|
||||
expect(wrapper.instance().state.activeLink).toBe(`##${hash}`);
|
||||
const calls = scrollToSpy.mock.calls.length;
|
||||
await sleep(1000);
|
||||
expect(scrollToSpy.mock.calls.length).toBeGreaterThan(calls);
|
||||
});
|
||||
|
||||
it('should remove listener when unmount', async () => {
|
||||
const hash = getHashUrl();
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||
wrapper.unmount();
|
||||
expect(removeListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should unregister link when unmount children', async () => {
|
||||
const hash = getHashUrl();
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
expect((wrapper.instance() as any).links).toEqual([`#${hash}`]);
|
||||
wrapper.setProps({ children: null });
|
||||
expect((wrapper.instance() as any).links).toEqual([]);
|
||||
});
|
||||
|
||||
it('should update links when link href update', async () => {
|
||||
const hash = getHashUrl();
|
||||
let anchorInstance: Anchor | null = null;
|
||||
function AnchorUpdate({ href }: { href: string }) {
|
||||
return (
|
||||
<Anchor
|
||||
ref={c => {
|
||||
anchorInstance = c;
|
||||
}}
|
||||
>
|
||||
<Link href={href} title={hash} />
|
||||
</Anchor>
|
||||
);
|
||||
}
|
||||
const wrapper = mount(<AnchorUpdate href={`#${hash}`} />);
|
||||
|
||||
if (anchorInstance == null) {
|
||||
throw new Error('anchorInstance should not be null');
|
||||
}
|
||||
expect((anchorInstance as any).links).toEqual([`#${hash}`]);
|
||||
wrapper.setProps({ href: `#${hash}_1` });
|
||||
expect((anchorInstance as any).links).toEqual([`#${hash}_1`]);
|
||||
});
|
||||
|
||||
it('Anchor onClick event', () => {
|
||||
const hash = getHashUrl();
|
||||
let event;
|
||||
let link;
|
||||
const handleClick = (
|
||||
e: React.MouseEvent<HTMLElement>,
|
||||
_link: { title: React.ReactNode; href: string },
|
||||
) => {
|
||||
event = e;
|
||||
link = _link;
|
||||
};
|
||||
|
||||
const href = `#${hash}`;
|
||||
const title = hash;
|
||||
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor onClick={handleClick}>
|
||||
<Link href={href} title={title} />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.find(`a[href="${href}"]`).simulate('click');
|
||||
|
||||
wrapper.instance().handleScroll();
|
||||
expect(event).not.toBe(undefined);
|
||||
expect(link).toEqual({ href, title });
|
||||
});
|
||||
|
||||
it('Different function returns the same DOM', async () => {
|
||||
const hash = getHashUrl();
|
||||
const root = createDiv();
|
||||
mount(<div id={hash}>Hello</div>, { attachTo: root });
|
||||
const getContainerA = createGetContainer(hash);
|
||||
const getContainerB = createGetContainer(hash);
|
||||
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor getContainer={getContainerA}>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||
await sleep(1000);
|
||||
wrapper.setProps({ getContainer: getContainerB });
|
||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Different function returns different DOM', async () => {
|
||||
const hash1 = getHashUrl();
|
||||
const hash2 = getHashUrl();
|
||||
const root = createDiv();
|
||||
mount(
|
||||
<div>
|
||||
<div id={hash1}>Hello</div>
|
||||
<div id={hash2}>World</div>
|
||||
</div>,
|
||||
{ attachTo: root },
|
||||
);
|
||||
const getContainerA = createGetContainer(hash1);
|
||||
const getContainerB = createGetContainer(hash2);
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor getContainer={getContainerA}>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||
await sleep(1000);
|
||||
wrapper.setProps({ getContainer: getContainerB });
|
||||
expect(removeListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Same function returns the same DOM', () => {
|
||||
const hash = getHashUrl();
|
||||
const root = createDiv();
|
||||
mount(<div id={hash}>Hello</div>, { attachTo: root });
|
||||
const getContainer = createGetContainer(hash);
|
||||
const wrapper = mount(
|
||||
<Anchor getContainer={getContainer}>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.find(`a[href="#${hash}"]`).simulate('click');
|
||||
(wrapper.instance() as any).handleScroll();
|
||||
expect(wrapper.instance().state).not.toBe(null);
|
||||
});
|
||||
|
||||
it('Same function returns different DOM', async () => {
|
||||
const hash1 = getHashUrl();
|
||||
const hash2 = getHashUrl();
|
||||
const root = createDiv();
|
||||
mount(
|
||||
<div>
|
||||
<div id={hash1}>Hello</div>
|
||||
<div id={hash2}>World</div>
|
||||
</div>,
|
||||
{ attachTo: root },
|
||||
);
|
||||
const holdContainer = {
|
||||
container: document.getElementById(hash1),
|
||||
};
|
||||
const getContainer = () => {
|
||||
if (holdContainer.container == null) {
|
||||
throw new Error('container should not be null');
|
||||
}
|
||||
return holdContainer.container;
|
||||
};
|
||||
const wrapper = mount(
|
||||
<Anchor getContainer={getContainer}>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||
await sleep(1000);
|
||||
holdContainer.container = document.getElementById(hash2);
|
||||
wrapper.setProps({ 'data-only-trigger-re-render': true });
|
||||
expect(removeListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Anchor getCurrentAnchor prop', () => {
|
||||
const hash1 = getHashUrl();
|
||||
const hash2 = getHashUrl();
|
||||
const getCurrentAnchor = () => `#${hash2}`;
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor getCurrentAnchor={getCurrentAnchor}>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
);
|
||||
expect(wrapper.instance().state.activeLink).toBe(`#${hash2}`);
|
||||
});
|
||||
|
||||
it('Anchor targetOffset prop', async () => {
|
||||
const hash = getHashUrl();
|
||||
let dateNowMock;
|
||||
|
||||
function dataNowMockFn() {
|
||||
let start = 0;
|
||||
|
||||
const handler = () => {
|
||||
return (start += 1000);
|
||||
};
|
||||
|
||||
return jest.spyOn(Date, 'now').mockImplementation(handler);
|
||||
}
|
||||
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
const root = createDiv();
|
||||
mount(<h1 id={hash}>Hello</h1>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ offsetTop: 100 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ targetOffset: 200 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
|
||||
dateNowMock.mockRestore();
|
||||
});
|
||||
|
||||
it('Anchor onChange prop', async () => {
|
||||
const hash1 = getHashUrl();
|
||||
const hash2 = getHashUrl();
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor onChange={onChange}>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
);
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
wrapper.instance().handleScrollTo(hash2);
|
||||
expect(onChange).toHaveBeenCalledTimes(2);
|
||||
expect(onChange).toHaveBeenCalledWith(hash2);
|
||||
});
|
||||
|
||||
it('invalid hash', async () => {
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
<Link href="notexsited" title="title" />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.find(`a[href="notexsited"]`).simulate('click');
|
||||
|
||||
wrapper.instance().handleScrollTo('notexsited');
|
||||
expect(wrapper.instance().state).not.toBe(null);
|
||||
});
|
||||
|
||||
it('test edge case when getBoundingClientRect return zero size', async () => {
|
||||
getBoundingClientRectMock.mockReturnValue({
|
||||
width: 0,
|
||||
height: 0,
|
||||
top: 1000,
|
||||
} as DOMRect);
|
||||
const hash = getHashUrl();
|
||||
let dateNowMock;
|
||||
|
||||
function dataNowMockFn() {
|
||||
let start = 0;
|
||||
|
||||
const handler = () => {
|
||||
return (start += 1000);
|
||||
};
|
||||
|
||||
return jest.spyOn(Date, 'now').mockImplementation(handler);
|
||||
}
|
||||
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
const root = createDiv();
|
||||
mount(<h1 id={hash}>Hello</h1>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ offsetTop: 100 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ targetOffset: 200 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
|
||||
dateNowMock.mockRestore();
|
||||
getBoundingClientRectMock.mockReturnValue({
|
||||
width: 100,
|
||||
height: 100,
|
||||
top: 1000,
|
||||
} as DOMRect);
|
||||
});
|
||||
|
||||
it('test edge case when container is not windows', async () => {
|
||||
const hash = getHashUrl();
|
||||
let dateNowMock;
|
||||
|
||||
function dataNowMockFn() {
|
||||
let start = 0;
|
||||
|
||||
const handler = () => {
|
||||
return (start += 1000);
|
||||
};
|
||||
|
||||
return jest.spyOn(Date, 'now').mockImplementation(handler);
|
||||
}
|
||||
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
const root = createDiv();
|
||||
mount(<h1 id={hash}>Hello</h1>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor getContainer={() => document.body}>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ offsetTop: 100 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ targetOffset: 200 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
|
||||
dateNowMock.mockRestore();
|
||||
});
|
||||
});
|
||||
6
components/anchor/context.ts
Normal file
6
components/anchor/context.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { AntAnchor } from './Anchor';
|
||||
|
||||
const AnchorContext = React.createContext<AntAnchor>(null as any);
|
||||
|
||||
export default AnchorContext;
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
type: Other
|
||||
cols: 2
|
||||
title: Anchor
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/ep_L42LFy/Anchor.svg
|
||||
---
|
||||
|
||||
Hyperlinks to scroll on one page.
|
||||
|
||||
@@ -4,6 +4,7 @@ subtitle: 锚点
|
||||
cols: 2
|
||||
type: 其他
|
||||
title: Anchor
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/ep_L42LFy/Anchor.svg
|
||||
---
|
||||
|
||||
用于跳转到页面指定位置。
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
&-link {
|
||||
padding: 7px 0 7px 16px;
|
||||
padding: @anchor-link-padding;
|
||||
line-height: 1.143;
|
||||
|
||||
&-title {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
@@ -30,9 +30,9 @@ exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
|
||||
input here
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
</div>,
|
||||
<br />,
|
||||
<br />,
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
@@ -61,8 +61,8 @@ exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
|
||||
control mode
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/auto-complete/demo/certain-category.md correctly 1`] = `
|
||||
@@ -256,6 +256,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
@@ -341,6 +342,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
@@ -534,6 +536,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
@@ -675,6 +678,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
@@ -817,6 +821,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
|
||||
@@ -1,6 +1,87 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AutoComplete with Custom Input Element Render rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
exports[`AutoComplete legacy dataSource should accept react element option 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-open ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant="undefined_list_0"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-expanded="true"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
role="combobox"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
id="undefined_list"
|
||||
role="listbox"
|
||||
style="height:0;width:0;overflow:hidden"
|
||||
>
|
||||
<div
|
||||
aria-label="ReactNode"
|
||||
aria-selected="false"
|
||||
id="undefined_list_0"
|
||||
role="option"
|
||||
>
|
||||
key
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class=""
|
||||
style="height:256px"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class=""
|
||||
style="display:flex;flex-direction:column"
|
||||
>
|
||||
<div
|
||||
aria-selected="false"
|
||||
class="ant-select-item ant-select-item-option ant-select-item-option-active"
|
||||
>
|
||||
<div
|
||||
class="ant-select-item-option-content"
|
||||
>
|
||||
ReactNode
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-select-item-option-state"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="on"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`AutoComplete rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-rtl ant-select-single ant-select-show-search"
|
||||
>
|
||||
|
||||
@@ -4,7 +4,7 @@ import AutoComplete from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('AutoComplete with Custom Input Element Render', () => {
|
||||
describe('AutoComplete', () => {
|
||||
mountTest(AutoComplete);
|
||||
rtlTest(AutoComplete);
|
||||
|
||||
@@ -52,4 +52,21 @@ describe('AutoComplete with Custom Input Element Render', () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error.mockRestore();
|
||||
});
|
||||
|
||||
it('legacy dataSource should accept react element option', () => {
|
||||
const wrapper = mount(<AutoComplete open dataSource={[<span key="key">ReactNode</span>]} />);
|
||||
expect(wrapper).toMatchRenderedSnapshot();
|
||||
});
|
||||
|
||||
it('legacy AutoComplete.Option should be compatiable', () => {
|
||||
const wrapper = mount(
|
||||
<AutoComplete>
|
||||
<AutoComplete.Option value="111">111</AutoComplete.Option>
|
||||
<AutoComplete.Option value="222">222</AutoComplete.Option>
|
||||
</AutoComplete>,
|
||||
);
|
||||
expect(wrapper.find('input').length).toBe(1);
|
||||
wrapper.find('input').simulate('change', { target: { value: '1' } });
|
||||
expect(wrapper.find('.ant-select-item-option').length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,7 +37,7 @@ const Complete: React.FC = () => {
|
||||
setValue(data);
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<AutoComplete
|
||||
options={options}
|
||||
style={{ width: 200 }}
|
||||
@@ -56,7 +56,7 @@ const Complete: React.FC = () => {
|
||||
onChange={onChange}
|
||||
placeholder="control mode"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -67,18 +67,16 @@ const options = [
|
||||
},
|
||||
];
|
||||
|
||||
const Complete: React.FC = () => {
|
||||
return (
|
||||
<AutoComplete
|
||||
dropdownClassName="certain-category-search-dropdown"
|
||||
dropdownMatchSelectWidth={500}
|
||||
style={{ width: 250 }}
|
||||
options={options}
|
||||
>
|
||||
<Input.Search size="large" placeholder="input here" />
|
||||
</AutoComplete>
|
||||
);
|
||||
};
|
||||
const Complete: React.FC = () => (
|
||||
<AutoComplete
|
||||
dropdownClassName="certain-category-search-dropdown"
|
||||
dropdownMatchSelectWidth={500}
|
||||
style={{ width: 250 }}
|
||||
options={options}
|
||||
>
|
||||
<Input.Search size="large" placeholder="input here" />
|
||||
</AutoComplete>
|
||||
);
|
||||
|
||||
ReactDOM.render(<Complete />, mountNode);
|
||||
```
|
||||
|
||||
@@ -22,25 +22,25 @@ const formItemLayout = {
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<Form style={{ margin: '0 auto' }}>
|
||||
<Form.Item label="单独 AutoComplete" {...formItemLayout}>
|
||||
<Form style={{ margin: '0 auto' }} {...formItemLayout}>
|
||||
<Form.Item label="单独 AutoComplete">
|
||||
<AutoComplete />
|
||||
</Form.Item>
|
||||
<Form.Item label="单独 TreeSelect" {...formItemLayout}>
|
||||
<Form.Item label="单独 TreeSelect">
|
||||
<TreeSelect />
|
||||
</Form.Item>
|
||||
<Form.Item label="添加 Input.Group 正常" {...formItemLayout}>
|
||||
<Form.Item label="添加 Input.Group 正常">
|
||||
<Input.Group compact>
|
||||
<TreeSelect style={{ width: '30%' }} />
|
||||
<AutoComplete />
|
||||
</Input.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="包含 search 图标正常" {...formItemLayout}>
|
||||
<Form.Item label="包含 search 图标正常">
|
||||
<AutoComplete>
|
||||
<Input suffix={<SearchOutlined />} />
|
||||
</AutoComplete>
|
||||
</Form.Item>
|
||||
<Form.Item label="同时有 Input.Group 和图标发生移位" {...formItemLayout}>
|
||||
<Form.Item label="同时有 Input.Group 和图标发生移位">
|
||||
<Input.Group compact>
|
||||
<TreeSelect style={{ width: '30%' }} />
|
||||
<AutoComplete>
|
||||
@@ -48,7 +48,7 @@ ReactDOM.render(
|
||||
</AutoComplete>
|
||||
</Input.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="同时有 Input.Group 和 Search 组件发生移位" {...formItemLayout}>
|
||||
<Form.Item label="同时有 Input.Group 和 Search 组件发生移位">
|
||||
<Input.Group compact>
|
||||
<TreeSelect style={{ width: '30%' }} />
|
||||
<AutoComplete>
|
||||
@@ -56,7 +56,7 @@ ReactDOM.render(
|
||||
</AutoComplete>
|
||||
</Input.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="Input Group 和 Button 结合" {...formItemLayout}>
|
||||
<Form.Item label="Input Group 和 Button 结合">
|
||||
<Input.Group compact>
|
||||
<TreeSelect style={{ width: '20%' }} />
|
||||
<AutoComplete>
|
||||
|
||||
@@ -22,18 +22,16 @@ const options = [
|
||||
{ value: 'Wall Street' },
|
||||
];
|
||||
|
||||
const Complete: React.FC = () => {
|
||||
return (
|
||||
<AutoComplete
|
||||
style={{ width: 200 }}
|
||||
options={options}
|
||||
placeholder="try to type `b`"
|
||||
filterOption={(inputValue, option) =>
|
||||
option.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const Complete: React.FC = () => (
|
||||
<AutoComplete
|
||||
style={{ width: 200 }}
|
||||
options={options}
|
||||
placeholder="try to type `b`"
|
||||
filterOption={(inputValue, option) =>
|
||||
option.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(<Complete />, mountNode);
|
||||
```
|
||||
|
||||
@@ -30,14 +30,13 @@ const Complete: React.FC = () => {
|
||||
}
|
||||
setResult(res);
|
||||
};
|
||||
const children = result.map((email: string) => (
|
||||
<Option key={email} value={email}>
|
||||
{email}
|
||||
</Option>
|
||||
));
|
||||
return (
|
||||
<AutoComplete style={{ width: 200 }} onSearch={handleSearch} placeholder="input here">
|
||||
{children}
|
||||
{result.map((email: string) => (
|
||||
<Option key={email} value={email}>
|
||||
{email}
|
||||
</Option>
|
||||
))}
|
||||
</AutoComplete>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
type: Data Entry
|
||||
cols: 2
|
||||
title: AutoComplete
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/gtGCgVDKv/AutoComplete.svg
|
||||
---
|
||||
|
||||
Autocomplete function of input field.
|
||||
@@ -34,6 +35,7 @@ When there is a need for autocomplete functionality.
|
||||
| defaultOpen | Initial open state of dropdown | boolean | - | |
|
||||
| open | Controlled open state of dropdown | boolean | - | |
|
||||
| onDropdownVisibleChange | Call when dropdown open | function(open) | - | |
|
||||
| notFoundContent | Specify content to show when no result matches.. | string | 'Not Found' | |
|
||||
|
||||
## Methods
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import Select, { InternalSelectProps, OptionType } from '../select';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
import devWarning from '../_util/devWarning';
|
||||
import { isValidElement } from '../_util/reactNode';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@@ -25,7 +26,10 @@ export interface DataSourceItemObject {
|
||||
export type DataSourceItemType = string | DataSourceItemObject;
|
||||
|
||||
export interface AutoCompleteProps
|
||||
extends Omit<InternalSelectProps<string>, 'inputIcon' | 'loading' | 'mode' | 'optionLabelProp' | 'labelInValue'> {
|
||||
extends Omit<
|
||||
InternalSelectProps<string>,
|
||||
'inputIcon' | 'loading' | 'mode' | 'optionLabelProp' | 'labelInValue'
|
||||
> {
|
||||
dataSource?: DataSourceItemType[];
|
||||
}
|
||||
|
||||
@@ -46,7 +50,7 @@ const AutoComplete: React.RefForwardingComponent<Select, AutoCompleteProps> = (p
|
||||
|
||||
if (
|
||||
childNodes.length === 1 &&
|
||||
React.isValidElement(childNodes[0]) &&
|
||||
isValidElement(childNodes[0]) &&
|
||||
!isSelectOptionOrSelectOptGroup(childNodes[0])
|
||||
) {
|
||||
customizeInput = childNodes[0];
|
||||
@@ -63,7 +67,7 @@ const AutoComplete: React.RefForwardingComponent<Select, AutoCompleteProps> = (p
|
||||
} else {
|
||||
optionChildren = dataSource
|
||||
? dataSource.map(item => {
|
||||
if (React.isValidElement(item)) {
|
||||
if (isValidElement(item)) {
|
||||
return item;
|
||||
}
|
||||
switch (typeof item) {
|
||||
@@ -90,13 +94,13 @@ const AutoComplete: React.RefForwardingComponent<Select, AutoCompleteProps> = (p
|
||||
|
||||
// ============================ Warning ============================
|
||||
React.useEffect(() => {
|
||||
warning(
|
||||
devWarning(
|
||||
!('dataSource' in props),
|
||||
'AutoComplete',
|
||||
'`dataSource` is deprecated, please use `options` instead.',
|
||||
);
|
||||
|
||||
warning(
|
||||
devWarning(
|
||||
!customizeInput || !('size' in props),
|
||||
'AutoComplete',
|
||||
'You need to control style self instead of setting `size` when using customize input.',
|
||||
|
||||
@@ -4,6 +4,7 @@ subtitle: 自动完成
|
||||
type: 数据录入
|
||||
cols: 2
|
||||
title: AutoComplete
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/gtGCgVDKv/AutoComplete.svg
|
||||
---
|
||||
|
||||
输入框自动完成功能。
|
||||
@@ -36,6 +37,7 @@ title: AutoComplete
|
||||
| defaultOpen | 是否默认展开下拉菜单 | boolean | - | |
|
||||
| open | 是否展开下拉菜单 | boolean | - | |
|
||||
| onDropdownVisibleChange | 展开下拉菜单的回调 | function(open) | - | |
|
||||
| notFoundContent | 当下拉列表为空时显示的内容 | ReactNode | - | |
|
||||
|
||||
## 方法
|
||||
|
||||
|
||||
@@ -40,19 +40,10 @@ describe('Avatar Render', () => {
|
||||
global.document.body.appendChild(div);
|
||||
|
||||
const wrapper = mount(<Avatar src="http://error.url">Fallback</Avatar>, { attachTo: div });
|
||||
wrapper.instance().setScale = jest.fn(() => {
|
||||
if (wrapper.state().scale === 0.5) {
|
||||
return;
|
||||
}
|
||||
wrapper.instance().setState({ scale: 0.5 });
|
||||
});
|
||||
wrapper.find('img').simulate('error');
|
||||
|
||||
const children = wrapper.find('.ant-avatar-string');
|
||||
expect(children.length).toBe(1);
|
||||
expect(children.text()).toBe('Fallback');
|
||||
expect(wrapper.instance().setScale).toHaveBeenCalled();
|
||||
expect(div.querySelector('.ant-avatar-string').style.transform).toContain('scale(0.5)');
|
||||
|
||||
wrapper.detach();
|
||||
global.document.body.removeChild(div);
|
||||
@@ -136,6 +127,11 @@ describe('Avatar Render', () => {
|
||||
expect(wrapper.state().scale).toBe(0.32);
|
||||
});
|
||||
|
||||
it('should calculate scale of avatar children correctly with gap', () => {
|
||||
const wrapper = mount(<Avatar gap={2}>Avatar</Avatar>);
|
||||
expect(wrapper.state().scale).toBe(0.36);
|
||||
});
|
||||
|
||||
it('should warning when pass a string as icon props', () => {
|
||||
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
mount(<Avatar size={64} icon="aa" />);
|
||||
@@ -146,4 +142,16 @@ describe('Avatar Render', () => {
|
||||
);
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('support size is number', () => {
|
||||
const wrapper = mount(<Avatar size={100}>TestString</Avatar>);
|
||||
expect(wrapper).toMatchRenderedSnapshot();
|
||||
});
|
||||
|
||||
it('support onMouseEnter', () => {
|
||||
const onMouseEnter = jest.fn();
|
||||
const wrapper = mount(<Avatar onMouseEnter={onMouseEnter}>TestString</Avatar>);
|
||||
wrapper.simulate('mouseenter');
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,3 +10,17 @@ exports[`Avatar Render rtl render component should be rendered correctly in RTL
|
||||
/>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Avatar Render support size is number 1`] = `
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
style="width:100px;height:100px;line-height:100px;font-size:18px"
|
||||
>
|
||||
<span
|
||||
class="ant-avatar-string"
|
||||
style="opacity:0"
|
||||
>
|
||||
TestString
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<span
|
||||
class="avatar-item"
|
||||
>
|
||||
@@ -194,7 +194,7 @@ exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
|
||||
</span>
|
||||
</sup>
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span>
|
||||
<span
|
||||
class="ant-badge"
|
||||
@@ -228,12 +228,12 @@ exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
|
||||
data-show="true"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</span>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/avatar/demo/basic.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div>
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-icon"
|
||||
@@ -332,7 +332,7 @@ exports[`renders ./components/avatar/demo/basic.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>,
|
||||
<div>
|
||||
<span
|
||||
class="ant-avatar ant-avatar-square ant-avatar-icon"
|
||||
@@ -431,12 +431,12 @@ exports[`renders ./components/avatar/demo/basic.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/avatar/demo/dynamic.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<span
|
||||
class="ant-avatar ant-avatar-lg ant-avatar-circle"
|
||||
style="background-color:#f56a00;vertical-align:middle"
|
||||
@@ -447,21 +447,30 @@ exports[`renders ./components/avatar/demo/dynamic.md correctly 1`] = `
|
||||
>
|
||||
U
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<button
|
||||
class="ant-btn ant-btn-sm"
|
||||
style="margin:0 16px;vertical-align:middle"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Change
|
||||
ChangeUser
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn ant-btn-sm"
|
||||
style="vertical-align:middle"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
changeGap
|
||||
</span>
|
||||
</button>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
@@ -469,7 +478,7 @@ exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `
|
||||
<span>
|
||||
Toggle Avatar visibility
|
||||
</span>
|
||||
</button>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
@@ -477,7 +486,7 @@ exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `
|
||||
<span>
|
||||
Toggle Avatar size
|
||||
</span>
|
||||
</button>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
@@ -485,9 +494,9 @@ exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `
|
||||
<span>
|
||||
Change Avatar scale
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<br />
|
||||
</button>,
|
||||
<br />,
|
||||
<br />,
|
||||
<div
|
||||
style="text-align:center;transform:scale(1);margin-top:24px"
|
||||
>
|
||||
@@ -533,12 +542,12 @@ exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-icon"
|
||||
>
|
||||
@@ -562,7 +571,7 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
>
|
||||
@@ -572,9 +581,10 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
>
|
||||
U
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
style="width:40px;height:40px;line-height:40px;font-size:18px"
|
||||
>
|
||||
<span
|
||||
class="ant-avatar-string"
|
||||
@@ -582,14 +592,14 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
>
|
||||
USER
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-image"
|
||||
>
|
||||
<img
|
||||
src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
|
||||
/>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
style="color:#f56a00;background-color:#fde3cf"
|
||||
@@ -600,7 +610,7 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
>
|
||||
U
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-icon"
|
||||
style="background-color:#87d068"
|
||||
@@ -625,6 +635,6 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</span>,
|
||||
]
|
||||
`;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Avatar, Badge } from 'antd';
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<span className="avatar-item">
|
||||
<Badge count={1}>
|
||||
<Avatar shape="square" icon={<UserOutlined />} />
|
||||
@@ -29,7 +29,7 @@ ReactDOM.render(
|
||||
<Avatar shape="square" icon={<UserOutlined />} />
|
||||
</Badge>
|
||||
</span>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Avatar } from 'antd';
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<div>
|
||||
<Avatar size={64} icon={<UserOutlined />} />
|
||||
<Avatar size="large" icon={<UserOutlined />} />
|
||||
@@ -31,7 +31,7 @@ ReactDOM.render(
|
||||
<Avatar shape="square" icon={<UserOutlined />} />
|
||||
<Avatar shape="square" size="small" icon={<UserOutlined />} />
|
||||
</div>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
@@ -41,4 +41,8 @@ ReactDOM.render(
|
||||
margin-top: 16px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
.ant-row-rtl #components-avatar-demo-basic .ant-avatar {
|
||||
margin-right: 0;
|
||||
margin-left: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,11 +7,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
对于字符型的头像,当字符串较长时,字体大小可以根据头像宽度自动调整。
|
||||
对于字符型的头像,当字符串较长时,字体大小可以根据头像宽度自动调整。也可使用 `gap` 来设置字符距离左右两侧边界单位像素。
|
||||
|
||||
## en-US
|
||||
|
||||
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar.
|
||||
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar. You can also use `gap` to set the unit distance between left and right sides.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
@@ -19,18 +19,24 @@ import { Avatar, Button } from 'antd';
|
||||
|
||||
const UserList = ['U', 'Lucy', 'Tom', 'Edward'];
|
||||
const ColorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
|
||||
const GapList = [4, 3, 2, 1];
|
||||
|
||||
const Autoset: React.FC = () => {
|
||||
const [user, setUser] = useState(UserList[0]);
|
||||
const [color, setColor] = useState(ColorList[0]);
|
||||
const [gap, setGap] = useState(GapList[0]);
|
||||
const changeUser = () => {
|
||||
const index = UserList.indexOf(user);
|
||||
setUser(index < UserList.length - 1 ? UserList[index + 1] : UserList[0]);
|
||||
setColor(index < ColorList.length - 1 ? ColorList[index + 1] : ColorList[0]);
|
||||
};
|
||||
const changeGap = () => {
|
||||
const index = GapList.indexOf(gap);
|
||||
setGap(index < GapList.length - 1 ? GapList[index + 1] : GapList[0]);
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<Avatar style={{ backgroundColor: color, verticalAlign: 'middle' }} size="large">
|
||||
<>
|
||||
<Avatar style={{ backgroundColor: color, verticalAlign: 'middle' }} size="large" gap={gap}>
|
||||
{user}
|
||||
</Avatar>
|
||||
<Button
|
||||
@@ -38,9 +44,12 @@ const Autoset: React.FC = () => {
|
||||
style={{ margin: '0 16px', verticalAlign: 'middle' }}
|
||||
onClick={changeUser}
|
||||
>
|
||||
Change
|
||||
ChangeUser
|
||||
</Button>
|
||||
</div>
|
||||
<Button size="small" style={{ verticalAlign: 'middle' }} onClick={changeGap}>
|
||||
changeGap
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ const App: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<Button onClick={toggle}>Toggle Avatar visibility</Button>
|
||||
<Button onClick={toggleSize}>Toggle Avatar size</Button>
|
||||
<Button onClick={changeScale}>Change Avatar scale</Button>
|
||||
@@ -67,7 +67,7 @@ const App: React.FC = () => {
|
||||
</Avatar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -18,14 +18,14 @@ import { Avatar } from 'antd';
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<Avatar icon={<UserOutlined />} />
|
||||
<Avatar>U</Avatar>
|
||||
<Avatar>USER</Avatar>
|
||||
<Avatar size={40}>USER</Avatar>
|
||||
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
|
||||
<Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>U</Avatar>
|
||||
<Avatar style={{ backgroundColor: '#87d068' }} icon={<UserOutlined />} />
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
@@ -35,4 +35,8 @@ ReactDOM.render(
|
||||
margin-top: 16px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
.ant-row-rtl #components-avatar-demo-type .ant-avatar {
|
||||
margin-right: 0;
|
||||
margin-left: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user