Compare commits
1289 Commits
3.0.0-alph
...
main
Author | SHA1 | Date |
---|---|---|
![]() |
35c1ad9c80 | |
![]() |
e9f8ea7903 | |
![]() |
27acc9a80e | |
![]() |
43ad5dec90 | |
![]() |
aa8802679f | |
![]() |
aa211fd789 | |
![]() |
61d39be86f | |
![]() |
b80bd37f6e | |
![]() |
3db5e191b8 | |
![]() |
45c7109212 | |
![]() |
b58d0fb723 | |
![]() |
a21a1ca533 | |
![]() |
4a37016f4e | |
![]() |
5d6ebb30ac | |
![]() |
888457238d | |
![]() |
b0d9309471 | |
![]() |
f64d0718ae | |
![]() |
968317ca9f | |
![]() |
22dad3ba6d | |
![]() |
4f7bd6f28d | |
![]() |
12fcfa15b1 | |
![]() |
e46d537d45 | |
![]() |
ac9d1b0a7f | |
![]() |
2c7008d786 | |
![]() |
49d4b3166e | |
![]() |
339fb4a230 | |
![]() |
bb443a05e2 | |
![]() |
3a79f72816 | |
![]() |
89eec07145 | |
![]() |
c69a6d29b2 | |
![]() |
2666cb79ab | |
![]() |
35d5185634 | |
![]() |
4492086aac | |
![]() |
4b7c6ac02c | |
![]() |
208b8d3085 | |
![]() |
f41fec26ba | |
![]() |
9118d6cd42 | |
![]() |
5c7aaf0dd6 | |
![]() |
b82d8dd2ad | |
![]() |
1d0fa8533a | |
![]() |
4318147fc6 | |
![]() |
312bcc5127 | |
![]() |
6594fe3964 | |
![]() |
82f28ce3d0 | |
![]() |
6e2c5a6a83 | |
![]() |
307148e2df | |
![]() |
afebeb9ffa | |
![]() |
aeda2637f6 | |
![]() |
f42d8ad1ce | |
![]() |
33a0708eb4 | |
![]() |
085eb398a4 | |
![]() |
9c27414cd0 | |
![]() |
014e86bd27 | |
![]() |
40ad45bc05 | |
![]() |
1c82940160 | |
![]() |
7ce0f115d5 | |
![]() |
54434b0931 | |
![]() |
e01f26c541 | |
![]() |
9a45b35511 | |
![]() |
8e8073d17e | |
![]() |
d6cc262c3a | |
![]() |
9d7c171940 | |
![]() |
48a3ceb921 | |
![]() |
23c620ea3a | |
![]() |
752686e334 | |
![]() |
9b0f0e71e7 | |
![]() |
42d33e963c | |
![]() |
ed27700ef4 | |
![]() |
eedd7f3302 | |
![]() |
c28c38d02e | |
![]() |
162d1fcf95 | |
![]() |
4815ee6f20 | |
![]() |
2b41e56520 | |
![]() |
ab874ffd4b | |
![]() |
61ade6b8ec | |
![]() |
4d35b8caa3 | |
![]() |
040af82eb9 | |
![]() |
a8c72fc5e7 | |
![]() |
c25736d57d | |
![]() |
4a48bfc66b | |
![]() |
4138d3c822 | |
![]() |
dec67a6d65 | |
![]() |
85c48c0566 | |
![]() |
966bc1004c | |
![]() |
457d0fde0b | |
![]() |
ff184b3969 | |
![]() |
75886a8cbf | |
![]() |
2b0c2da232 | |
![]() |
ffd4d8fe92 | |
![]() |
49e1323baa | |
![]() |
35d1de9ea6 | |
![]() |
fa46999963 | |
![]() |
01300d01da | |
![]() |
9a5f83ed06 | |
![]() |
ce6b7f3b4e | |
![]() |
4a2f95fe88 | |
![]() |
7c73beb309 | |
![]() |
0cbf3ca354 | |
![]() |
7afb7ce465 | |
![]() |
9cc73011c5 | |
![]() |
4b21210700 | |
![]() |
a80ca17461 | |
![]() |
ad8d32ab09 | |
![]() |
d870f3f8e0 | |
![]() |
c717473568 | |
![]() |
1e07544e74 | |
![]() |
8ab008d255 | |
![]() |
f034a7759e | |
![]() |
3f33cefa81 | |
![]() |
81e43c56ef | |
![]() |
f400c803e1 | |
![]() |
502c11cc4c | |
![]() |
2cdb69f706 | |
![]() |
2eed8e62ec | |
![]() |
61c0d0cc9d | |
![]() |
d7f9bd27dc | |
![]() |
4ed2868137 | |
![]() |
8696e01039 | |
![]() |
a3fd390619 | |
![]() |
a9198e44df | |
![]() |
509ec682f2 | |
![]() |
73f0a29acf | |
![]() |
f93dd9170d | |
![]() |
cfa0a68568 | |
![]() |
afcff32fcc | |
![]() |
b989cf2d97 | |
![]() |
0e6fd652b8 | |
![]() |
6625d39118 | |
![]() |
67efafca4a | |
![]() |
a8a774a5ff | |
![]() |
1fc109704b | |
![]() |
d140523c89 | |
![]() |
91fe1b0d71 | |
![]() |
c1b4941def | |
![]() |
af383a34bc | |
![]() |
1dccce4e16 | |
![]() |
8aa8e5a778 | |
![]() |
42952b713a | |
![]() |
07c36192b8 | |
![]() |
562623c091 | |
![]() |
e362571719 | |
![]() |
e32ae99bfd | |
![]() |
ccbeb44264 | |
![]() |
3499b11a47 | |
![]() |
dae7262f13 | |
![]() |
8cf6be11f7 | |
![]() |
2510608665 | |
![]() |
b22875db33 | |
![]() |
2bdeed1432 | |
![]() |
49a6b588c1 | |
![]() |
bd080cde2a | |
![]() |
c1454bc7b5 | |
![]() |
61402142f8 | |
![]() |
242982301d | |
![]() |
9bdf882517 | |
![]() |
88ec06b717 | |
![]() |
6c39bec277 | |
![]() |
82f407d396 | |
![]() |
bfcdba251f | |
![]() |
0abcd25b2a | |
![]() |
72b8d09b92 | |
![]() |
b4c29d927b | |
![]() |
bf917f36eb | |
![]() |
0f9c80b86e | |
![]() |
61e5746b0d | |
![]() |
7786a81e76 | |
![]() |
6f89185fe1 | |
![]() |
449adb03df | |
![]() |
4428423be4 | |
![]() |
380fcd4aa9 | |
![]() |
4a1296bb3f | |
![]() |
b9c65656db | |
![]() |
f1bcf2093a | |
![]() |
398710cf1b | |
![]() |
858c4ec409 | |
![]() |
77eab3637c | |
![]() |
664711373c | |
![]() |
21d85ea82c | |
![]() |
b3ef24963f | |
![]() |
f953482a4d | |
![]() |
a9f9899185 | |
![]() |
c99e9b00bd | |
![]() |
3084ced55f | |
![]() |
c5ea668e88 | |
![]() |
3c5fb84542 | |
![]() |
2f7f0e6928 | |
![]() |
2c4d4650da | |
![]() |
0f1ffc99cd | |
![]() |
83d6c93765 | |
![]() |
a6c945caaa | |
![]() |
d0f7c34497 | |
![]() |
2b8f2adcbf | |
![]() |
f25bf6e189 | |
![]() |
93415d0442 | |
![]() |
d185a3af21 | |
![]() |
d3800b54a3 | |
![]() |
b7eed32484 | |
![]() |
46be19531d | |
![]() |
089548ed74 | |
![]() |
ce72484623 | |
![]() |
31d00bf7d1 | |
![]() |
deada0aeb8 | |
![]() |
418d8b33dd | |
![]() |
3c05b7704b | |
![]() |
1254677805 | |
![]() |
f7cc27b7ad | |
![]() |
9855e43805 | |
![]() |
1f01ae0728 | |
![]() |
9464158c0c | |
![]() |
13a4470fd8 | |
![]() |
84fb4b4b3d | |
![]() |
106750ed62 | |
![]() |
cac650737c | |
![]() |
95fa2547fe | |
![]() |
70102039c4 | |
![]() |
7a0c2a384c | |
![]() |
72e148cae8 | |
![]() |
6c13c964c5 | |
![]() |
367ddff30e | |
![]() |
e3ad856543 | |
![]() |
61df5e656f | |
![]() |
439fe840b4 | |
![]() |
197a00f6ea | |
![]() |
3f99a7e985 | |
![]() |
9c0311546b | |
![]() |
7f5b630d72 | |
![]() |
65ccb447c9 | |
![]() |
18405e13b2 | |
![]() |
9e78b4a985 | |
![]() |
6cf5d79e2e | |
![]() |
1abc33a9e7 | |
![]() |
e39e998ecc | |
![]() |
cfd4aadc29 | |
![]() |
38dd977b4c | |
![]() |
72f9262d0a | |
![]() |
c2d71fa7c3 | |
![]() |
969dadb265 | |
![]() |
9c3bf46108 | |
![]() |
141f0100d2 | |
![]() |
6ced156342 | |
![]() |
42608a5121 | |
![]() |
22b21cdac8 | |
![]() |
80a5b531f6 | |
![]() |
cacbde3e03 | |
![]() |
e3f09a18a1 | |
![]() |
7bfe30d280 | |
![]() |
53dc5daaaf | |
![]() |
531ae16553 | |
![]() |
d2b6eb9d94 | |
![]() |
27a4d8ceff | |
![]() |
12074a0dca | |
![]() |
8f95cdd5a3 | |
![]() |
cb0abe5fd5 | |
![]() |
ed87500e77 | |
![]() |
c01630113d | |
![]() |
5279d1289a | |
![]() |
9d406ab7ba | |
![]() |
826c183d0b | |
![]() |
bc576d6255 | |
![]() |
2c39273cc6 | |
![]() |
b49540a339 | |
![]() |
37059c38fd | |
![]() |
4fe57fa322 | |
![]() |
a3ccdeffc2 | |
![]() |
e8c2860c7d | |
![]() |
f1f89191ee | |
![]() |
0c863c1803 | |
![]() |
7591d5c3e6 | |
![]() |
4ea318be30 | |
![]() |
5fd00c05b5 | |
![]() |
a2e50dc43e | |
![]() |
0a738a36b6 | |
![]() |
10f990d534 | |
![]() |
8b5d71663a | |
![]() |
058e8ec542 | |
![]() |
f70b04c74f | |
![]() |
2ce4e7da82 | |
![]() |
a0e94978f5 | |
![]() |
fc5181d1d8 | |
![]() |
994707bd50 | |
![]() |
e9d26f2a7d | |
![]() |
7fd0e4a225 | |
![]() |
e229248053 | |
![]() |
10159941b9 | |
![]() |
9c26ab05d3 | |
![]() |
6861a77d29 | |
![]() |
308c30c738 | |
![]() |
afc1b84ed0 | |
![]() |
58f6d6ee28 | |
![]() |
7270855ce8 | |
![]() |
19f0aea965 | |
![]() |
8212237045 | |
![]() |
80edf86d18 | |
![]() |
6f032c9722 | |
![]() |
1001ff3834 | |
![]() |
6be947aeb9 | |
![]() |
3057cfe9ef | |
![]() |
45ede0853b | |
![]() |
afb2619a81 | |
![]() |
2bf85998ba | |
![]() |
9cff5cb558 | |
![]() |
42cb6871ee | |
![]() |
508e8e3706 | |
![]() |
fe3c2bdf89 | |
![]() |
64b9347fce | |
![]() |
96f940d834 | |
![]() |
d3d37f08a2 | |
![]() |
1e0cefa786 | |
![]() |
d49082008e | |
![]() |
bba322702e | |
![]() |
1d0a2737a4 | |
![]() |
c9f0841628 | |
![]() |
03760e3e3d | |
![]() |
144bb2e6d5 | |
![]() |
b4258dc23d | |
![]() |
9499a7fc86 | |
![]() |
c36f7e701f | |
![]() |
83017269ab | |
![]() |
1c7b7a35f6 | |
![]() |
28263bbe33 | |
![]() |
5aad611d4c | |
![]() |
429172b345 | |
![]() |
e5787c2ed2 | |
![]() |
698c0ff3b4 | |
![]() |
db4148af5a | |
![]() |
21cf533664 | |
![]() |
4c8cc0129f | |
![]() |
6a1952c469 | |
![]() |
a694167f37 | |
![]() |
3ed455b3f7 | |
![]() |
e49e72d24a | |
![]() |
149cedd262 | |
![]() |
8bf8515933 | |
![]() |
f5bea1413b | |
![]() |
0d24755ee3 | |
![]() |
f2f7cfd94d | |
![]() |
d933605b56 | |
![]() |
266482deca | |
![]() |
1deefa8b7f | |
![]() |
fd8af2322c | |
![]() |
9fdc297686 | |
![]() |
fded418b8a | |
![]() |
feffe70ebb | |
![]() |
02ed988cba | |
![]() |
6eb4d8f5c5 | |
![]() |
b61c88e5df | |
![]() |
ac93c476d1 | |
![]() |
db46965761 | |
![]() |
5578c14a8e | |
![]() |
69640c0af8 | |
![]() |
0df6abe3a7 | |
![]() |
045193e797 | |
![]() |
3b37cc1ae7 | |
![]() |
b103b7570d | |
![]() |
b39f2b2d03 | |
![]() |
61d6312783 | |
![]() |
98be7071e5 | |
![]() |
5439e0c164 | |
![]() |
9be58078d2 | |
![]() |
019b539f16 | |
![]() |
ccf850552d | |
![]() |
858169aee3 | |
![]() |
80fbabc66f | |
![]() |
6d1035f1b0 | |
![]() |
063c06f9c6 | |
![]() |
43009f0c59 | |
![]() |
ca0d8cc7c1 | |
![]() |
678ec079bc | |
![]() |
eba8f6b960 | |
![]() |
760c4c2695 | |
![]() |
8ab50b1757 | |
![]() |
12c9e0c3fb | |
![]() |
b0990b7323 | |
![]() |
c36b69d7bd | |
![]() |
8e5431886a | |
![]() |
5376014b33 | |
![]() |
bccd9204e8 | |
![]() |
8932aff13f | |
![]() |
de00607dc7 | |
![]() |
118ae9a50b | |
![]() |
0683ede0fb | |
![]() |
634adae1c3 | |
![]() |
95642610da | |
![]() |
69da428a51 | |
![]() |
78c8c9d791 | |
![]() |
c690f4188a | |
![]() |
838aa71b4b | |
![]() |
2bf654da71 | |
![]() |
bf5fcdc269 | |
![]() |
515ab9e38c | |
![]() |
d4f2e97ca9 | |
![]() |
be90b53527 | |
![]() |
0b85b84dcf | |
![]() |
4e277ea9bb | |
![]() |
bf97057c2c | |
![]() |
637656b0c3 | |
![]() |
0e1b7fd94f | |
![]() |
33d1553908 | |
![]() |
2eaad16331 | |
![]() |
58998c4978 | |
![]() |
7db4265616 | |
![]() |
8a3ed32254 | |
![]() |
1151bdad0f | |
![]() |
84037f8eef | |
![]() |
3e46f27b59 | |
![]() |
719847901e | |
![]() |
fbfec0a062 | |
![]() |
9a5cbeee50 | |
![]() |
b0125de963 | |
![]() |
bf1e6fec95 | |
![]() |
5f1cb0d240 | |
![]() |
f6daa8d28f | |
![]() |
48ab5a2f99 | |
![]() |
1977074a7e | |
![]() |
72508d864b | |
![]() |
670ff3f857 | |
![]() |
a8294a9f79 | |
![]() |
9445dd23c8 | |
![]() |
2a5b18ac6e | |
![]() |
65408bfd48 | |
![]() |
a8823f523c | |
![]() |
f4b47ad94b | |
![]() |
b16c89fcd2 | |
![]() |
ae27d430e5 | |
![]() |
9dbe035efe | |
![]() |
7ebabb3778 | |
![]() |
051161f102 | |
![]() |
9802fb3ea1 | |
![]() |
5fd866b136 | |
![]() |
d956eed086 | |
![]() |
6d60eba281 | |
![]() |
bfcbd5bdef | |
![]() |
4d2a37fcd3 | |
![]() |
e5e20cca5b | |
![]() |
dcc3bb10cb | |
![]() |
7d1418d9f4 | |
![]() |
3653f37d6b | |
![]() |
f265a7bb02 | |
![]() |
89314fb4d0 | |
![]() |
b1f38eb2ec | |
![]() |
d95861aa90 | |
![]() |
0a610d818f | |
![]() |
5cc85f3cc1 | |
![]() |
98c361cbad | |
![]() |
2ac1e1d42a | |
![]() |
f3935ebb4f | |
![]() |
11c52d487d | |
![]() |
295c417f49 | |
![]() |
27c5a6c96a | |
![]() |
fc7cadb3f9 | |
![]() |
ad1d6443f2 | |
![]() |
77d0d188f0 | |
![]() |
b22bd85828 | |
![]() |
f819a1b209 | |
![]() |
dde2ff140d | |
![]() |
f429148734 | |
![]() |
23a213acda | |
![]() |
6fb47874a3 | |
![]() |
d241a06f9d | |
![]() |
3d2d5fdd99 | |
![]() |
1d9a521669 | |
![]() |
a04cae1221 | |
![]() |
add208aefb | |
![]() |
355c41b4aa | |
![]() |
3f5f3ecabf | |
![]() |
41a455f881 | |
![]() |
eda7247c2c | |
![]() |
f85485e733 | |
![]() |
a1e967dfc2 | |
![]() |
6058ca5576 | |
![]() |
dd063b8275 | |
![]() |
9c6a9fb47c | |
![]() |
516b2e5a0c | |
![]() |
d3a919b0bf | |
![]() |
261e7d0857 | |
![]() |
b393a0a2dd | |
![]() |
2b80870461 | |
![]() |
33a47bc27a | |
![]() |
53b146ab88 | |
![]() |
f3ffcdbc7e | |
![]() |
37b5d02b6d | |
![]() |
1b51e6ffb3 | |
![]() |
f39d4894e4 | |
![]() |
975d70e7ed | |
![]() |
c301c63e8b | |
![]() |
e04f73dfef | |
![]() |
8fcb3fdfe3 | |
![]() |
c7b15a96a8 | |
![]() |
e8918ce589 | |
![]() |
62dda88ea0 | |
![]() |
3741931363 | |
![]() |
7af22a70f9 | |
![]() |
087dfa2f1b | |
![]() |
799eeed346 | |
![]() |
124aae72a4 | |
![]() |
39e5824699 | |
![]() |
9df8317ece | |
![]() |
62e7f94aba | |
![]() |
47385347ee | |
![]() |
6240ab2885 | |
![]() |
328e42a9be | |
![]() |
634675e032 | |
![]() |
7ddf882a99 | |
![]() |
895b43338d | |
![]() |
9f53d53cb8 | |
![]() |
cd47a277da | |
![]() |
adec5211f1 | |
![]() |
a6a270b44a | |
![]() |
8472c25633 | |
![]() |
c1ed77f67a | |
![]() |
df6a1fdb71 | |
![]() |
321989b9c2 | |
![]() |
2f51f2d3af | |
![]() |
dc9987aea8 | |
![]() |
3715ded674 | |
![]() |
04e3819b0b | |
![]() |
587c1ca89d | |
![]() |
8a233d7c3a | |
![]() |
0464c84afc | |
![]() |
7e29eb2163 | |
![]() |
92795a828f | |
![]() |
44e5d09f22 | |
![]() |
f6afd7fffc | |
![]() |
7de1be6a9a | |
![]() |
19ec975deb | |
![]() |
4ccb1c3e19 | |
![]() |
68d295d7ef | |
![]() |
bbfb3cef7d | |
![]() |
e9ce4eb2d5 | |
![]() |
cb08f8551a | |
![]() |
f0e5da3b69 | |
![]() |
2f049329a5 | |
![]() |
350dbfedbb | |
![]() |
4b2ffd7127 | |
![]() |
a5389a22ea | |
![]() |
7a34c99935 | |
![]() |
dc480bd4b3 | |
![]() |
1d774507c0 | |
![]() |
80918cba98 | |
![]() |
197e209b4e | |
![]() |
82c4c8f0d3 | |
![]() |
23b81b0e17 | |
![]() |
f0649999fb | |
![]() |
b695dc95e3 | |
![]() |
e2d4f8c2e3 | |
![]() |
de77b0175d | |
![]() |
26f98b7b10 | |
![]() |
a9fbf98f0e | |
![]() |
fee7c04d67 | |
![]() |
8658806e3f | |
![]() |
4f3ce35e74 | |
![]() |
69c17dc255 | |
![]() |
bcc46d1d5d | |
![]() |
a40816880a | |
![]() |
2c1afa5e72 | |
![]() |
81e26a900e | |
![]() |
fc0f0d8a96 | |
![]() |
a205615af9 | |
![]() |
9b5a07220b | |
![]() |
47c84cdbad | |
![]() |
989bedda47 | |
![]() |
dd57d1e305 | |
![]() |
158cca7f8a | |
![]() |
8099391e97 | |
![]() |
7939eb1718 | |
![]() |
34373ca05d | |
![]() |
4ef70b1503 | |
![]() |
31776a2cf8 | |
![]() |
31ca070a18 | |
![]() |
f49437f002 | |
![]() |
1d01df4b85 | |
![]() |
337d958c67 | |
![]() |
94e981e00b | |
![]() |
221b203cbb | |
![]() |
dfe462ec6f | |
![]() |
8110d8cbbd | |
![]() |
c903de3c0e | |
![]() |
44d7917afd | |
![]() |
73ce708868 | |
![]() |
d211688059 | |
![]() |
9d5343ae9c | |
![]() |
2d54e2124f | |
![]() |
b5d7d582cd | |
![]() |
0399ce0ec7 | |
![]() |
94c2887c81 | |
![]() |
75e4b72c21 | |
![]() |
287a8d0c4e | |
![]() |
1e4e3cb3b4 | |
![]() |
e64a19a05a | |
![]() |
6c735fee67 | |
![]() |
f8ddc430cf | |
![]() |
641714734a | |
![]() |
46862d749b | |
![]() |
1f33babc89 | |
![]() |
b2841a27ae | |
![]() |
c0d7d041b4 | |
![]() |
10b52e0072 | |
![]() |
d64c6a8d53 | |
![]() |
058bc3622a | |
![]() |
034f71c005 | |
![]() |
c8b7848f99 | |
![]() |
75c65e094f | |
![]() |
8a0c8a8fb1 | |
![]() |
7ea18a8287 | |
![]() |
2eb071ce30 | |
![]() |
5b3ade8980 | |
![]() |
6bd8a9b984 | |
![]() |
040956819f | |
![]() |
0fd3d302e4 | |
![]() |
80a160d766 | |
![]() |
cb80e40aa6 | |
![]() |
7246e62823 | |
![]() |
925a8f6ee5 | |
![]() |
7c35bcfece | |
![]() |
fbf1c78cc8 | |
![]() |
d484e1f6a0 | |
![]() |
7fa1fe428d | |
![]() |
ac9d3e40c1 | |
![]() |
265233c34f | |
![]() |
639b746ba5 | |
![]() |
fcca4baefe | |
![]() |
9eac1a1da5 | |
![]() |
213c3a4059 | |
![]() |
4cdda535a6 | |
![]() |
5e60d7c3b0 | |
![]() |
7252149804 | |
![]() |
2a30de162c | |
![]() |
e10b659aac | |
![]() |
4201c923b5 | |
![]() |
a69a7ff82a | |
![]() |
d0eebf3791 | |
![]() |
d7f78435c1 | |
![]() |
bc5dc845ac | |
![]() |
7923c25e4f | |
![]() |
aea54ac7ad | |
![]() |
af756de1f3 | |
![]() |
775e48d428 | |
![]() |
23a8368894 | |
![]() |
714a6f4764 | |
![]() |
8318b731b4 | |
![]() |
31430f5365 | |
![]() |
c2b197a443 | |
![]() |
a2f7d6d062 | |
![]() |
b35f63788d | |
![]() |
0f634e27d5 | |
![]() |
31800cb99c | |
![]() |
6cd099d691 | |
![]() |
07907ca7f3 | |
![]() |
3cb1edad41 | |
![]() |
24c4c84576 | |
![]() |
1177c336cb | |
![]() |
0f11e4ecd4 | |
![]() |
d48cd8ef57 | |
![]() |
187f3b8c07 | |
![]() |
00422ac77b | |
![]() |
b53a5de6dc | |
![]() |
9815f817d4 | |
![]() |
6feda7be81 | |
![]() |
2a3798e9b4 | |
![]() |
ae451b71df | |
![]() |
d933f3edd5 | |
![]() |
dd60465373 | |
![]() |
60a8be3014 | |
![]() |
a26ac3e9f4 | |
![]() |
e7fdb128e3 | |
![]() |
fa53e89e51 | |
![]() |
1d6a8916cc | |
![]() |
8d0155878e | |
![]() |
333c48c6ba | |
![]() |
e79dd3508c | |
![]() |
3ca5209e0d | |
![]() |
e5e98e5776 | |
![]() |
b9000c891a | |
![]() |
125a0f7636 | |
![]() |
4c8131bd70 | |
![]() |
612c5000b5 | |
![]() |
05357a8c3f | |
![]() |
151555b7b7 | |
![]() |
c739e498c5 | |
![]() |
86450c2a1b | |
![]() |
c40fec0afa | |
![]() |
6650c4d6b1 | |
![]() |
8ef4d44787 | |
![]() |
6d83af53b5 | |
![]() |
3d77a1c1d4 | |
![]() |
36df585acf | |
![]() |
39e7b8f4b6 | |
![]() |
85b7741f3c | |
![]() |
b440215842 | |
![]() |
73bd25cbbe | |
![]() |
7473233bc9 | |
![]() |
9d210e3a30 | |
![]() |
901811bc43 | |
![]() |
9ea87fb973 | |
![]() |
dae579a88e | |
![]() |
58e8fd3e2e | |
![]() |
aae9a48dd0 | |
![]() |
09c5a3e53f | |
![]() |
985f1cfe1d | |
![]() |
e42fdd7a06 | |
![]() |
7999a2fef6 | |
![]() |
a2690a2d45 | |
![]() |
f672f873dc | |
![]() |
d94fe1c0b2 | |
![]() |
4c0f6f5865 | |
![]() |
8a659da84f | |
![]() |
3003d67c4f | |
![]() |
8b6a771318 | |
![]() |
39ac6ed89e | |
![]() |
bddf64e0ad | |
![]() |
62dc2402f3 | |
![]() |
b3dafb92ef | |
![]() |
9493dc224b | |
![]() |
cbd9e6b6ce | |
![]() |
ab8457303e | |
![]() |
168626bfeb | |
![]() |
d9304506d3 | |
![]() |
bb4b86a82e | |
![]() |
87121e2632 | |
![]() |
e39edab75a | |
![]() |
599b474ab7 | |
![]() |
09cb907bee | |
![]() |
c87ecd7ffc | |
![]() |
033e55af5d | |
![]() |
e5b9308374 | |
![]() |
171b2b643f | |
![]() |
87db9bd87d | |
![]() |
fef42fd089 | |
![]() |
361e818bcc | |
![]() |
e86a833b15 | |
![]() |
3ddc7cdd7c | |
![]() |
71c6195771 | |
![]() |
e907ffd759 | |
![]() |
18ce00d239 | |
![]() |
3cd7ca3e0b | |
![]() |
387141ae68 | |
![]() |
d5bb271dd8 | |
![]() |
9b0fb707e2 | |
![]() |
2c2a372137 | |
![]() |
ba8e17e1b5 | |
![]() |
c7e079bd65 | |
![]() |
dead1a3753 | |
![]() |
4f9b677555 | |
![]() |
44e1f020c8 | |
![]() |
9280b418d7 | |
![]() |
09ff91488c | |
![]() |
efe600e89e | |
![]() |
8b34bdfa5e | |
![]() |
3cbbba1020 | |
![]() |
3b1d48b4b4 | |
![]() |
dd1a535943 | |
![]() |
5b583962db | |
![]() |
37d35f7801 | |
![]() |
a4b6c0aee4 | |
![]() |
03f559a0dc | |
![]() |
bf1226d3bb | |
![]() |
527dec6078 | |
![]() |
af9371fe6f | |
![]() |
5c136e0286 | |
![]() |
a32d29149f | |
![]() |
e6a46b43ac | |
![]() |
9d1e5d72b5 | |
![]() |
63a688f94c | |
![]() |
21f9a1178a | |
![]() |
76573fc252 | |
![]() |
208c7ac6de | |
![]() |
44be8722f8 | |
![]() |
a435e2c090 | |
![]() |
8475542b2f | |
![]() |
40a65d19da | |
![]() |
8ad9317d11 | |
![]() |
d9b3d8057f | |
![]() |
4439e0f3c3 | |
![]() |
5edca6be5a | |
![]() |
13e1db0bc4 | |
![]() |
fdf76b9fb9 | |
![]() |
bb85f1f372 | |
![]() |
76585f75b9 | |
![]() |
3656dd5dbb | |
![]() |
7b60f2a8e6 | |
![]() |
5cf2707e11 | |
![]() |
d716421745 | |
![]() |
c6f692222d | |
![]() |
03c41177a3 | |
![]() |
c1a1b93553 | |
![]() |
6e41fbd01f | |
![]() |
093fa555ba | |
![]() |
e9d41efcec | |
![]() |
d5348f0361 | |
![]() |
e4f678f665 | |
![]() |
f00b9535d2 | |
![]() |
a1ac22443e | |
![]() |
4eb8088645 | |
![]() |
353f470c11 | |
![]() |
7a91110326 | |
![]() |
73f7f9e3b9 | |
![]() |
5bc17f0578 | |
![]() |
dbe7fe78ce | |
![]() |
40be639b63 | |
![]() |
6e1f30666b | |
![]() |
c4a61f210f | |
![]() |
0244e7f5b4 | |
![]() |
3aedf48eaf | |
![]() |
78045b4b5b | |
![]() |
894a5b955c | |
![]() |
a8dbea7c32 | |
![]() |
1d08e80165 | |
![]() |
ebc2082934 | |
![]() |
d315b61418 | |
![]() |
9673cb3a1a | |
![]() |
e4a7411ede | |
![]() |
2826ee1d04 | |
![]() |
96caaa0769 | |
![]() |
7789cb2989 | |
![]() |
9aeadaf877 | |
![]() |
53b4c5d8b2 | |
![]() |
646f0c69b2 | |
![]() |
c5159279ce | |
![]() |
ba041a767e | |
![]() |
cb6d0bd411 | |
![]() |
04752880af | |
![]() |
98867b36ae | |
![]() |
c127bac6fe | |
![]() |
f081707576 | |
![]() |
dd69527946 | |
![]() |
38d7408ecf | |
![]() |
91527cbc25 | |
![]() |
0c879fc22d | |
![]() |
c686bd2518 | |
![]() |
fc9b52e6e7 | |
![]() |
04f3e0da21 | |
![]() |
ab90e3fa08 | |
![]() |
bc3843b774 | |
![]() |
9b6e742f0c | |
![]() |
728bfe69da | |
![]() |
722f3f2ebf | |
![]() |
7bbf6d5272 | |
![]() |
3a7cb252e6 | |
![]() |
cddaf8cbc4 | |
![]() |
93c1d400c1 | |
![]() |
a7da435079 | |
![]() |
531755ebea | |
![]() |
bd87079e12 | |
![]() |
32a145a79f | |
![]() |
7a050e2498 | |
![]() |
8ad95e75c2 | |
![]() |
b3e31e1eba | |
![]() |
d5270e9a9d | |
![]() |
6d2bcf0ab8 | |
![]() |
f1f6085dbb | |
![]() |
278478b5b0 | |
![]() |
6f8c75cd6d | |
![]() |
d645ad6eda | |
![]() |
23f56561e9 | |
![]() |
2addaf35ac | |
![]() |
07940a4836 | |
![]() |
c0efc1e615 | |
![]() |
8fbdbb13a6 | |
![]() |
4724c0415e | |
![]() |
bb1ae396e0 | |
![]() |
eb29738cd8 | |
![]() |
b4b2732133 | |
![]() |
bfdc6749f9 | |
![]() |
4fc0fea5cd | |
![]() |
6e9cb0bd56 | |
![]() |
9b6bf4ac5f | |
![]() |
0c803216e5 | |
![]() |
9b554c9295 | |
![]() |
c9eb20f24b | |
![]() |
e82e4bed3e | |
![]() |
4c83c64812 | |
![]() |
babc85bc1b | |
![]() |
1ca0689233 | |
![]() |
34ebd55082 | |
![]() |
a41a9b086b | |
![]() |
74f77de5d0 | |
![]() |
7d9edbfde0 | |
![]() |
dd0653249d | |
![]() |
7c6dcba441 | |
![]() |
4a4670bdce | |
![]() |
48ade76046 | |
![]() |
b68a395e33 | |
![]() |
a7ea9bbe34 | |
![]() |
2e0f65926d | |
![]() |
9e6a592cff | |
![]() |
6d14732e2a | |
![]() |
6222e43d7a | |
![]() |
272430ba06 | |
![]() |
327489603f | |
![]() |
a154ecdfaf | |
![]() |
fa76f5c480 | |
![]() |
0d06ce26ac | |
![]() |
a298b00052 | |
![]() |
9004644738 | |
![]() |
797a1c6c8f | |
![]() |
ec177879ac | |
![]() |
669b22a54b | |
![]() |
80342f40b3 | |
![]() |
afd74c95d8 | |
![]() |
8e37ffbb97 | |
![]() |
def6a72a77 | |
![]() |
00dc2add94 | |
![]() |
790f83f4a6 | |
![]() |
3613eceff8 | |
![]() |
e146b4847d | |
![]() |
e9ba9fe110 | |
![]() |
12588250d5 | |
![]() |
b0042ab40c | |
![]() |
e7fb72ce90 | |
![]() |
2feab99b89 | |
![]() |
7bf1e0dda1 | |
![]() |
d137971e0a | |
![]() |
e81abe39ee | |
![]() |
86e69d34d9 | |
![]() |
ecab7f66d8 | |
![]() |
5724c84fe7 | |
![]() |
5d9afb7d1c | |
![]() |
cec9414d5c | |
![]() |
7127a5d816 | |
![]() |
96f508104c | |
![]() |
414e7a1c56 | |
![]() |
c86338542d | |
![]() |
ecda0a1084 | |
![]() |
47e218d7ab | |
![]() |
17acda5655 | |
![]() |
97a08423a1 | |
![]() |
ea79779ab5 | |
![]() |
cc47bb66ea | |
![]() |
d1e2f4ff27 | |
![]() |
bc5928ec42 | |
![]() |
9bd52d4ca0 | |
![]() |
00551b6263 | |
![]() |
120980cb5c | |
![]() |
a2ecd5f48e | |
![]() |
ee6d489bf4 | |
![]() |
c69cf76d3c | |
![]() |
73ce0ca7ff | |
![]() |
bac864ff83 | |
![]() |
625efff1fa | |
![]() |
2b81a7213b | |
![]() |
ccf9a410ac | |
![]() |
5c9aea8a19 | |
![]() |
71e110036e | |
![]() |
85197c4b50 | |
![]() |
00cf241315 | |
![]() |
f8cef206f3 | |
![]() |
05ff353f5d | |
![]() |
3814fc8f4e | |
![]() |
67939d3399 | |
![]() |
fa9f1f4f53 | |
![]() |
adbc39bfbd | |
![]() |
8f20fd514a | |
![]() |
4b9fe8242e | |
![]() |
32ffd6bb32 | |
![]() |
d929217752 | |
![]() |
ab26180635 | |
![]() |
4471520e35 | |
![]() |
1e8bbccdd2 | |
![]() |
eb6711f4f9 | |
![]() |
a3149521bd | |
![]() |
8f47732b45 | |
![]() |
fe7ee5b9a4 | |
![]() |
9b730ef5e2 | |
![]() |
a8d5dad362 | |
![]() |
2b8bdf3b1d | |
![]() |
2efe1af6b6 | |
![]() |
9707506c5a | |
![]() |
24ea3cd7f3 | |
![]() |
ed346d6251 | |
![]() |
f2e58b6225 | |
![]() |
cf37535d22 | |
![]() |
bf2ee6f5bd | |
![]() |
1750e163c0 | |
![]() |
ac52955caf | |
![]() |
637310015e | |
![]() |
2bafbb104c | |
![]() |
b3a0263c03 | |
![]() |
21fd0c74e8 | |
![]() |
abc4894605 | |
![]() |
5dd7a57734 | |
![]() |
f7e89998e9 | |
![]() |
ce00829d85 | |
![]() |
fc3bd1cba0 | |
![]() |
fe4c3e60bf | |
![]() |
87a0cd5a00 | |
![]() |
2ee3d43534 | |
![]() |
fdf7857f89 | |
![]() |
4c786dd7a7 | |
![]() |
207c944e21 | |
![]() |
7999cdecbf | |
![]() |
639a68521c | |
![]() |
991fa776cf | |
![]() |
55e0ad7f92 | |
![]() |
fe0fc8084f | |
![]() |
f0c770def0 | |
![]() |
f771a1aec0 | |
![]() |
be7a73a7e6 | |
![]() |
78c436b990 | |
![]() |
f0bc380527 | |
![]() |
c7492a0b59 | |
![]() |
5edc8cadca | |
![]() |
04baae5a57 | |
![]() |
3cf5d4fa43 | |
![]() |
6056b751b6 | |
![]() |
31c3a6f693 | |
![]() |
ad06a9ee05 | |
![]() |
2ec21c95a7 | |
![]() |
2e0bfd1f01 | |
![]() |
d9cdfa67db | |
![]() |
2d0e2b6899 | |
![]() |
91c6a28205 | |
![]() |
2b0adaf717 | |
![]() |
43b218806a | |
![]() |
8f9875e518 | |
![]() |
5d38b3cf8d | |
![]() |
c615251136 | |
![]() |
d12edaea6f | |
![]() |
34869eceb5 | |
![]() |
23624679fe | |
![]() |
42e34a63ec | |
![]() |
037470e1d2 | |
![]() |
b952038db1 | |
![]() |
5cc603d84c | |
![]() |
53fa27771d | |
![]() |
5c23d97daf | |
![]() |
95ce5f4eb1 | |
![]() |
4846bd0f65 | |
![]() |
6d4248d046 | |
![]() |
d442db08eb | |
![]() |
7657157586 | |
![]() |
ae4085f7c0 | |
![]() |
3d2a80b3bb | |
![]() |
41fe8be1f6 | |
![]() |
1418422bcf | |
![]() |
1d47959606 | |
![]() |
b88d97a314 | |
![]() |
ab79b4b078 | |
![]() |
f0385d7c24 | |
![]() |
7624d80abe | |
![]() |
62428b6df3 | |
![]() |
26f1b98728 | |
![]() |
10fed707f8 | |
![]() |
239354e313 | |
![]() |
b62c1564ec | |
![]() |
ce767f2e0d | |
![]() |
b25c5cc28e | |
![]() |
9693e4b10b | |
![]() |
dab6f90f81 | |
![]() |
f6d1b848e4 | |
![]() |
3d3dcd5c44 | |
![]() |
23f5fba013 | |
![]() |
7dda6e8e07 | |
![]() |
3297f7aa58 | |
![]() |
8013592e82 | |
![]() |
7c9c95cc37 | |
![]() |
615d7c7d32 | |
![]() |
dd0b0b2eb9 | |
![]() |
98755f332c | |
![]() |
ab2df12cce | |
![]() |
0a5dbf3642 | |
![]() |
efa045ab9c | |
![]() |
3e8959ad22 | |
![]() |
81ab68f696 | |
![]() |
5c90cc251e | |
![]() |
3fc7a050ec | |
![]() |
5b20498792 | |
![]() |
d71df4b3ba | |
![]() |
b13756ffbe | |
![]() |
ad76bb678d | |
![]() |
8a3724ff89 | |
![]() |
1d33c51d24 | |
![]() |
f6725f86c2 | |
![]() |
2213d0ed62 | |
![]() |
3c0979c5e4 | |
![]() |
ed3740048a | |
![]() |
ca2ad60aef | |
![]() |
26496ba0a9 | |
![]() |
620214d536 | |
![]() |
30bbd4c3b4 | |
![]() |
41f4187593 | |
![]() |
e1613fa9d4 | |
![]() |
8b2b402f73 | |
![]() |
b265d75c9a | |
![]() |
0bc1e0a620 | |
![]() |
8beb37f64a | |
![]() |
862a2b36e3 | |
![]() |
8526a7eb81 | |
![]() |
3791cfc37c | |
![]() |
c6ab969a96 | |
![]() |
9cfeace7f8 | |
![]() |
47f1bb050b | |
![]() |
e9c9fbae21 | |
![]() |
73ebf4c518 | |
![]() |
b645f827d0 | |
![]() |
3ff4f6b926 | |
![]() |
b6c1b3ed86 | |
![]() |
4e70c6dd77 | |
![]() |
7aae6f675c | |
![]() |
1c9cfd19e6 | |
![]() |
72f82771f1 | |
![]() |
cbbf9f8f51 | |
![]() |
89435951ae | |
![]() |
02e6fecc6d | |
![]() |
5cc1bd715d | |
![]() |
246e1163bb | |
![]() |
2a47de6c57 | |
![]() |
384ea35ca7 | |
![]() |
257f7f03b5 | |
![]() |
b77ca0eed7 | |
![]() |
ebd52af454 | |
![]() |
b02af565a6 | |
![]() |
a3799fb0ea | |
![]() |
443640effa | |
![]() |
79ea8918e5 | |
![]() |
46b216274f | |
![]() |
47066753ac | |
![]() |
ae9ab9c5b0 | |
![]() |
9784b429f5 | |
![]() |
06516ec60d | |
![]() |
2c2c070663 | |
![]() |
18cc95fa30 | |
![]() |
66eb020ce1 | |
![]() |
31c8339315 | |
![]() |
af2e2683b4 | |
![]() |
9791231e63 | |
![]() |
883d6e21ad | |
![]() |
0ee974a3aa | |
![]() |
296a2e549a | |
![]() |
5543ce6add | |
![]() |
7ec6831508 | |
![]() |
cd6c6ff048 | |
![]() |
07ee749023 | |
![]() |
4204ff0736 | |
![]() |
b9ff4eabcc | |
![]() |
9d469fb2af | |
![]() |
8eb43a4848 | |
![]() |
c685b46704 | |
![]() |
0f833cb536 | |
![]() |
9c0464d072 | |
![]() |
6e5390cec4 | |
![]() |
bcc5ca40ec | |
![]() |
d9cd6f2ba5 | |
![]() |
7bc9c78d51 | |
![]() |
7d7f0f326c | |
![]() |
6c28a8e40c | |
![]() |
8e207009b0 | |
![]() |
fcd6add766 | |
![]() |
95a1b4a964 | |
![]() |
30f87e6193 | |
![]() |
0a404e88b7 | |
![]() |
ee3188a782 | |
![]() |
3b1510b70e | |
![]() |
6f5730b8ac | |
![]() |
5ed8f8686d | |
![]() |
3bb093cb23 | |
![]() |
56a9b9a405 | |
![]() |
b19c8dd650 | |
![]() |
9ed73529a6 | |
![]() |
698b684233 | |
![]() |
75be0189d6 | |
![]() |
bde57724b7 | |
![]() |
eea3fe9015 | |
![]() |
6fad9ead9e | |
![]() |
5265440f76 | |
![]() |
c07e3f0831 | |
![]() |
79ae8006a8 | |
![]() |
af54405381 | |
![]() |
fbabea9065 | |
![]() |
4a80b556f8 | |
![]() |
65fc82e105 | |
![]() |
0dd60654c5 | |
![]() |
dfe590240f | |
![]() |
e8a77eb3a9 | |
![]() |
0113abb6f6 | |
![]() |
b336d3acca | |
![]() |
57469f4be8 | |
![]() |
96299c5812 | |
![]() |
cf4ab5470c | |
![]() |
7df7d788f8 | |
![]() |
8dfe7eed8b | |
![]() |
7461188c60 | |
![]() |
95cae149c4 | |
![]() |
61bf98e641 | |
![]() |
0ae5d7a324 | |
![]() |
be9d448ec9 | |
![]() |
fe54804b21 | |
![]() |
8ade6ebce2 | |
![]() |
b20865ffb6 | |
![]() |
ddc34539a9 | |
![]() |
bbfe451d5e | |
![]() |
5ad66497e5 | |
![]() |
3a141b2e9b | |
![]() |
b07882d92f | |
![]() |
5398550d35 | |
![]() |
e28168e0be | |
![]() |
51874d9cee | |
![]() |
7a64fe544d | |
![]() |
67066e2fb6 | |
![]() |
5af08c0904 | |
![]() |
d129670882 | |
![]() |
3e05460d09 | |
![]() |
84b9ac5904 | |
![]() |
876720f31b | |
![]() |
f5986a9cc9 | |
![]() |
3b3c71b3a0 | |
![]() |
74038a0f61 | |
![]() |
723785ef4e | |
![]() |
042bf616f8 | |
![]() |
cf9627e16d | |
![]() |
85eb1066a3 | |
![]() |
87a4007dd3 | |
![]() |
91dbc39bad | |
![]() |
dc4275129b | |
![]() |
45c0583426 | |
![]() |
c3400115dd | |
![]() |
a61f7fdd11 | |
![]() |
685460591d | |
![]() |
8f77208806 | |
![]() |
bbf1cc8a6f | |
![]() |
215a4d5752 | |
![]() |
0ef6cc81b4 | |
![]() |
bb2af2c730 | |
![]() |
61afa1571f | |
![]() |
641afe1b34 | |
![]() |
6dfc8375c8 | |
![]() |
fd02bcfb7b | |
![]() |
e38e59d05a | |
![]() |
80f9b9e8ac | |
![]() |
3ce5046dd5 | |
![]() |
42afcbbfbc | |
![]() |
9f5ac8d441 | |
![]() |
247032833b | |
![]() |
c57da055fc | |
![]() |
35bcec1e80 | |
![]() |
6f0dab1f72 | |
![]() |
166bac62b4 | |
![]() |
8e15f126eb | |
![]() |
943a345a92 | |
![]() |
a938bcb4de | |
![]() |
7b03f8a739 | |
![]() |
26b07115cd | |
![]() |
fdc2012b90 | |
![]() |
fbd9a21dc8 | |
![]() |
c16a5d46ae | |
![]() |
75e53514dc | |
![]() |
c8617dc9ee | |
![]() |
a5604bb967 | |
![]() |
a5779f2d18 | |
![]() |
42cc616ed3 | |
![]() |
15d4b2eb2c | |
![]() |
6b4a1c8f61 | |
![]() |
abcc545484 | |
![]() |
1272457517 | |
![]() |
17a1ca5edf | |
![]() |
a9f6365d78 | |
![]() |
7fbb0a0947 | |
![]() |
9322965027 | |
![]() |
816665f935 | |
![]() |
40f361fe1f | |
![]() |
7e9e5af63f | |
![]() |
a6d9d36343 | |
![]() |
c76b46fa1a | |
![]() |
333331a11c | |
![]() |
40d08f73bb | |
![]() |
f6868abbdb | |
![]() |
7d67e0e7f2 | |
![]() |
4fc7c1666a | |
![]() |
0373e3d523 | |
![]() |
d41d7a610c | |
![]() |
f2994c8fcc | |
![]() |
8fc4d7ac9c | |
![]() |
80fe6953ce | |
![]() |
d7a124c59d | |
![]() |
f0f71787c7 | |
![]() |
3a968fdd33 | |
![]() |
3f71a14874 | |
![]() |
73d68b9040 | |
![]() |
bb03efcf7a | |
![]() |
98b5e5d53f | |
![]() |
7638d3cc69 | |
![]() |
bd0bc086c1 | |
![]() |
f64d7adb22 | |
![]() |
350242129e | |
![]() |
e87f80bce3 | |
![]() |
9536fdd157 | |
![]() |
21de9fb209 | |
![]() |
a00ef07cd8 | |
![]() |
c4f6eb603e | |
![]() |
cc0a53c191 |
|
@ -0,0 +1,36 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const restCssPath = path.join(process.cwd(), 'components', 'style', 'reset.css');
|
||||
const tokenStatisticPath = path.join(process.cwd(), 'components', 'version', 'token.json');
|
||||
const tokenMetaPath = path.join(process.cwd(), 'components', 'version', 'token-meta.json');
|
||||
|
||||
function finalizeCompile() {
|
||||
if (fs.existsSync(path.join(__dirname, './es'))) {
|
||||
fs.copyFileSync(restCssPath, path.join(process.cwd(), 'es', 'style', 'reset.css'));
|
||||
fs.copyFileSync(tokenStatisticPath, path.join(process.cwd(), 'es', 'version', 'token.json'));
|
||||
fs.copyFileSync(tokenMetaPath, path.join(process.cwd(), 'es', 'version', 'token-meta.json'));
|
||||
}
|
||||
|
||||
if (fs.existsSync(path.join(__dirname, './lib'))) {
|
||||
fs.copyFileSync(restCssPath, path.join(process.cwd(), 'lib', 'style', 'reset.css'));
|
||||
fs.copyFileSync(tokenStatisticPath, path.join(process.cwd(), 'lib', 'version', 'token.json'));
|
||||
fs.copyFileSync(tokenMetaPath, path.join(process.cwd(), 'lib', 'version', 'token-meta.json'));
|
||||
}
|
||||
}
|
||||
|
||||
function finalizeDist() {
|
||||
if (fs.existsSync(path.join(__dirname, './dist'))) {
|
||||
fs.copyFileSync(restCssPath, path.join(process.cwd(), 'dist', 'reset.css'));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
compile: {
|
||||
finalize: finalizeCompile,
|
||||
},
|
||||
dist: {
|
||||
finalize: finalizeDist,
|
||||
},
|
||||
bail: true,
|
||||
};
|
|
@ -7,3 +7,7 @@ es/
|
|||
lib/
|
||||
_site/
|
||||
dist/
|
||||
site/dist/
|
||||
components/version/version.ts
|
||||
site/src/router/demoRoutes.js
|
||||
locale/
|
39
.eslintrc.js
39
.eslintrc.js
|
@ -15,9 +15,21 @@ module.exports = {
|
|||
'plugin:vue/vue3-recommended',
|
||||
'plugin:import/recommended',
|
||||
'plugin:import/typescript',
|
||||
'prettier',
|
||||
'@vue/typescript/recommended',
|
||||
'@vue/prettier',
|
||||
// 'prettier',
|
||||
],
|
||||
// extends: [
|
||||
// 'eslint:recommended',
|
||||
// 'plugin:vue/vue3-recommended',
|
||||
// '@vue/typescript/recommended',
|
||||
// '@vue/prettier',
|
||||
// ],
|
||||
plugins: ['markdown', 'jest', '@typescript-eslint', 'import'],
|
||||
globals: {
|
||||
h: true,
|
||||
defineProps: 'readonly',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.md'],
|
||||
|
@ -28,12 +40,11 @@ module.exports = {
|
|||
},
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
extends: ['@vue/typescript/recommended', '@vue/prettier', '@vue/prettier/@typescript-eslint'],
|
||||
// extends: ['@vue/typescript/recommended', '@vue/prettier'],
|
||||
parserOptions: {
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 0,
|
||||
'@typescript-eslint/ban-types': 0,
|
||||
'@typescript-eslint/consistent-type-imports': 'error',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 0,
|
||||
|
@ -51,17 +62,21 @@ module.exports = {
|
|||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
ecmaVersion: 2021,
|
||||
},
|
||||
rules: {
|
||||
'no-console': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ vars: 'all', args: 'after-used', ignoreRestSiblings: true },
|
||||
],
|
||||
'vue/no-reserved-component-names': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 0,
|
||||
'@typescript-eslint/no-empty-function': 0,
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ vars: 'all', args: 'after-used', ignoreRestSiblings: true, argsIgnorePattern: '^_' },
|
||||
],
|
||||
'import/no-named-as-default': 'off',
|
||||
'import/namespace': [2, { allowComputed: true }],
|
||||
'import/no-named-as-default-member': 'off',
|
||||
|
@ -84,18 +99,14 @@ module.exports = {
|
|||
'vue/prop-name-casing': 'off',
|
||||
'vue/one-component-per-file': 'off',
|
||||
'vue/custom-event-name-casing': 'off',
|
||||
'vue/v-on-event-hyphenation': 'off',
|
||||
'vue/max-attributes-per-line': [
|
||||
2,
|
||||
{
|
||||
singleline: 20,
|
||||
multiline: {
|
||||
max: 1,
|
||||
allowFirstLine: false,
|
||||
},
|
||||
multiline: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
globals: {
|
||||
h: true,
|
||||
'vue/multi-word-component-names': 'off',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
blank_issues_enabled: false
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Create new issue
|
||||
url: https://vuecomponent.github.io/issue-helper/
|
||||
|
@ -13,5 +13,5 @@ contact_links:
|
|||
url: https://www.paypal.me/tangjinzhou
|
||||
about: Love Ant Design Vue? Please consider supporting us via Paypal.
|
||||
- name: 支付宝/微信 赞助
|
||||
url: https://qn.antdv.com/alipay-and-wechat.png
|
||||
url: https://aliyuncdn.antdv.com/alipay-and-wechat.png
|
||||
about: Ant Design Vue 的健康持续发展需要您的支持,🙏
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
首先,感谢你的贡献! 😄
|
||||
|
||||
新特性请提交至 feature 分支,其余可提交至 master 分支。在一个维护者审核通过后合并。请确保填写以下 pull request 的信息,谢谢!~
|
||||
新特性请提交至 feature 分支,其余可提交至 main 分支。在一个维护者审核通过后合并。请确保填写以下 pull request 的信息,谢谢!~
|
||||
|
||||
[[English Template / 英文模板](?expand=1)]
|
||||
[[English Template / 英文模板](./pr_en.md)]
|
||||
|
||||
### 这个变动的性质是
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
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!
|
||||
New feature please send pull request to feature branch, and rest to main 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/vueComponent/ant-design-vue/blob/master/.github/PULL_REQUEST_TEMPLATE/pr_cn.md)]
|
||||
[[中文版模板 / Chinese template](./pr_cn.md)]
|
||||
|
||||
### This is a ...
|
||||
|
|
@ -16,7 +16,7 @@ jobs:
|
|||
key: lock-${{ github.sha }}
|
||||
|
||||
- name: create package-lock.json
|
||||
run: npm i --package-lock-only
|
||||
run: npm i --package-lock-only --ignore-scripts
|
||||
|
||||
- name: hack for singe file
|
||||
run: |
|
||||
|
|
|
@ -4,12 +4,15 @@ on:
|
|||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
close-issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: need reproduce
|
||||
uses: actions-cool/issues-helper@v1.7
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'close-issues'
|
||||
labels: '🤔 Need Reproduce'
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
name: Issue Reply
|
||||
name: Issue Labeled
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
issue-reply:
|
||||
issue-labeled:
|
||||
permissions:
|
||||
issues: write # for actions-cool/issues-helper to update issues
|
||||
pull-requests: write # for actions-cool/issues-helper to update PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Need Reproduce
|
||||
if: github.event.label.name == '🤔 Need Reproduce'
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hello @${{ github.event.issue.user.login }}. Please provide a online reproduction by forking this [link for vue2](https://codesandbox.io/s/2wpk21kzvr)、 [link for vue3](https://codesandbox.io/s/agitated-franklin-1w72v) or a minimal GitHub repository. Make sure to choose the correct version.
|
||||
|
@ -21,9 +28,10 @@ jobs:
|
|||
|
||||
- name: help wanted
|
||||
if: github.event.label.name == 'help wanted'
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hello @${{ github.event.issue.user.login }}. We totally like your proposal/feedback, welcome to send us a Pull Request for it. Please send your Pull Request to proper branch, fill the Pull Request Template here, provide changelog/TypeScript/documentation/test cases if needed and make sure CI passed, we will review it soon. We appreciate your effort in advance and looking forward to your contribution!
|
||||
|
@ -32,12 +40,37 @@ jobs:
|
|||
|
||||
- name: Usage
|
||||
if: github.event.label.name == 'Usage'
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment, close-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hello @${{ github.event.issue.user.login }}, we use GitHub issues to trace bugs or discuss plans of Ant Design Vue. So, please don't ask usage questions here. You can try to open a new discussion in [antdv discussions](https://github.com/vueComponent/ant-design-vue/discussions), select `Q&A` to ask questions, also can ask questions on [Stack Overflow](http://stackoverflow.com/questions/) or [Segment Fault](https://segmentfault.com).
|
||||
|
||||
你好 @${{ github.event.issue.user.login }},Ant Design Vue Issue 板块是用于 bug 反馈与需求讨论的地方。请勿询问如何使用的问题,你可以试着在 [antdv discussions](https://github.com/vueComponent/ant-design-vue/discussions) 新开一个 discussion,选择 `Q&A` 类别进行提问,也可以在 [Stack Overflow](http://stackoverflow.com/questions/) 或者 [Segment Fault](https://segmentfault.com/) 中提问。
|
||||
|
||||
- name: 1.x
|
||||
if: github.event.label.name == '1.x'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment,close-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hi @${{ github.event.issue.user.login }}. Current version (1.x) is off the maintenance period. We may not accept pull request or fix bug with it anymore. This topic will be auto closed.
|
||||
|
||||
你好 @${{ github.event.issue.user.login }},当前版本(1.x)已经过了维护期。我们不会再接受对其的相关 PR 与 issue。当前 topic 会被自动关闭。
|
||||
|
||||
- name: 2.x
|
||||
if: github.event.label.name == '2.x'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment,close-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hi @${{ github.event.issue.user.login }}. Current version (2.x) is off the maintenance period. We may not accept pull request or fix bug with it anymore. This topic will be auto closed.
|
||||
|
||||
你好 @${{ github.event.issue.user.login }},当前版本(2.x)已经过了维护期。我们不会再接受对其的相关 PR 与 issue。当前 topic 会被自动关闭。
|
||||
|
|
@ -4,8 +4,16 @@ on:
|
|||
issues:
|
||||
types: [opened]
|
||||
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-issue:
|
||||
issue-open-check:
|
||||
permissions:
|
||||
contents: read # for visiky/dingtalk-release-notify to get latest release
|
||||
issues: write # for actions-cool/issues-helper to update issues
|
||||
pull-requests: write # for actions-cool/issues-helper to update PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions-cool/check-user-permission@v1.0.0
|
||||
|
@ -15,7 +23,7 @@ jobs:
|
|||
|
||||
- name: check invalid
|
||||
if: (contains(github.event.issue.body, 'issue-helper') == false) && (steps.checkUser.outputs.result == 'false')
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment,add-labels,close-issue'
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
name: PR Labeled
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
reply:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Usage
|
||||
if: github.event.label.name == 'Usage'
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
with:
|
||||
actions: 'create-comment, close-issue'
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
Hello @${{ github.event.pull_request.user.login }}, we use GitHub PR to build and perfect of Ant Design Vue. So, please don't ask usage questions here. You can try to open a new discussion in [antdv discussions](https://github.com/vueComponent/ant-design-vue/discussions), select `Q&A` to ask questions, also can ask questions on [Stack Overflow](http://stackoverflow.com/questions/) or [Segment Fault](https://segmentfault.com).
|
||||
|
||||
你好 @${{ github.event.pull_request.user.login }},Ant Design Vue PR 是用于建设、完善项目的地方。请勿询问如何使用的问题,你可以试着在 [antdv discussions](https://github.com/vueComponent/ant-design-vue/discussions) 新开一个 discussion,选择 `Q&A` 类别进行提问,也可以在 [Stack Overflow](http://stackoverflow.com/questions/) 或者 [Segment Fault](https://segmentfault.com/) 中提问。
|
|
@ -7,7 +7,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@master
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: cache package-lock.json
|
||||
uses: actions/cache@v2
|
||||
|
@ -16,7 +16,7 @@ jobs:
|
|||
key: lock-${{ github.sha }}
|
||||
|
||||
- name: create package-lock.json
|
||||
run: npm i --package-lock-only
|
||||
run: npm i --package-lock-only --ignore-scripts
|
||||
|
||||
- name: hack for singe file
|
||||
run: |
|
||||
|
@ -40,7 +40,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@master
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: restore cache from package-lock.json
|
||||
uses: actions/cache@v2
|
||||
|
@ -74,7 +74,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@master
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: restore cache from package-lock.json
|
||||
uses: actions/cache@v2
|
||||
|
@ -96,17 +96,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@master
|
||||
|
||||
# with:
|
||||
# token: ${{ secrets.ACCESS_TOKEN }}
|
||||
# - name: Checkout submodules
|
||||
# uses: actions/checkout@master
|
||||
# with:
|
||||
# repository: tangjinzhou/antdv-demo
|
||||
# token: ${{ secrets.ACCESS_TOKEN }}
|
||||
# path: antdv-demo
|
||||
# submodules: true
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: restore cache from package-lock.json
|
||||
uses: actions/cache@v2
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
name: Translation Helper
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
translate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: issue
|
||||
if: github.event_name == 'issues'
|
||||
uses: actions-cool/translation-helper@v1.1.1
|
||||
with:
|
||||
translate-body: false
|
||||
|
||||
- name: pr
|
||||
if: github.event_name == 'pull_request_target'
|
||||
uses: actions-cool/translation-helper@v1.1.1
|
||||
with:
|
||||
translate-body: false
|
|
@ -59,9 +59,11 @@ jspm_packages/
|
|||
dist
|
||||
lib
|
||||
es
|
||||
/locale
|
||||
_site
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
/coverage
|
||||
|
||||
# 备份文件
|
||||
|
@ -76,3 +78,9 @@ vetur/
|
|||
report.html
|
||||
|
||||
site/src/router/demoRoutes.js
|
||||
|
||||
components/version/version.ts
|
||||
components/version/version.tsx
|
||||
components/version/token.json
|
||||
components/version/token-meta.json
|
||||
~component-api.json
|
||||
|
|
35
.jest.js
35
.jest.js
|
@ -9,41 +9,48 @@ const transformIgnorePatterns = [
|
|||
];
|
||||
const testPathIgnorePatterns = ['/node_modules/', 'node'];
|
||||
|
||||
function getTestRegex(libDir) {
|
||||
if (libDir === 'dist') {
|
||||
return 'demo\\.test\\.js$';
|
||||
}
|
||||
return '.*\\.test\\.(j|t)sx?$';
|
||||
}
|
||||
module.exports = {
|
||||
testURL: 'http://localhost/',
|
||||
verbose: true,
|
||||
setupFiles: ['./tests/setup.js'],
|
||||
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
||||
moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json', 'vue', 'md', 'jpg'],
|
||||
modulePathIgnorePatterns: ['/_site/'],
|
||||
testPathIgnorePatterns: testPathIgnorePatterns,
|
||||
transform: {
|
||||
'^.+\\.(vue|md)$': '<rootDir>/node_modules/vue-jest',
|
||||
'^.+\\.(js|jsx)$': '<rootDir>/node_modules/babel-jest',
|
||||
'^.+\\.(ts|tsx)$': '<rootDir>/node_modules/ts-jest',
|
||||
'^.+\\.svg$': '<rootDir>/node_modules/jest-transform-stub',
|
||||
'\\.(vue|md)$': '<rootDir>/node_modules/@vue/vue3-jest',
|
||||
'\\.(js|jsx)$': '<rootDir>/node_modules/babel-jest',
|
||||
'\\.(ts|tsx)$': '<rootDir>/node_modules/ts-jest',
|
||||
'\\.svg$': '<rootDir>/node_modules/jest-transform-stub',
|
||||
},
|
||||
testRegex: libDir === 'dist' ? 'demo\\.test\\.js$' : '.*\\.test\\.js$',
|
||||
testRegex: getTestRegex(libDir),
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/$1',
|
||||
'ant-design-vue$': '<rootDir>/components/index.ts',
|
||||
'ant-design-vue/es': '<rootDir>/components',
|
||||
'^@/(.*)$/': '<rootDir>/$1',
|
||||
'^ant-design-vue$': '<rootDir>/components/index',
|
||||
'^ant-design-vue/es/(.*)$': '<rootDir>/components/$1',
|
||||
},
|
||||
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
|
||||
collectCoverage: process.env.COVERAGE === 'true',
|
||||
collectCoverageFrom: [
|
||||
'components/**/*.{js,jsx,vue}',
|
||||
'!components/*/style/index.{js,jsx}',
|
||||
'!components/style/*.{js,jsx}',
|
||||
'!components/*/locale/*.{js,jsx}',
|
||||
'!components/*/__tests__/**/type.{js,jsx}',
|
||||
'!components/vc-*/**/*',
|
||||
'!components/*/demo/**/*',
|
||||
'!components/_util/**/*',
|
||||
'!components/align/**/*',
|
||||
'!components/trigger/**/*',
|
||||
'!components/style.js',
|
||||
'!**/node_modules/**',
|
||||
],
|
||||
testEnvironment: 'jest-environment-jsdom-fifteen',
|
||||
testEnvironment: 'jsdom',
|
||||
testEnvironmentOptions: {
|
||||
url: 'http://localhost',
|
||||
customExportConditions: ['node', 'node-addons'],
|
||||
},
|
||||
transformIgnorePatterns,
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
|
|
|
@ -18,7 +18,6 @@ yarn-error.log
|
|||
.editorconfig
|
||||
.eslintignore
|
||||
**/*.yml
|
||||
components/style/color/*.less
|
||||
**/assets
|
||||
.gitattributes
|
||||
.stylelintrc
|
||||
|
|
|
@ -4,13 +4,40 @@
|
|||
"stylelint-config-rational-order",
|
||||
"stylelint-config-prettier"
|
||||
],
|
||||
"plugins": ["stylelint-order", "stylelint-declaration-block-no-ignored-properties"],
|
||||
"customSyntax": "postcss-less",
|
||||
"plugins": ["stylelint-declaration-block-no-ignored-properties"],
|
||||
"rules": {
|
||||
"comment-empty-line-before": null,
|
||||
"function-name-case": ["lower", { "ignoreFunctions": ["/colorPalette/"] }],
|
||||
"no-invalid-double-slash-comments": null,
|
||||
"no-descending-specificity": null,
|
||||
"declaration-empty-line-before": null
|
||||
},
|
||||
"ignoreFiles": ["components/style/color/{bezierEasing,colorPalette,tinyColor}.less"]
|
||||
"function-name-case": ["lower"],
|
||||
"function-no-unknown": [
|
||||
true,
|
||||
{
|
||||
"ignoreFunctions": [
|
||||
"fade",
|
||||
"fadeout",
|
||||
"tint",
|
||||
"darken",
|
||||
"ceil",
|
||||
"fadein",
|
||||
"floor",
|
||||
"unit",
|
||||
"shade",
|
||||
"lighten",
|
||||
"percentage",
|
||||
"-"
|
||||
]
|
||||
}
|
||||
],
|
||||
"import-notation": null,
|
||||
"no-descending-specificity": null,
|
||||
"no-invalid-position-at-import-rule": null,
|
||||
"declaration-empty-line-before": null,
|
||||
"keyframes-name-pattern": null,
|
||||
"custom-property-pattern": null,
|
||||
"number-max-precision": 8,
|
||||
"alpha-value-notation": "number",
|
||||
"color-function-notation": "legacy",
|
||||
"selector-class-pattern": null,
|
||||
"selector-id-pattern": null,
|
||||
"selector-not-notation": null
|
||||
}
|
||||
}
|
||||
|
|
3
.vcmrc
3
.vcmrc
|
@ -9,7 +9,8 @@
|
|||
"perf",
|
||||
"test",
|
||||
"chore",
|
||||
"revert"
|
||||
"revert",
|
||||
"ci"
|
||||
],
|
||||
"warnOnFail": false,
|
||||
"autoFix": false
|
||||
|
|
|
@ -10,713 +10,229 @@
|
|||
|
||||
---
|
||||
|
||||
## 3.0.0-alpha.1
|
||||
|
||||
`2021-10-07`
|
||||
|
||||
- 🌟 Refactor `Tabs` [#4732](https://github.com/vueComponent/ant-design-vue/issues/4732)
|
||||
- Removed `prevClick`, `nextClick` events, and use `tabScroll` event instead
|
||||
- Obsolete the `tabBarExtraContent` slot, replace it with the rightExtra slot, and add the `leftExtra` slot
|
||||
- Added `addIcon`, `closeIcon`, `moreIcon` slots
|
||||
- 🌟 Refactor `Card`, discard the tabList slots configuration, and use the customTab slot for unified configuration [#4732](https://github.com/vueComponent/ant-design-vue/issues/4732)
|
||||
- 🌟 Refactor `Drawer`
|
||||
- Added `autofocus` `contentWrapperStyle` `footerStyle` `headerStyle` `push` `size` `forceRender` and other attributes
|
||||
- Added `closeIcon` `extra` `footer` and other slots
|
||||
- Deprecated `afterVisibleChange` property, use event with the same name instead
|
||||
- 🐞 Fix the problem that `Table` pagination does not respond to changes [1add0d](https://github.com/vueComponent/ant-design-vue/commit/1add0d251cd35aa2c55404f7a60f1531425490c1)
|
||||
- 🐞 Fix `notification` style misalignment problem [#4703](https://github.com/vueComponent/ant-design-vue/issues/4703)
|
||||
- 🐞 Fix the selection, dragging and other abnormalities caused by `Tree` fieldsName [#4726](https://github.com/vueComponent/ant-design-vue/issues/4726)
|
||||
|
||||
## 3.0.0-alpha.0
|
||||
|
||||
`2021-09-24`
|
||||
|
||||
🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
||||
|
||||
- Open source documentation
|
||||
- Removed the `lazy` attribute of Transfer, it does not have a real optimization effect.
|
||||
- Removed the `combobox` mode of Select, please use `AutoComplete` instead.
|
||||
- Deprecated Button.Group, please use `Space` instead.
|
||||
- `Timeline.Item` new label
|
||||
- `Steps` added `responsive`, `percent`
|
||||
- `Collapse` added `ghost`, `collapsible`
|
||||
- `Popconfirm` added `cancelButton`, `okButton`, and `esc` button hiding
|
||||
- `ConfigProvider` added ConfigProvider.config to define the configuration of `Modal.xxx` `message` `notification`
|
||||
- `Tree` `TreeSlelct`
|
||||
|
||||
- Added virtual scrolling, discarded using `a-tree-node` `a-tree-select-node` to build nodes, using `treeData` property instead to improve component performance
|
||||
- Deprecated `scopedSlots` `slots` custom rendering node, and replace it with `v-slot:title` to improve ease of use, avoid slot configuration expansion, and also avoid slot conflicts
|
||||
|
||||
- `Table`
|
||||
|
||||
- Removed the `rowSelection.hideDefaultSelections` property of Table, please use `SELECTION_ALL` and `SELECTION_INVERT` in `rowSelection.selections` instead, [custom options](/components/table/#components-table-demo- row-selection-custom).
|
||||
- Removed Column slots and replaced them with `v-slot:headerCell` `v-slot:headerCell` `v-slot:bodyCell` `v-slot:customFilterDropdown` `v-slot:customFilterIcon` to improve ease of use , To avoid slot configuration expansion, but also to avoid the problem of slot conflicts
|
||||
- Added expandFixed to control whether the expanded icon is fixed
|
||||
- Added the showSorterTooltip header whether to display the tooltip for the next sort.
|
||||
- Added sticky for setting sticky head and scroll bar
|
||||
- Added rowExpandable to set whether to allow row expansion
|
||||
- New slot headerCell is used to personalize the header cell
|
||||
- Added slot bodyCell for personalized cell
|
||||
- New slot customFilterDropdown is used to customize the filter menu, which needs to be used with `column.customFilterDropdown`
|
||||
- Added slot customFilterIcon for custom filter icons
|
||||
- New slot emptyText is used to customize the display content of empty data
|
||||
- Added slot summary for the summary column
|
||||
|
||||
- `DatePicker` `TimePicker` `Calendar`
|
||||
|
||||
- By default, a more lightweight dayjs is used to replace momentjs. If your project is too large and uses a lot of momentjs methods, you can refer to the document [Custom Time Library](/docs/vue/replace-date-cn), Replace with momentjs.
|
||||
- UI interaction adjustment, its antd 4.x interaction specification
|
||||
|
||||
- `Form` The main goal of this update is to improve performance. If you don't have custom form controls, you can almost ignore this part
|
||||
|
||||
- Since version 3.0, Form.Item no longer hijacks child elements, but automatically checks through provider/inject dependency injection. This method can improve component performance, and there is no limit to the number of child elements. The same is true for child elements. It can be a high-level component that is further encapsulated.
|
||||
|
||||
You can reference [Customized Form Controls](#components-form-demo-customized-form-controls)
|
||||
|
||||
But it also has some disadvantages:
|
||||
|
||||
1. If the custom component wants Form.Item to be verified and displayed, you need to inject `const {id, onFieldChange, onFieldBlur} = useFormItemContext()` and call the corresponding method.
|
||||
## 4.2.6
|
||||
|
||||
2. A Form.Item can only collect the data of one form item. If there are multiple form items, it will cause collection confusion, for example,
|
||||
|
||||
```html
|
||||
<a-form-item>
|
||||
<a-input name="a"></a-input>
|
||||
<a-input name="b"></a-input>
|
||||
</a-form-item>
|
||||
```
|
||||
- 🐞 Fix Modal component aria-hidden error problem under chrome [#7823](https://github.com/vueComponent/ant-design-vue/issues/7823)
|
||||
- 🐞 Fix the problem that the built-in input method of Safari automatically fills in the decimal point when inputting Chinese [#7918](https://github.com/vueComponent/ant-design-vue/issues/7918)
|
||||
- 🐞 Fix InputNumber component disabled style problem [#7776](https://github.com/vueComponent/ant-design-vue/issues/7776)
|
||||
- 🐞 Fix Select cannot lose focus problem [#7819](https://github.com/vueComponent/ant-design-vue/issues/7819)
|
||||
|
||||
As above Form.Item does not know whether to collect `name="a"` or `name=`b``, you can solve this kind of problem in the following two ways:
|
||||
## 4.2.5
|
||||
|
||||
The first is to use multiple `a-form-item`:
|
||||
|
||||
```html
|
||||
<a-form-item>
|
||||
<a-input name="a"></a-input>
|
||||
<a-form-item><a-input name="b"></a-input></a-form-item>
|
||||
</a-form-item>
|
||||
```
|
||||
- 🐞 Fix Empty component memory leak problem
|
||||
- 🐞 Fix Image width & height property not working problem
|
||||
|
||||
The second way is to wrap it with a custom component and call `useFormItemContext` in the custom component, It is equivalent to merging multiple form items into one.
|
||||
## 4.2.4
|
||||
|
||||
```html
|
||||
<script>
|
||||
// custom component
|
||||
import { Form } from 'ant-desing-vue';
|
||||
export default {
|
||||
name: 'custom-name',
|
||||
setup() {
|
||||
const formItemContext = Form.useFormItemContext();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
```html
|
||||
<a-form-item>
|
||||
<custom-com>
|
||||
<a-input name="a"></a-input>
|
||||
<a-input name="b"></a-input>
|
||||
</custom-com>
|
||||
</a-form-item>
|
||||
```
|
||||
- 🐞 Fix Wave memory leak problem
|
||||
|
||||
Third, the component library provides an `a-form-item-rest` component, which will prevent data collection. You can put form items that do not need to be collected and verified into this component. It is the same as the first This method is very similar, but it does not generate additional dom nodes.
|
||||
## 4.2.3
|
||||
|
||||
```html
|
||||
<a-form-item>
|
||||
<a-input name="a"></a-input>
|
||||
<a-form-item-rest><a-input name="b"></a-input></a-form-item-rest>
|
||||
</a-form-item>
|
||||
```
|
||||
- 🌟 TourStep custom Button, support function children [#7628](https://github.com/vueComponent/ant-design-vue/pull/7628)
|
||||
- 🐞 Fix the problem that the input value is hidden in Select and Cascader search multi-select mode [#7640](https://github.com/vueComponent/ant-design-vue/issues/7640)
|
||||
|
||||
## 2.2.8
|
||||
## 4.2.2
|
||||
|
||||
`2021-09-17`
|
||||
- 🐞 Fix TreeSelect placeholder slot invalid [#7545](https://github.com/vueComponent/ant-design-vue/issues/7545)
|
||||
- 🐞 Fix Tree slot responsive invalid issue [40ad45](https://github.com/vueComponent/ant-design-vue/commit/40ad45bc05b2bf9d0a2445d9f6ff365468ba90b7)
|
||||
- 🐞 Fix FloatButton target type error issue [#7576](https://github.com/vueComponent/ant-design-vue/issues/7576)
|
||||
- 🐞 Fix FormItem className error issue [#7582](https://github.com/vueComponent/ant-design-vue/issues/7582)
|
||||
- 🐞 Fix Input Cannot input problem under lazy [#7543](https://github.com/vueComponent/ant-design-vue/issues/7543)
|
||||
- 🐞 Fix the problem that placeholder is not hidden when inputting Chinese in Select [#7611](https://github.com/vueComponent/ant-design-vue/issues/7611)
|
||||
- 🐞 Fix the problem that the pop-up window flashes when clicking the preset option in DatePicker [#7550](https://github.com/vueComponent/ant-design-vue/issues/7550)
|
||||
|
||||
- 🌟 Upload method supports patch [#4637](https://github.com/vueComponent/ant-design-vue/issues/4637)
|
||||
- 🌟 List gutter supports array [d2b721](https://github.com/vueComponent/ant-design-vue/commit/d2b72143f0e15c8716b4ea8f68b2b72eff5cf510)
|
||||
- 🐞 Fix Modal type error [#4632](https://github.com/vueComponent/ant-design-vue/issues/4632)
|
||||
- 🐞 Fix the problem that AutoComplete cannot reset undefined [741718](https://github.com/vueComponent/ant-design-vue/commit/741718a0f92c790266e7a07d8d129c5673344a7e)
|
||||
- 🐞 Fix the missing style of Tag closed icon [#4649](https://github.com/vueComponent/ant-design-vue/issues/4649)
|
||||
- 🐞 Fix the problem that the TreeSelect clear button does not display under special conditions [#4655](https://github.com/vueComponent/ant-design-vue/issues/4655)
|
||||
- 🐞 Fix useForm immdiate not working issue [#4646](https://github.com/vueComponent/ant-design-vue/issues/4646)
|
||||
## 4.2.1
|
||||
|
||||
## 2.2.7
|
||||
- 🐞 fix Input clear action error [#7523](https://github.com/vueComponent/ant-design-vue/issues/7523)
|
||||
|
||||
`2021-09-08`
|
||||
## 4.2.0
|
||||
|
||||
- 🌟 Menu supports overflowedIndicator slot [#4515](https://github.com/vueComponent/ant-design-vue/issues/4515)
|
||||
- 🌟 useForm supports dynamic rule [#4498](https://github.com/vueComponent/ant-design-vue/issues/4498)
|
||||
- 🌟 Select supports Number type [#4570](https://github.com/vueComponent/ant-design-vue/issues/4570)
|
||||
- 🐞 Fix the warning problem caused by css zoom [#4554](https://github.com/vueComponent/ant-design-vue/issues/4554)
|
||||
- 🐞 Fix Mentions input Chinese error report [#4524](https://github.com/vueComponent/ant-design-vue/issues/4524)
|
||||
- 🐞 Fix the issue that AutoComplete does not support global prefixCls [#4566](https://github.com/vueComponent/ant-design-vue/issues/4566)
|
||||
- 🐞 Fix Table nested table error report [#4600](https://github.com/vueComponent/ant-design-vue/issues/4600)
|
||||
- 🐞 Fix MenuItem danger property under Dropdown has no style problem [#4618](https://github.com/vueComponent/ant-design-vue/issues/4618)
|
||||
- 🐞 Fix Modal.xxx and other methods passing appContext invalid problem [#4627](https://github.com/vueComponent/ant-design-vue/issues/4627)
|
||||
- 🐞 Fix some TS type errors
|
||||
|
||||
## 2.2.6
|
||||
|
||||
`2021-08-12`
|
||||
|
||||
- 🐞 Fix `Table` expanded list rendering problem [#4507](https://github.com/vueComponent/ant-design-vue/issues/4507)
|
||||
- 🐞 Fix `Rate` custom `character` slot not taking effect [#4509](https://github.com/vueComponent/ant-design-vue/issues/4509)
|
||||
- 🐞 Add resize-observer-polyfill to fix the problem of reporting errors in low versions of Chrome [#4508](https://github.com/vueComponent/ant-design-vue/issues/4508)
|
||||
|
||||
## 2.2.5
|
||||
|
||||
`2021-08-11`
|
||||
|
||||
- 🌟 `Select` supports customizing nodes through option slots [68c1f4](https://github.com/vueComponent/ant-design-vue/commit/68c1f4550108a3a6bbe4f1b2c5c168523fd6c84a)
|
||||
- 🐞 Fix the problem that the pop-up window component in the development environment does not display in the lower version of chrome, and avoid the pop-up window flashing [#4409](https://github.com/vueComponent/ant-design-vue/issues/4409)
|
||||
- 🐞 Fix the problem of not scrolling to the active position when `Select` is opened [ccb240](https://github.com/vueComponent/ant-design-vue/commit/ccb24016c07632f49550646c971060c402586c67)
|
||||
|
||||
## 2.2.4
|
||||
|
||||
`2021-08-10`
|
||||
|
||||
- 🌟 Support Vue@3.2 [#4490](https://github.com/vueComponent/ant-design-vue/issues/4490)
|
||||
- 🌟 Automatically hide the horizontal scroll bar of `Table` [#4484](https://github.com/vueComponent/ant-design-vue/issues/4484)
|
||||
- 🐞 Fix the issue of `Progress` trailColor not taking effect [#4483](https://github.com/vueComponent/ant-design-vue/issues/4483)
|
||||
|
||||
## 2.2.3
|
||||
|
||||
`2021-08-07`
|
||||
|
||||
- 🌟 Use `position: sticky` for the fixed column of `Table` to improve performance and solve the problem of misalignment in some scenes [38569c](https://github.com/vueComponent/ant-design-vue/commit/38569c28c7eb4eaa34f2cc096982daea901062d4)
|
||||
- 🌟 `Collapse` supports number type key [#4405](https://github.com/vueComponent/ant-design-vue/issues/4405)
|
||||
- 🌟 Optimize the flickering problem of `Tabs` when selected under windows [#4241](https://github.com/vueComponent/ant-design-vue/issues/4241)
|
||||
- 🌟 `InputPassword` supports global setting prefixCls [#4430](https://github.com/vueComponent/ant-design-vue/issues/4430)
|
||||
- 🐞 Fix `Select` cannot scroll issue [#4396](https://github.com/vueComponent/ant-design-vue/issues/4396)
|
||||
- 🐞 Fix `Badge` error reporting under ssr [#4384](https://github.com/vueComponent/ant-design-vue/issues/4384)
|
||||
- 🐞 Fix the issue of invalid data fields in `Form` [#4435](https://github.com/vueComponent/ant-design-vue/issues/4435)
|
||||
- 🐞 Fix an error when the child element of `FormItem` is a native label [#4383](https://github.com/vueComponent/ant-design-vue/issues/4383)
|
||||
- 🐞 Fix the error when `TreeSelect` customize title through slot [#4459](https://github.com/vueComponent/ant-design-vue/issues/4459)
|
||||
|
||||
## 2.2.2
|
||||
|
||||
`2021-07-11`
|
||||
|
||||
- 🌟 Switch added checkedValue and unCheckedValue attributes to customize checked binding value [#4329](https://github.com/vueComponent/ant-design-vue/issues/4329)
|
||||
- 🐞 Fix the issue of missing SubMenu animation [#4325](https://github.com/vueComponent/ant-design-vue/issues/4325)
|
||||
- 🐞 Fix that there is no red box problem when TimePicker validates the error under Form [#4331](https://github.com/vueComponent/ant-design-vue/issues/4331)
|
||||
- 🐞 Fix UploadDragger does not support vite-plugin-components on-demand loading problem [#4334](https://github.com/vueComponent/ant-design-vue/issues/4334)
|
||||
- 🐞 Fix the error when TreeSelect customize title through slot [1152e8](https://github.com/vueComponent/ant-design-vue/commit/1152e8cd71cadf9e8fb4797916adca20c0e35974)
|
||||
- 🐞 Fix the dropdown submenu style loss issue [#4351](https://github.com/vueComponent/ant-design-vue/issues/4351)
|
||||
- TS
|
||||
- Fix the type error of Table in ts 4.3.5 version [#4296](https://github.com/vueComponent/ant-design-vue/issues/4296)
|
||||
- Improve notification type [#4346](https://github.com/vueComponent/ant-design-vue/issues/4346)
|
||||
|
||||
## 2.2.1
|
||||
|
||||
`2021-07-06`
|
||||
|
||||
- 🐞 Fix the issue that the Space component does not take effect in browsers that do not support flex
|
||||
- 🐞 Fix the issue of DatePicker triggering scrolling under safari [#4323](https://github.com/vueComponent/ant-design-vue/issues/4323)
|
||||
|
||||
## 2.2.0
|
||||
|
||||
`2021-07-06`
|
||||
|
||||
- 🎉 Refactor the Button component, remove type="danger", and add the `danger` attribute [#4291](https://github.com/vueComponent/ant-design-vue/issues/4291)
|
||||
- 🐞 Fix Rate component not updating issue [#4294](https://github.com/vueComponent/ant-design-vue/issues/4294)
|
||||
- 🐞 Fix Tree replaceFields error report [#4298](https://github.com/vueComponent/ant-design-vue/issues/4298)
|
||||
- 🐞 Fix Modal missing parentContext type problem [#4305](https://github.com/vueComponent/ant-design-vue/issues/4305)
|
||||
|
||||
## 2.2.0-rc.1
|
||||
|
||||
`2021-06-29`
|
||||
|
||||
- 🌟 Change babel configuration, smaller build package size
|
||||
- 🌟 Form provides the useForm function natively, and we will deprecate the @ant-design-vue/use library
|
||||
- 🐞 Fix the issue that the Form validateFirst property does not trigger reject when there are multiple validation rules [#4273](https://github.com/vueComponent/ant-design-vue/issues/4273)
|
||||
- 🐞 Fix List circular references causing errors in Vite [#4263](https://github.com/vueComponent/ant-design-vue/issues/4263)
|
||||
- 🐞 Fix the missing item attribute problem in Menu event callback [#4290](https://github.com/vueComponent/ant-design-vue/issues/4290)
|
||||
|
||||
## 2.2.0-beta.6
|
||||
|
||||
`2021-06-26`
|
||||
|
||||
- 🌟 Menu performance optimization [e8b957](https://github.com/vueComponent/ant-design-vue/commit/e8b95784eb1ee0554b0d6b17bdc14e18775f2ae6)
|
||||
- 🐞 Fix `Layout` `RangePicker` `WeekPicker` `Textarea` on-demand loading failure
|
||||
|
||||
## 2.2.0-beta.5
|
||||
|
||||
`2021-06-24`
|
||||
|
||||
- 🎉 Support vite-plugin-components to be loaded on demand
|
||||
- 🎉 Refactor the List component
|
||||
- 🌟 Select adds responsive folding option [656d14](https://github.com/vueComponent/ant-design-vue/commit/656d14fc4e4ef0f781324438f0d58cfb6816d583)
|
||||
- 🐞 Fix the problem that the virtual list cannot be scrolled when the Select dynamic update option [b2aa49d](https://github.com/vueComponent/ant-design-vue/commit/b2aa49d064a83c6ce786a6bb4cd9fc5266a5964d)
|
||||
- 🐞 Fix the incorrect location of Select keyboard events [604372](https://github.com/vueComponent/ant-design-vue/commit/604372ff2da521dd580ad5229f7dbd445c1c6190)
|
||||
- 🐞 Fix the issue that AutoComplete does not support options slot [#4012](https://github.com/vueComponent/ant-design-vue/issues/4012)
|
||||
|
||||
## 2.2.0-beta.4
|
||||
|
||||
`2021-06-21`
|
||||
|
||||
- 🎉 Refactor Descriptions component [#4219](https://github.com/vueComponent/ant-design-vue/issues/4219)
|
||||
- 🐞 Fix the issue that Countdown does not trigger the finish event [#4222](https://github.com/vueComponent/ant-design-vue/issues/4222)
|
||||
- 🐞 Fix ConfigProvider reporting errors under vue 3.1 [#4225](https://github.com/vueComponent/ant-design-vue/issues/4225)
|
||||
- 🐞 Fix the problem of using SubMenu under Dropdown to report an error [#4205](https://github.com/vueComponent/ant-design-vue/issues/4205)
|
||||
- 🐞 Fix Col type error [#4226](https://github.com/vueComponent/ant-design-vue/issues/4226)
|
||||
- 🐞 Fix the problem that onEnd is not triggered when Typography is out of focus [#4227](https://github.com/vueComponent/ant-design-vue/issues/4227)
|
||||
- 🐞 Fix ImagePreview style loss problem [#4231](https://github.com/vueComponent/ant-design-vue/issues/4231)
|
||||
|
||||
## 2.2.0-beta.3
|
||||
|
||||
`2021-06-11`
|
||||
|
||||
- 🎉 Refactor Breadcrumb, Statistic, Tag components
|
||||
- 🌟 Statistic supports loading attribute
|
||||
- 🐞 Fix the problem of Menu rendering multiple sub-components to improve performance [6ae707](https://github.com/vueComponent/ant-design-vue/commit/6ae707edf508a9c5e8dca7dacf1410de5251bcf8)
|
||||
- 🐞 Fix FormItem custom class invalidation [617e53](https://github.com/vueComponent/ant-design-vue/commit/617e534fda2ae6d468b5e9d3eb43370f8a4b0000)
|
||||
- 🐞 Fix MenuDivider class error [#4195](https://github.com/vueComponent/ant-design-vue/issues/4195)
|
||||
- 🐞 Fix Tag and Image type errors
|
||||
- 🐞 Fix the issue of missing component animations such as Modal [#4191](https://github.com/vueComponent/ant-design-vue/issues/4191)
|
||||
- 🐞 Fix the issue that Select class cannot be dynamically updated [#4194](https://github.com/vueComponent/ant-design-vue/issues/4194)
|
||||
- 🐞 Fix the problem that the Dropdown mail expands and cannot be collapsed by clicking [#4198](https://github.com/vueComponent/ant-design-vue/issues/4198)
|
||||
- 🐞 Fix the issue of missing some export methods of FormItem [#4183](https://github.com/vueComponent/ant-design-vue/issues/4183)
|
||||
|
||||
## 2.2.0-beta.2
|
||||
|
||||
`2021-06-08`
|
||||
|
||||
- 🐞 Fix PageHeader display extension problem [4de73](https://github.com/vueComponent/ant-design-vue/commit/4de7737907d485d3dd3be44b70e599cc53edb171)
|
||||
- 🐞 Fix the problem that some components cannot be rendered normally under Vue3.1[#4173](https://github.com/vueComponent/ant-design-vue/issues/4173)
|
||||
- 🐞 Fix Menu.Divider name error problem [6c5c84](https://github.com/vueComponent/ant-design-vue/commit/6c5c84a3fc4b8abcd7aed0922852a64e0ac293c7)
|
||||
|
||||
## 2.2.0-beta.1
|
||||
|
||||
`2021-06-17`
|
||||
|
||||
- 🔥🔥🔥 Virtual Table independent library released https://www.npmjs.com/package/@surely-vue/table, this component is an independent library, the document example is not yet complete, it is a completely ts-developed component , There are good type hints, there are API documents on npm, those who are in a hurry can explore and use it, here is an online experience example, https://store.antdv.com/pro/preview/list/big-table-list
|
||||
- 🔥🔥🔥 Refactored a large number of components, the source code is more readable, the performance is better, and the ts type is more comprehensive -Refactored components in this version Anchor, Alert, Avatar, Badge, BackTop, Col, Form, Layout, Menu, Space, Spin, Switch, Row, Result, Rate
|
||||
- 🎉 Menu
|
||||
|
||||
- Better performance [#3300](https://github.com/vueComponent/ant-design-vue/issues/3300)
|
||||
- Fix the problem of incorrect highlighting [#4053](https://github.com/vueComponent/ant-design-vue/issues/4053)
|
||||
- Fix console invalid warning [#4169](https://github.com/vueComponent/ant-design-vue/issues/4169)
|
||||
- Easier to use, simpler to use single file recursion [#4133](https://github.com/vueComponent/ant-design-vue/issues/4133)
|
||||
- 💄 icon icon needs to be passed through slot
|
||||
|
||||
- Skeleton
|
||||
|
||||
- 🌟 Support Skeleton.Avatar placeholder component.
|
||||
- 🌟 Support Skeleton.Button placeholder component.
|
||||
- 🌟 Support Skeleton.Input placeholder component.
|
||||
|
||||
- 💄 Destructive update
|
||||
|
||||
- The `a-menu-item` and `a-sub-menu` icons need to be passed through the slot, and the icon is not automatically obtained through the sub-node
|
||||
- row gutter supports row-wrap, no need to use multiple rows to divide col
|
||||
- `Menu` removes `defaultOpenKeys` and `defaultSelectedKeys`; `Switch` removes `defaultChecked`; `Rate` removes `defaultValue`; Please be cautious to use the defaultXxx-named attributes of other unrefactored components, and they will be removed in future versions.
|
||||
|
||||
- 🌟 Added Avatar.Group component
|
||||
- 🐞 Fix AutoComplete filterOptions not taking effect [#4170](https://github.com/vueComponent/ant-design-vue/issues/4170)
|
||||
- 🐞 Fix Select automatic width invalidation problem [#4118](https://github.com/vueComponent/ant-design-vue/issues/4118)
|
||||
- 🐞 Fix the lack of internationalized files in dist [#3684](https://github.com/vueComponent/ant-design-vue/issues/3684)
|
||||
|
||||
## 2.1.6
|
||||
|
||||
`2021-05-13`
|
||||
|
||||
- 🐞 Use vue@3.0.10 to rebuild to avoid console warning [#3998](https://github.com/vueComponent/ant-design-vue/issues/3998)
|
||||
|
||||
## 2.1.5
|
||||
|
||||
`2021-05-12`
|
||||
|
||||
- 🐞 Fix SSR time reporting error [#3983](https://github.com/vueComponent/ant-design-vue/issues/3983)
|
||||
|
||||
## 2.1.4
|
||||
|
||||
`2021-05-09`
|
||||
|
||||
- 🐞 Fix `Table` scrolling misalignment issue [#4045](https://github.com/vueComponent/ant-design-vue/issues/4045)
|
||||
- 🐞 Fix `Typography` editable mode triggering link jump issue [#4105](https://github.com/vueComponent/ant-design-vue/issues/4105)
|
||||
- 🐞 Fix the issue that `Carousel` variableWidth does not take effect [#3977](https://github.com/vueComponent/ant-design-vue/issues/3977)
|
||||
- 🐞 Fix the problem that `TreeSelect` cannot delete parent and child nodes at the same time through the keyboard [#3508](https://github.com/vueComponent/ant-design-vue/issues/3508)
|
||||
- 🐞 Fix some types of errors
|
||||
|
||||
## 2.1.3
|
||||
|
||||
`2021-04-25`
|
||||
|
||||
- 🎉🎉🎉 remove ads during npm installation
|
||||
- 🐞 `Select`
|
||||
- Fix the first issue of default activation [#3842](https://github.com/vueComponent/ant-design-vue/issues/3842)
|
||||
- Fix group display abnormal problem [#3841](https://github.com/vueComponent/ant-design-vue/issues/3841)
|
||||
- Fix scrolling abnormal issue after dynamically updating selections [#3972](https://github.com/vueComponent/ant-design-vue/issues/3972)
|
||||
- 🐞 Fix the issue that `Checkbox` triggers twice `update:checked` [#3838](https://github.com/vueComponent/ant-design-vue/issues/3838)
|
||||
- 🌟 `Table` column group supports fixed [#3882](https://github.com/vueComponent/ant-design-vue/issues/3882)
|
||||
- 🌟 `Table` column supports v-for [#3934](https://github.com/vueComponent/ant-design-vue/issues/3934)
|
||||
- 🐞 Fix the problem that `Table` displays horizontal scroll bar on windows [6d33d6](https://github.com/vueComponent/ant-design-vue/commit/6d33d60d2bca98825f274e48bcc3badd1857f742)
|
||||
- 🌟 `Form` scrollToFirstError supports option parameter passing [#3918](https://github.com/vueComponent/ant-design-vue/issues/3918)
|
||||
- 🐞 Fix the issue of `Calendar` month selector displaying wrong characters [#3915](https://github.com/vueComponent/ant-design-vue/issues/3915)
|
||||
- 🌟 Refactor the `Switch` component and remove the defaultChecked attribute [#3885](https://github.com/vueComponent/ant-design-vue/issues/3885)
|
||||
- 🐞 Fix the process exception when using Vite [#3930](https://github.com/vueComponent/ant-design-vue/issues/3930)
|
||||
- 🐞 Fix `Radio` shadow occlusion problem [#3955](https://github.com/vueComponent/ant-design-vue/issues/3955)
|
||||
- 🐞 Fix the issue that span does not take effect in `Form` inline mode [#3862](https://github.com/vueComponent/ant-design-vue/issues/3862)
|
||||
- 🐞 Fix the issue that `Cascader` keydown selection does not take effect [#958](https://github.com/vueComponent/ant-design-vue/issues/958)
|
||||
- 🐞 Fix `Image` preview function failure problem [#3701](https://github.com/vueComponent/ant-design-vue/issues/3701)
|
||||
- 🐞 Fix some TS type issues
|
||||
|
||||
## 2.1.2
|
||||
|
||||
`2021-03-28`
|
||||
|
||||
- 🌟 Recompile with Vue 3.0.9, compatible with 3.0.7 and below
|
||||
|
||||
## 2.1.1
|
||||
|
||||
`2021-03-27`
|
||||
|
||||
- 🌟 Compatible with Vue 3.0.8, note: Due to the destructive update of 3.0.8, 2.1.1 is not compatible with versions below 3.0.7 [vue#3493](https://github.com/vuejs/vue-next/issues /3493)
|
||||
- 🐞 Fix Modal.confirm missing closable ts type [#3684](https://github.com/vueComponent/ant-design-vue/issues/3845)
|
||||
- 🐞 Fix upload custom method not working issue [#3843](https://github.com/vueComponent/ant-design-vue/issues/3843)
|
||||
|
||||
## 2.1.0
|
||||
|
||||
`2021-03-20`
|
||||
|
||||
- 🎉🎉🎉 Added `Typography` component [#3807](https://github.com/vueComponent/ant-design-vue/issues/3807)
|
||||
- 🌟 Modal method adds close icon customization [#3753](https://github.com/vueComponent/ant-design-vue/issues/3753)
|
||||
- 🐞 Fix missing build files containing internationalization [#3684](https://github.com/vueComponent/ant-design-vue/issues/3684)
|
||||
- 🐞 Fix Drawer error after destruction [#848d64](https://github.com/vueComponent/ant-design-vue/commit/848d6497e68c87566790dfa889a1913199a6699a)
|
||||
- 🐞 Fix BackTop incorrect position when KeepAlive is activated [#3803](https://github.com/vueComponent/ant-design-vue/issues/3803)
|
||||
- 🐞 Fix the problem that the TreeNode class does not take effect [#3822](https://github.com/vueComponent/ant-design-vue/issues/3822)
|
||||
- 🐞 Fix Table tags being an array error issue [#3812](https://github.com/vueComponent/ant-design-vue/issues/3812)
|
||||
- 🐞 Fix the sorting issue when Table custom filterIcon is triggered [#3819](https://github.com/vueComponent/ant-design-vue/issues/3819)
|
||||
- 🐞 Fix Select style misalignment under Form [#3781](https://github.com/vueComponent/ant-design-vue/issues/3781)
|
||||
|
||||
## 2.0.1
|
||||
|
||||
`2021-02-27`
|
||||
|
||||
- 🌟 `Badge` adds `Ribbon` [#3681](https://github.com/vueComponent/ant-design-vue/issues/3681)
|
||||
- 🌟 Adjust the trigger order of `SearchInput` search event [#3725](https://github.com/vueComponent/ant-design-vue/issues/3725)
|
||||
- 🐞 Fix the stuck problem when `Table` is destroyed [#3531](https://github.com/vueComponent/ant-design-vue/issues/3531)
|
||||
- 🐞 Fix the issue of less file introduced in `Menu` css [#3678](https://github.com/vueComponent/ant-design-vue/issues/3678)
|
||||
- 🐞 Fix the problem of `Alert` custom icon misalignment [#3712](https://github.com/vueComponent/ant-design-vue/issues/3712)
|
||||
|
||||
## 2.0.0
|
||||
|
||||
`2021-02-06`
|
||||
|
||||
- 🎉🎉🎉 2.0 official version released
|
||||
- 🎉🎉🎉 support dark theme [#3410](https://github.com/vueComponent/ant-design-vue/issues/3410)
|
||||
- 🎉🎉🎉 The new version of the document is online, use the Composition API to completely reconstruct the document example, and provide the TS and JS dual version source code
|
||||
- 🌟 Refactor the `Alert` component using Composition API [#3654](https://github.com/vueComponent/ant-design-vue/pull/3654)
|
||||
- 🌟 `Tooltip` supports custom colors [#3603](https://github.com/vueComponent/ant-design-vue/issues/3603)
|
||||
- 🐞 Fix the problem that `TimePicker` does not automatically scroll to the selected position [#ab7537](https://github.com/vueComponent/ant-design-vue/commit/ab75379f0c2f5e54ab7c348284a7391939ab5aaf)
|
||||
|
||||
## 2.0.0-rc.9
|
||||
|
||||
`2021-01-24`
|
||||
|
||||
- 🌟 `@ant-design/icons-vue` upgrade to 6.0, use es module by default
|
||||
- 🌟 `Tabs` adds `centered` centered mode [#3501](https://github.com/vueComponent/ant-design-vue/issues/3501)
|
||||
- 🐞 `Progress` Add opacity animation [#3505](https://github.com/vueComponent/ant-design-vue/issues/3505)
|
||||
- 🐞 Fix an error when installing npm [#3515](https://github.com/vueComponent/ant-design-vue/issues/3515)
|
||||
- 🐞 Fix the problem of `Breadcrumn` split line not displaying [#3522](https://github.com/vueComponent/ant-design-vue/issues/3522)
|
||||
- 🐞 Fix `Radio` uncontrolled issue [#3517](https://github.com/vueComponent/ant-design-vue/issues/3517)
|
||||
- 🐞 Fix `FormItem` not wrapping issue [#3538](https://github.com/vueComponent/ant-design-vue/issues/3538)
|
||||
- 🐞 Fix `Carousel` `pauseOnDotsHover` not working problem [#3519](https://github.com/vueComponent/ant-design-vue/issues/3519)
|
||||
- 🐞 Fix `Input.Search` `class` not working issue [#3541](https://github.com/vueComponent/ant-design-vue/issues/3541)
|
||||
- 🐞 Fix the issue that `InputNumber` triggers the change event multiple times under Microsoft input method [#3550](https://github.com/vueComponent/ant-design-vue/issues/3550)
|
||||
- 🐞 Fix the problem that the keyboard can still be switched in the disabled state of `Tabs` [#3575](https://github.com/vueComponent/ant-design-vue/issues/3575)
|
||||
- 🐞 Fix the issue that `Switch` does not take effect in the table [#3512](https://github.com/vueComponent/ant-design-vue/issues/3512)
|
||||
|
||||
## 2.0.0-rc.8
|
||||
|
||||
`2021-01-07`
|
||||
|
||||
- 🌟 Support Vite 2 [#3490](https://github.com/vueComponent/ant-design-vue/issues/3490)
|
||||
- 🌟 Use Composition API to refactor Affix component [#3447](https://github.com/vueComponent/ant-design-vue/issues/3447)
|
||||
- 🐞 Fix Image component type definition error [#3488](https://github.com/vueComponent/ant-design-vue/issues/3488)
|
||||
- 🐞 Upgrade icons-vue Fix IconFont component type error [#3474](https://github.com/vueComponent/ant-design-vue/issues/3474)
|
||||
- 🐞 Fix Tooltip arrow style error in less 4 [#3477](https://github.com/vueComponent/ant-design-vue/issues/3477)
|
||||
- 🐞 Fix DatePicker type definition parsing error under Vue 3.0.5 [#bf7c62](https://github.com/vueComponent/ant-design-vue/commit/bf7c62f457fc14624881f69c5baf9a62219383f7)
|
||||
|
||||
## 2.0.0-rc.7
|
||||
|
||||
`2020-12-28`
|
||||
|
||||
- 🐞 Fix Switch `change`、`click` not work [#3453](https://github.com/vueComponent/ant-design-vue/issues/3453)
|
||||
|
||||
## 2.0.0-rc.6
|
||||
|
||||
`2020-12-27`
|
||||
|
||||
- 🌟 Support Less 4 [#3449](https://github.com/vueComponent/ant-design-vue/issues/3449)
|
||||
- 🌟 Added Image component [#3235](https://github.com/vueComponent/ant-design-vue/issues/3235)
|
||||
- 🌟 Functional component, add displayName attribute [#3445](https://github.com/vueComponent/ant-design-vue/issues/3445)
|
||||
- 🐞 Message adds custom class style function [#3443](https://github.com/vueComponent/ant-design-vue/issues/3443)
|
||||
- 🐞 Fix the initial disabled state of the Tabs component does not take effect [#3366](https://github.com/vueComponent/ant-design-vue/issues/3366)
|
||||
- 🐞 Fix Slider accuracy issue [#3346](https://github.com/vueComponent/ant-design-vue/issues/3346)
|
||||
- 🐞 Fix the incorrect scroll height of Select [#3419](https://github.com/vueComponent/ant-design-vue/issues/3419)
|
||||
- 🐞 Fix the problem that Input small is too small and the height is 2px [#3396](https://github.com/vueComponent/ant-design-vue/issues/3396)
|
||||
- 🐞 Fix the problem that TreeSelect triggers two change events
|
||||
- 🐞 Fix the endless loop problem of TreeSelect defining title through slot
|
||||
- 🐞 Fix the problem that Drawer handle slot triggers two click events
|
||||
- 🌟 Added Checkbox and Switch event declaration
|
||||
|
||||
## 2.0.0-rc.5
|
||||
|
||||
`2020-12-13`
|
||||
|
||||
- 🐞 Fix the undefined warning problem of this.dom output in the Drawer component console
|
||||
- 🐞 Fix Menu in Vue 3.0.3 and above versions, display confusion problem [#3354](https://github.com/vueComponent/ant-design-vue/issues/3354)
|
||||
|
||||
## 2.0.0-rc.4
|
||||
|
||||
`2020-12-10`
|
||||
|
||||
- 🌟 Input.Password supports custom icons [#3320](https://github.com/vueComponent/ant-design-vue/issues/3320)
|
||||
- 🐞 Fix the issue that the Select Option click event does not trigger [#4ea00d](https://github.com/vueComponent/ant-design-vue/commit/4ea00d3a70d0afd7bea07f814df03ab7d0b25ebd)
|
||||
- 🐞 Fix the problem that the dark theme does not work after the Menu exceeds the width [#10f35a](https://github.com/vueComponent/ant-design-vue/commit/10f35a1fa510de91e9484b07fcfff253920cee29)
|
||||
- 🐞 Fix Menu console vue key some waring [#520d6a](https://github.com/vueComponent/ant-design-vue/commit/520d6a5e85eb391e5294211c9d7b2ea598c59119)
|
||||
- 🐞 Remove console passive prompt log [#8d1669](https://github.com/vueComponent/ant-design-vue/commit/8d1669b8896d84a67c61d3a00d0b13c42d70f30f)
|
||||
|
||||
## 2.0.0-rc.3
|
||||
|
||||
`2020-12-05`
|
||||
|
||||
- 🐞 Fix the problem of functional components reporting type errors in Vue 3.0.3 [#f5cf7e](https://github.com/vueComponent/ant-design-vue/commit/f5cf7e0920a51f0ac024046996c99260aa41becf)
|
||||
- 🐞 Fix Menu display error after detecting width [#3262](https://github.com/vueComponent/ant-design-vue/issues/3262)
|
||||
- 🐞 Fix Menu subMenuOpenDelay subMenuCloseDelay not working problem [#3291](https://github.com/vueComponent/ant-design-vue/pull/3291)
|
||||
- 🐞 Fix TreeSelect stack overflow problem [#28aeea](https://github.com/vueComponent/ant-design-vue/commit/28aeea6f0b142ed68950a3738f7cf2c1581a7a5b)
|
||||
- 🐞 Fix Input custom style class being overwritten [#3273](https://github.com/vueComponent/ant-design-vue/issues/3273)
|
||||
- 🐞 Fix InputNumber parse error in production environment [#3249](https://github.com/vueComponent/ant-design-vue/issues/3249)
|
||||
|
||||
## 2.0.0-rc.2
|
||||
|
||||
`2020-11-24`
|
||||
|
||||
- 🌟 Optimize Menu performance, enable lazy loading by default [#3243](https://github.com/vueComponent/ant-design-vue/pull/3243)
|
||||
- 🌟 Tag supports defining icon via slot [#3185](https://github.com/vueComponent/ant-design-vue/pull/3185)
|
||||
- 🌟 Small type table changed to borderless [#3221](https://github.com/vueComponent/ant-design-vue/issues/3221)
|
||||
- 🌟 @ant-design/icons-vue upgraded to 5.1.6, support SSR, support spin attribute shorthand
|
||||
- 🐞 Fix the style problem of Alert's close button in Safari [#3184](https://github.com/vueComponent/ant-design-vue/issues/3184)
|
||||
- 🐞 Fix the problem of Notification top attribute type error [#3187](https://github.com/vueComponent/ant-design-vue/issues/3187)
|
||||
- 🐞 Fix DirectoryTree custom icon does not take effect [#3183](https://github.com/vueComponent/ant-design-vue/issues/3183)
|
||||
- 🐞 Fix Button loading delay not taking effect [#3194](https://github.com/vueComponent/ant-design-vue/issues/3194)
|
||||
- 💄 Select optionFilterProp no longer supports filtering by children [#3204](https://github.com/vueComponent/ant-design-vue/issues/3204)
|
||||
- 🐞 Fix Select labelInValue error when reporting [#3216](https://github.com/vueComponent/ant-design-vue/issues/3216)
|
||||
- 🐞 Fix ConfigProvider transformCellText missing issue [#3206](https://github.com/vueComponent/ant-design-vue/issues/3206)
|
||||
- 🐞 Fix the style disorder problem when Dropdown Button is mixed together [#3244](https://github.com/vueComponent/ant-design-vue/issues/3244)
|
||||
- 🐞 Fix RangePicker custom width invalidation issue [#3244](https://github.com/vueComponent/ant-design-vue/issues/3245)
|
||||
- 🐞 Fix multiple errors or missing Ts types
|
||||
|
||||
## 2.0.0-rc.1
|
||||
|
||||
`2020-11-14`
|
||||
|
||||
- 🎉🎉🎉
|
||||
- 🌟 Menu cancel the default lazy loading, improve the first animation effect, optimize the Bezier curve function, and make it smoother [#3177](https://github.com/vueComponent/ant-design-vue/pull/3177)
|
||||
- 🐞 Fix Select search function failure problem [#3144](https://github.com/vueComponent/ant-design-vue/issues/3144)
|
||||
- 🐞 Fix the Drawer component does not have automatic focus, which can not be closed directly by the ESC button [#3148](https://github.com/vueComponent/ant-design-vue/issues/3148)
|
||||
- 🐞 Fix the incorrect position of popover elements in Popover [#3147](https://github.com/vueComponent/ant-design-vue/issues/3147)
|
||||
- 🐞 Fix CountDown not updating problem [#3170](https://github.com/vueComponent/ant-design-vue/pull/3170)
|
||||
- 🐞 Fix multiple errors or missing Ts types
|
||||
|
||||
## 2.0.0-beta.15
|
||||
|
||||
`2020-11-08`
|
||||
|
||||
- 🌟 Optimize the Menu animation to make it smoother [#3095](https://github.com/vueComponent/ant-design-vue/issues/3095)
|
||||
- 🌟 Optimize VirtualList to avoid invalid render [#2e61e9](https://github.com/vueComponent/ant-design-vue/commit/2e61e9cb502f2bb6910f59abfb483fd2517e594f)
|
||||
- 🐞 Fix Menu overflowedIndicator not taking effect [#689113](https://github.com/vueComponent/ant-design-vue/commit/689113b3c9c19e929607567a4c8252c6511bff5c)
|
||||
- 🐞 Select
|
||||
- Fix the issue that dropdownRender does not support slot [#3098](https://github.com/vueComponent/ant-design-vue/issues/3098)
|
||||
- Fix the issue of abnormal empty values in tag mode [#3100](https://github.com/vueComponent/ant-design-vue/issues/3100)
|
||||
- Fix the problem that the selected item is not updated in single selection mode [#3099](https://github.com/vueComponent/ant-design-vue/issues/3099)
|
||||
- Fix foucs status not taking effect in special scenarios [#3099](https://github.com/vueComponent/ant-design-vue/issues/3099)
|
||||
- 🐞 Fix DatePicker default formatting invalid problem [#3091](https://github.com/vueComponent/ant-design-vue/issues/3091)
|
||||
- 🐞 Fix Table customRow configuration event not taking effect [#3121](https://github.com/vueComponent/ant-design-vue/issues/3121)
|
||||
- 🐞 Fix the style of TreeSelect search box [ee4cd3c](https://github.com/vueComponent/ant-design-vue/commit/ ee4cd3c35a84658cbbb148ce368bc247a927d528)
|
||||
- 🐞 Fix Ts type error or missing problem
|
||||
|
||||
## 2.0.0-beta.13
|
||||
|
||||
`2020-11-02`
|
||||
|
||||
- 🐞 Fix npm install error report [#3080](https://github.com/vueComponent/ant-design-vue/issues/3080)
|
||||
- 🐞 Fix Select maxPlaceHolder display error problem [#3085](https://github.com/vueComponent/ant-design-vue/issues/3085)
|
||||
- 🐞 Fix the pop-up component, the pop-up position is not updated [#3085](https://github.com/vueComponent/ant-design-vue/issues/3085)
|
||||
- 🐞 Fix the warning problem when Table data is empty [#3082](https://github.com/vueComponent/ant-design-vue/issues/3082)
|
||||
- 🐞 Fix Input display multiple borders in Form [#3084](https://github.com/vueComponent/ant-design-vue/issues/3084)
|
||||
|
||||
## 2.0.0-beta.12
|
||||
|
||||
`2020-11-01`
|
||||
|
||||
- 🐞 Fix dist/antd.css missing component style issue [#3069](https://github.com/vueComponent/ant-design-vue/issues/3069)
|
||||
- 🐞 Fix Input style issue [#3074](https://github.com/vueComponent/ant-design-vue/issues/3074)
|
||||
- 🐞 Fix Form layout="vertical" style issue [#3075](https://github.com/vueComponent/ant-design-vue/issues/3075)
|
||||
- 🐞 Fix Select cannot open popup problem [#3070](https://github.com/vueComponent/ant-design-vue/issues/3070)
|
||||
|
||||
## 2.0.0-beta.11
|
||||
|
||||
`2020-10-30`
|
||||
|
||||
- 🎉🎉🎉 Refactored Select and AutoComplete components, supports virtual lists, and greatly improves performance
|
||||
- 🔥🔥🔥 Use Typescript to refactor all components, type support is more friendly
|
||||
- 🔥 Optimize the underlying animation components, with better performance and smoother
|
||||
- 🌟 Textarea component added showCount to support word count function
|
||||
- 🌟 Recursive Menu component, supports arbitrary nesting of other elements [#1452](https://github.com/vueComponent/ant-design-vue/issues/1452)
|
||||
- 🇮🇪 Add Irish language internationalization support
|
||||
- 🐞 Fix webpack 5 compatibility issues.
|
||||
- 🐞 Fix the problem that the Upload method attribute does not take effect [#2837](https://github.com/vueComponent/ant-design-vue/issues/2837)
|
||||
- 🐞 Fix Table component filter not supporting number type problem [#3052](https://github.com/vueComponent/ant-design-vue/issues/3052)
|
||||
- 🐞 Fix Table fixed column ellipsis not working issue [#2916](https://github.com/vueComponent/ant-design-vue/issues/2916)
|
||||
- 🐞 Fix Table custom expandIcon not taking effect [#3013](https://github.com/vueComponent/ant-design-vue/issues/3013)
|
||||
- 🐞 Fix the problem that TreeSelect cannot customize slot [#2827](https://github.com/vueComponent/ant-design-vue/issues/2827)
|
||||
- 🛎 Change Avatar's srcSet to srcset
|
||||
|
||||
## 2.0.0-beta.10
|
||||
|
||||
`2020-09-24`
|
||||
|
||||
- 🌟 Update Vue dependency to release version
|
||||
- 🐞 Fix the problem that Menu does not collapse in Layout [#2819](https://github.com/vueComponent/ant-design-vue/issues/2819)
|
||||
- 🐞 Fix a warning issue when switching Tabs [#2865](https://github.com/vueComponent/ant-design-vue/issues/2865)
|
||||
- 🐞 Fix the problem that the input box does not trigger the change event when compositionend
|
||||
- 🐞 Fix the problem that the Upload button does not disappear [#2884](https://github.com/vueComponent/ant-design-vue/issues/2884)
|
||||
- 🐞 Fix upload custom method not working issue [#2837](https://github.com/vueComponent/ant-design-vue/issues/2837)
|
||||
- 🐞 Fix some ts type errors
|
||||
|
||||
## 2.0.0-beta.8
|
||||
|
||||
- 🐞 Fix ts types error
|
||||
|
||||
## 2.0.0-beta.7
|
||||
|
||||
- 🐞 Fix the problem that Descriptions Item does not support v-for [#2793](https://github.com/vueComponent/ant-design-vue/issues/2793)
|
||||
- 🐞 Fix Modal button loading effect not working problem [9257c1](https://github.com/vueComponent/ant-design-vue/commit/9257c1ea685db4339239589153aee3189d0434fe)
|
||||
- 🐞 Fix the problem that the Steps component cannot be clicked when using v-model [ec7309](https://github.com/vueComponent/ant-design-vue/commit/ec73097d9b6ea8e2f2942ac28853c19191ca3298)
|
||||
- 🌟 Checkbox, Radio add event declaration
|
||||
- 🐞 Fix ts type error [802446](https://github.com/vueComponent/ant-design-vue/commit/8024469b8832cfc4fe85498b639bfb48820531aa)
|
||||
|
||||
## 2.0.0-beta.6
|
||||
|
||||
- 🐞 Fix the problem that TreeSelectNode subcomponent TreeSelectNode is not registered
|
||||
|
||||
## 2.0.0-beta.5
|
||||
|
||||
- 🔥 Support Vite.
|
||||
|
||||
## 2.0.0-beta.4
|
||||
|
||||
- 🌟 Remove polyfills that are no longer used
|
||||
- 🐞 Fix the problem of calling `Modal` afterClose twice
|
||||
- 🐞 Supplement the declaration that ts type files lack native attributes
|
||||
|
||||
## 2.0.0-beta.3
|
||||
|
||||
- 🔥 Support Typescript.
|
||||
- 🔥 Added `Space` component.
|
||||
- 🐞 Fix the problem that some components cannot use css scope [4bdb24](https://github.com/vueComponent/ant-design-vue/commit/4bdb241aa674b50fafa29b3b98e291643f2a06cc).
|
||||
- 🐞 Fix `List.Meta` registration failure problem [03a42a](https://github.com/vueComponent/ant-design-vue/commit/03a42a5b35e7d42a39aedb1aba8346995be2c27e)
|
||||
- 🐞 Fix the problem of misalignment in the fixed column of Table [#1493](https://github.com/vueComponent/ant-design-vue/issues/1493)
|
||||
- 🐞 Fix the problem that the `Button` is not vertically centered [bd71e3](https://github.com/vueComponent/ant-design-vue/commit/bd71e3806b73881f9a95028982d17a10b2cd0b5c)
|
||||
- 🐞 Fix `Tabs` multiple departure `change` event issue [8ed937](https://github.com/vueComponent/ant-design-vue/commit/8ed937344a57142a575e5272f50933c9c4459a43)
|
||||
|
||||
## 2.0.0-beta.2
|
||||
- 🌟 Optimize the textColor change when the layout component switches to dark mode [#7498](https://github.com/vueComponent/ant-design-vue/issues/7498)
|
||||
- 🌟 Tooltip added arrow hidden configuration [#7459](https://github.com/vueComponent/ant-design-vue/issues/7459)
|
||||
- 🌟 Optimize Table hover performance [#7451](https://github.com/vueComponent/ant-design-vue/issues/7451)
|
||||
- 🐞 Fixed the problem of changing the model during useForm verification, resulting in verification errors [#ffd4d8](https://github.com/vueComponent/ant-design-vue/commit/ffd4d8fe927f9ea40cbb6358ad997c447bd9a74e)
|
||||
- 🐞 Fix Tabs folding calculation error issue [#7491](https://github.com/vueComponent/ant-design-vue/issues/7491)
|
||||
- 🐞 Fix Qrcode missing type hint issue [#7502](https://github.com/vueComponent/ant-design-vue/issues/7502)
|
||||
- 🐞 Fix Menu rendering error under SSR [#7349](https://github.com/vueComponent/ant-design-vue/issues/7349)
|
||||
- 🐞 Fix Select and Cascader rendering errors under SSR [#7377](https://github.com/vueComponent/ant-design-vue/issues/7377)
|
||||
- 🐞 Fix AutoComplete missing option slot declaration issue [#7396](https://github.com/vueComponent/ant-design-vue/issues/7396)
|
||||
- 🐞 Fix Textarea autoSize not taking effect [#7478](https://github.com/vueComponent/ant-design-vue/issues/7478)
|
||||
- 🐞 Fix Pagination’s Enter key triggering two page turns [#7368](https://github.com/vueComponent/ant-design-vue/issues/7368)
|
||||
- 🐞 Fix the problem of Chinese input in the input box [#7391](https://github.com/vueComponent/ant-design-vue/issues/7391)[#7516](https://github.com/vueComponent/ant- design-vue/issues/7516)
|
||||
- 🐞 Fix Carousel beforeChange current parameter error issue [#7419](https://github.com/vueComponent/ant-design-vue/issues/7419)
|
||||
|
||||
## 4.1.2
|
||||
|
||||
- 🐞 Fix table resize error reporting under vue 3.4 [#7291](https://github.com/vueComponent/ant-design-vue/issues/7291)
|
||||
- 🐞 Fix the problem that the Segmented title attribute is not displayed [#7302](https://github.com/vueComponent/ant-design-vue/issues/7302)
|
||||
|
||||
## 4.1.1
|
||||
|
||||
- 🌟 QRcode adds scanned status [#7242](https://github.com/vueComponent/ant-design-vue/issues/7242)
|
||||
- 🐞 Fix css prefix issue in nuxt [#7256](https://github.com/vueComponent/ant-design-vue/issues/7256)
|
||||
- 🐞 Fix dropdown closing issue [#7246](https://github.com/vueComponent/ant-design-vue/issues/7246)
|
||||
- 🐞 Fix divider vertical dashed not display issue [#7218](https://github.com/vueComponent/ant-design-vue/issues/7218)
|
||||
- 🐞 Fix hook mode message console warning issue [#7281](https://github.com/vueComponent/ant-design-vue/issues/7281)
|
||||
- 🐞 Fix table expansion error reporting under vue 3.4 [#7265](https://github.com/vueComponent/ant-design-vue/issues/7265)
|
||||
- 🐞 Fix table group filter status error issue [#7233](https://github.com/vueComponent/ant-design-vue/issues/7233)
|
||||
|
||||
## 4.1.0
|
||||
|
||||
- 🐞 support vue 3.4 [#7239](https://github.com/vueComponent/ant-design-vue/issues/7239)
|
||||
|
||||
## 4.0.8
|
||||
|
||||
- 🐞 Fix theme responsiveness failure issue under Nuxt [#7180](https://github.com/vueComponent/ant-design-vue/issues/7180)
|
||||
- 🐞 Fix error reporting caused by Wave [#7108](https://github.com/vueComponent/ant-design-vue/issues/7108)
|
||||
- 🐞 Fix Upload disabled inheritance issue [#7110](https://github.com/vueComponent/ant-design-vue/issues/7110)
|
||||
- 🐞 Fix Tooltip popupAlign not taking effect [#7112](https://github.com/vueComponent/ant-design-vue/issues/7112)
|
||||
- 🐞 Fix Typography flashing problem [#7146](https://github.com/vueComponent/ant-design-vue/issues/7146)
|
||||
- 🐞 Fix the issue that RangePicker prevIcon nextIcon does not take effect [#7127](https://github.com/vueComponent/ant-design-vue/issues/7127)
|
||||
- 🐞 Fixed the issue of watermark not monitoring child element changes [#7149](https://github.com/vueComponent/ant-design-vue/issues/7149)
|
||||
- 🐞 Fix Menu animation missing issue [#7130](https://github.com/vueComponent/ant-design-vue/issues/7130)
|
||||
- 🐞 Fix the cursor change issue when TextArea autosize [#7121](https://github.com/vueComponent/ant-design-vue/issues/7121)
|
||||
|
||||
## 4.0.7
|
||||
|
||||
- 🌟 Added Flex component [#7052](https://github.com/vueComponent/ant-design-vue/issues/7052)
|
||||
- 🌟 ConfigProvider adds wave configuration [#7036](https://github.com/vueComponent/ant-design-vue/issues/7036)
|
||||
- 🌟 Watermark supports dark mode [#7067](https://github.com/vueComponent/ant-design-vue/issues/7067)
|
||||
- 🐞 Fix Space duplicate Key problem [#7048](https://github.com/vueComponent/ant-design-vue/issues/7048)
|
||||
- 🐞 Fix Upload disabled priority error issue [#7047](https://github.com/vueComponent/ant-design-vue/issues/7047)
|
||||
- 🐞 Fix Carousel rendering error in jsx [#7077](https://github.com/vueComponent/ant-design-vue/issues/7077)
|
||||
- 🐞 Fix Message offset position problem [#7093](https://github.com/vueComponent/ant-design-vue/issues/7093)
|
||||
- 🐞 Fix the problem of animation failure when using Collapse custom prefix [#7074](https://github.com/vueComponent/ant-design-vue/issues/7074)
|
||||
|
||||
## 4.0.6
|
||||
|
||||
- 🐞 Fix the Dropdown onVisibleChange failure issue introduced in 4.0.4 [#7031](https://github.com/vueComponent/ant-design-vue/issues/7031)
|
||||
|
||||
## 4.0.5
|
||||
|
||||
- 🐞 Fix cssinjs performance issue [#7023](https://github.com/vueComponent/ant-design-vue/issues/7023)
|
||||
|
||||
## 4.0.4
|
||||
|
||||
- 🌟 Added esm target file
|
||||
- 🌟 Added tooltip attribute to FormItem [#7014](https://github.com/vueComponent/ant-design-vue/issues/7014)
|
||||
- 🐞 Fix useMessage getContainer not taking effect [#6942](https://github.com/vueComponent/ant-design-vue/issues/6942)
|
||||
- 🐞 Fix the problem of Image triggering onPreviewVisibleChange event multiple times [#6945](https://github.com/vueComponent/ant-design-vue/issues/6945)
|
||||
- 🐞 Fix the problem that Checkbox global disabled does not take effect [#6970](https://github.com/vueComponent/ant-design-vue/issues/6970)
|
||||
- 🐞 Fix Drawer contentWrapperStyle not taking effect [#6983](https://github.com/vueComponent/ant-design-vue/issues/6983)
|
||||
- 🐞 Optimize Select Dropdown and other drop-down list scroll bar display hidden logic [#6987](https://github.com/vueComponent/ant-design-vue/issues/6987)
|
||||
- 🐞 Fix the problem of hiding when there are components such as input in the drop-down list such as Select Dropdown [#7020](https://github.com/vueComponent/ant-design-vue/issues/7020)
|
||||
|
||||
## 4.0.3
|
||||
|
||||
- 🐞 Fix the problem of style loss under shadow Dom [#6912](https://github.com/vueComponent/ant-design-vue/issues/6912)
|
||||
- 🐞 Upgrade Icon dependency and fix icon css missing problem under shadow Dom [#6914](https://github.com/vueComponent/ant-design-vue/issues/6914)
|
||||
|
||||
## 4.0.2
|
||||
|
||||
- 🐞 Fix useMessage causing body to be removed [#6880](https://github.com/vueComponent/ant-design-vue/issues/6880)
|
||||
- 🐞 Fix the problem that the water ripple effect does not disappear after Button loading is switched [#6895](https://github.com/vueComponent/ant-design-vue/issues/6895)
|
||||
- 🐞 Fixed the problem that flip does not reset after Image is closed [#6913](https://github.com/vueComponent/ant-design-vue/issues/6913)
|
||||
- 🐞 Fix ImageGroup animation effect loss problem [#6898](https://github.com/vueComponent/ant-design-vue/issues/6898)
|
||||
- 🐞 Fix Modal missing onUpdate:open attribute declaration [#6876](https://github.com/vueComponent/ant-design-vue/issues/6876)
|
||||
- 🐞 Fixed the issue of multiple clicks being triggered at the edge of Transfer's Checkbox [#6902](https://github.com/vueComponent/ant-design-vue/issues/6902)
|
||||
|
||||
## 4.0.1
|
||||
|
||||
- 🌟 FloatButton add Badge support [#6738](https://github.com/vueComponent/ant-design-vue/issues/6738)
|
||||
- 🌟 Image preview zoom in and out sensitivity adjustment [#6784](https://github.com/vueComponent/ant-design-vue/issues/6784)
|
||||
- 🌟 Add flip feature to Image [#6785](https://github.com/vueComponent/ant-design-vue/issues/6785)
|
||||
- 🌟 Add App component to provide context [#6735](https://github.com/vueComponent/ant-design-vue/issues/6735)
|
||||
- 🌟 Style extraction feature for SSR [#6757](https://github.com/vueComponent/ant-design-vue/issues/6757)
|
||||
- 🌟 Support px2rem [#6817](https://github.com/vueComponent/ant-design-vue/issues/6817)
|
||||
- 🌟 Tag supports borderless mode [#6819](https://github.com/vueComponent/ant-design-vue/issues/6819)
|
||||
- 🌟 Avatar group mode supports shape [#6822](https://github.com/vueComponent/ant-design-vue/issues/6822)
|
||||
- 🌟 AutoComplete supports borderless and custom clearIcon [#6829](https://github.com/vueComponent/ant-design-vue/issues/6829)
|
||||
- 🌟 InputPassword supports controlled visible [#6863](https://github.com/vueComponent/ant-design-vue/issues/6863)
|
||||
- 🐞 Fix the style misalignment problem when InputGroup is large [#6866](https://github.com/vueComponent/ant-design-vue/issues/6866)
|
||||
- 🐞 Fix the problem that Checkable Tag cannot customize class [#6854](https://github.com/vueComponent/ant-design-vue/issues/6854)
|
||||
- 🐞 Fix the rendering problem in Tabs animation mode [#6855](https://github.com/vueComponent/ant-design-vue/issues/6855)
|
||||
- 🐞 Fix the problem that the Image height attribute does not take effect [#6840](https://github.com/vueComponent/ant-design-vue/issues/6840)
|
||||
- 🐞 Fix InputNumber trigger mouseup event [#6772](https://github.com/vueComponent/ant-design-vue/issues/6772)
|
||||
- 🐞 Fix the Dropdown style problem when Tabs are collapsed [#6757](https://github.com/vueComponent/ant-design-vue/issues/6757)
|
||||
- 🐞 Fix Table expandedRowRender property does not take effect [#6783](https://github.com/vueComponent/ant-design-vue/issues/6783)
|
||||
- 🐞 Fix dayjs not packaged into dist [#6767](https://github.com/vueComponent/ant-design-vue/issues/6767)
|
||||
- 🐞 Fix clipPath browser compatibility issue [#6770](https://github.com/vueComponent/ant-design-vue/issues/6770)
|
||||
- 🐞 Fix Carousel autoplay responsive problem [#6768](https://github.com/vueComponent/ant-design-vue/issues/6768)
|
||||
- 🐞 Fix PageHeader ghost style problem [#6761](https://github.com/vueComponent/ant-design-vue/issues/6761)
|
||||
- 🐞 Fix Checkbox not triggering Form validation [#6741](https://github.com/vueComponent/ant-design-vue/issues/6741)
|
||||
- 🐞 Fix the problem that the Input prefix attribute does not take effect [#6810](https://github.com/vueComponent/ant-design-vue/issues/6810)
|
||||
- 🐞 Fix Badge style problem in Avatar [#6874](https://github.com/vueComponent/ant-design-vue/issues/6874)
|
||||
|
||||
## 4.0
|
||||
|
||||
### 🔥🔥🔥 4.0 official version released 🔥🔥🔥
|
||||
|
||||
### Design specification adjustment
|
||||
|
||||
- Adjust the row height from `1.5`(`21px`) to `1.5715`(`22px`).
|
||||
- Basic round corner adjustment, changed from `4px` to `2px`.
|
||||
- The color brightness of the dividing line is reduced, from `#E8E8E8` to `#F0F0F0`.
|
||||
- The default background color of Table is changed from transparent to white.
|
||||
- Basic rounded corner adjustment, changed from unified `2px` to four-level rounded corners, which are `2px` `4px` `6px` `8px` respectively, which are applied to different scenarios, for example, the rounded corners of the default size Button are adjusted to `6px`.
|
||||
- Main color adjustment, changed from `#1890ff` to `#1677ff`.
|
||||
- Overall shadow adjustment, from the original three-level shadow adjustment to two levels, which are used for resident page components (such as Card) and interactive feedback (such as Dropdown).
|
||||
- Adjust the internal spacing of some components.
|
||||
- Overall de-wireframing.
|
||||
|
||||
### Compatibility adjustment
|
||||
### Add 5 new components
|
||||
|
||||
- The minimum supported version of Vue is Vue 3.0.
|
||||
- Segmented segment controller
|
||||
- WaterMark watermark
|
||||
- QrCode QR code
|
||||
- FloatButton floating button
|
||||
- Tour roaming guide
|
||||
|
||||
#### Adjusted API
|
||||
### Technical adjustments
|
||||
|
||||
- Removed LocaleProvider, please use `ConfigProvider` instead.
|
||||
- Removed the afterClose property of Tag.
|
||||
- Merged FormModel and Form, see the Form refactoring part below for details.
|
||||
- `tabIndex`, `maxLength`, `readOnly`, `autoComplete`, `autoFocus` are changed to all lowercase.
|
||||
- In order to use the slot more friendly in template syntax, all related to xxxRender, renderXxxx are changed to single parameter, involving `itemRender`, `renderItem`, `customRender`, `dropdownRender`, `dateCellRender`, `dateFullCellRender`, `monthCellRender`, `monthFullCellRender`, `renderTabBar`.
|
||||
- All the places where scopedSlots are configured are changed to slots.
|
||||
- `{ on, props, attrs, ... }` configuration is flattened, such as `{ props: {type:'xxx'}, on: {click: this.handleClick}}` changed to `{ type: 'xxx', onClick: this.handleClick }`, related fields: `okButtonProps`, `cancelButtonProps`.
|
||||
- Change xxx.sync to v-model:xxx
|
||||
- v-model is changed to v-model:xxx, which specifically involves components:
|
||||
- Deprecated less and adopted CSS-in-JS to better support dynamic themes.
|
||||
- All less files are removed, and less variables no longer support leaking.
|
||||
- css files are no longer included in the product. Since CSS-in-JS supports importing on demand, the original `ant-design-vue/dist/antd.css` has also been removed. If you need to reset some basic styles, please import `ant-design-vue/dist/reset .css`.
|
||||
- If you need to reset the style of the component and don't want to introduce `ant-design-vue/dist/reset.css` to pollute the global style, you can try to use [App component](/components/app), to solve the problem that native elements do not have ant-design-vue specification style.
|
||||
- Removed css variables and dynamic theme schemes built on top of it.
|
||||
- LocaleProvider has been deprecated in 3.x (use `<ConfigProvider locale />` instead), we have completely removed the related directories `ant-design-vue/es/locale-provider`, `ant- design-vue/lib/locale-provider`.
|
||||
- `babel-plugin-import` is no longer supported, CSS-in-JS itself has the ability to load on demand, no longer need plug-in support.
|
||||
|
||||
- The components changed from v-model to v-model:checked are: CheckableTag, Checkbox, Switch
|
||||
- The components changed from v-model to v-model:value are: Radio, Mentions, CheckboxGroup, Rate, DatePicker
|
||||
- The components changed from v-model to v-model:visible are: Tag, Popconfirm, Popove, Tooltip, Moda, Dropdown
|
||||
- The components changed from v-model to v-model:activeKey are: Collaps, Tabs
|
||||
- The components changed from v-model to v-model:current are: Steps
|
||||
- The components changed from v-model to v-model:selectedKeys are: Menu
|
||||
#### Component API adjustments
|
||||
|
||||
#### Icon Upgrade
|
||||
- The classname API of the component popup is unified to `popupClassName`, and similar APIs such as `dropdownClassName` will be replaced.
|
||||
|
||||
In `ant-design-vue@1.2.0`, we introduced the svg icon ([Why use the svg icon?](https://github.com/ant-design/ant-design/issues/10353)). The icon API that uses string naming cannot be loaded on demand, so the svg icon file is fully introduced, which greatly increases the size of the packaged product. In 2.0, we adjusted the icon usage API to support tree shaking, reducing the default package size by approximately 150 KB (Gzipped).
|
||||
- AutoComplete component
|
||||
- Cascader component
|
||||
- Select component
|
||||
- TreeSelect component
|
||||
- TimePicker component
|
||||
- DatePicker component
|
||||
- Mentions component
|
||||
|
||||
The old way of using Icon will be obsolete:
|
||||
- The controlled visibility API of the component popup is unified as `open`, and `visible` and other similar APIs will be replaced.
|
||||
- Drawer component `visible` becomes `open`.
|
||||
- Modal component `visible` becomes `open`.
|
||||
- Dropdown component `visible` becomes `open`.
|
||||
- Tooltip component `visible` becomes `open`.
|
||||
- Tag component `visible` has been removed.
|
||||
- Slider component `tooltip` related API converges to `tooltip` property.
|
||||
- Table component `filterDropdownVisible` changed to `filterDropdownOpen`.
|
||||
- `getPopupContainer`: All `getPopupContainer` needs to ensure that the returned div is unique.
|
||||
- Drawer `style` and `class` are migrated to the Drawer popup area, and the original attributes are replaced by `rootClassName` and `rootStyle`.
|
||||
|
||||
```html
|
||||
<a-icon type="smile" />
|
||||
<a-button icon="smile" />
|
||||
```
|
||||
#### Component refactoring and removal
|
||||
|
||||
In 2.0, an on-demand introduction method will be adopted:
|
||||
- Remove the `locale-provider` directory. `LocaleProvider` has been removed in v4, please use `ConfigProvider` instead.
|
||||
|
||||
```html
|
||||
<template>
|
||||
<smile-outlined />
|
||||
<a-button>
|
||||
<template v-slot:icon><smile-outlined /></template>
|
||||
</a-buttom>
|
||||
</template>
|
||||
<script>
|
||||
import SmileOutlined from'@ant-design/icons-vue/SmileOutlined';
|
||||
export default {
|
||||
components: {
|
||||
SmileOutlined
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
- Remove `xxxl` breakpoint attribute in grid layout. `xxxl` attribute has been removed in v4, you can use [theme customization](/docs/vue/customize-theme) to modify `screen[XS|SM|MD|LG|XL|XXL]` to modify the break Point value achieved.
|
||||
|
||||
#### Component refactoring
|
||||
- The BackTop component was deprecated in `4.0.0` and moved to the FloatButton floating button. If needed, it can be imported from FloatButton.
|
||||
|
||||
In 1.x, we provide two form components, Form and FormModel. The original Form component uses v-decorator for data binding. In Vue2, we use context to force update components. However, in Vue3, due to the introduction of patchFlag, etc. Optimization method, forced refresh will destroy the performance advantage brought by patchFlag. So in version 2.0, we merged Form and FormModel, retained the use of FormModel, enriched related functions, and renamed it to Form.
|
||||
### [Upgrade Guide](/docs/vue/migration-v4)
|
||||
|
||||
Involving changes:
|
||||
## 3.x
|
||||
|
||||
- Added `scrollToFirstError`, `name`, `validateTrigger` properties for Form, added `finish`, `finishFailed` events, and added `scrollToField` method.
|
||||
- Form.Item adds `validateFirst`, `validateTrigger`, and discards the `prop` attribute, and replaces it with `name`.
|
||||
- The nested field path uses an array. In the past version, we used. To represent the nested path (such as user.name to represent {user: {name:''} }). However, in some back-end systems, the variable name will also carry .. This causes users to need additional codes for conversion. Therefore, in the new version, nested paths are represented by arrays to avoid wrong handling behaviors (such as ['user','name']).
|
||||
- validateFields no longer supports callback. validateFields will return a Promise object, so you can perform corresponding error handling through async/await or then/catch. It is no longer necessary to determine whether errors is empty:
|
||||
Visit [GitHub](https://github.com/vueComponent/ant-design-vue/blob/3.x/CHANGELOG.zh-CN.md) `3.x` Change Log。
|
||||
|
||||
```js
|
||||
// v1
|
||||
// eslint-disable-next-line no-undef,no-unused-vars
|
||||
validateFields((err, value) => {
|
||||
if (!err) {
|
||||
// Do something with value
|
||||
}
|
||||
});
|
||||
```
|
||||
## 2.x
|
||||
|
||||
Change to
|
||||
|
||||
```js
|
||||
// v2
|
||||
// eslint-disable-next-line no-undef,no-unused-vars
|
||||
validateFields().then(values => {
|
||||
// Do something with value
|
||||
});
|
||||
```
|
||||
Visit [GitHub](https://github.com/vueComponent/ant-design-vue/blob/2.x/CHANGELOG.zh-CN.md) `2.x` Change Log。
|
||||
|
||||
## 1.x
|
||||
|
||||
|
|
|
@ -10,713 +10,229 @@
|
|||
|
||||
---
|
||||
|
||||
## 3.0.0-alpha.1
|
||||
|
||||
`2021-10-07`
|
||||
|
||||
- 🌟 重构 `Tabs` [#4732](https://github.com/vueComponent/ant-design-vue/issues/4732)
|
||||
- 移除 `prevClick`、`nextClick` 事件,使用 `tabScroll` 事件替代
|
||||
- 废弃 `tabBarExtraContent` 插槽,使用 rightExtra 插槽替换,同时新增 `leftExtra` 插槽
|
||||
- 新增 `addIcon`、`closeIcon`、`moreIcon` 插槽
|
||||
- 🌟 重构 `Card`,废弃 tabList slots 配置,使用 customTab 插槽统一配置 [#4732](https://github.com/vueComponent/ant-design-vue/issues/4732)
|
||||
- 🌟 重构 `Drawer`
|
||||
- 新增 `autofocus` `contentWrapperStyle` `footerStyle` `headerStyle` `push` `size` `forceRender` 等属性
|
||||
- 新增 `closeIcon` `extra` `footer` 等插槽
|
||||
- 废弃 `afterVisibleChange` 属性,使用同名事件替代
|
||||
- 🐞 修复 `Table` pagination 没有响应式变化问题 [1add0d](https://github.com/vueComponent/ant-design-vue/commit/1add0d251cd35aa2c55404f7a60f1531425490c1)
|
||||
- 🐞 修复 `notification` 样式错位问题 [#4703](https://github.com/vueComponent/ant-design-vue/issues/4703)
|
||||
- 🐞 修复 `Tree` fieldsName 导致的选中、拖拽等异常 [#4726](https://github.com/vueComponent/ant-design-vue/issues/4726)
|
||||
|
||||
## 3.0.0-alpha.0
|
||||
|
||||
`2021-09-24`
|
||||
|
||||
🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
||||
|
||||
- 文档开源,如果您的公司不能外网访问,可以私有化部署,但不可以传播,不可以商业化
|
||||
- 移除了 Transfer 的 `lazy` 属性,它并没有起到真正的优化效果。
|
||||
- 移除了 Select 的 `combobox` 模式,请使用 `AutoComplete` 替代。
|
||||
- 废弃 Button.Group,请使用 `Space` 代替。
|
||||
- `Timeline.Item` 新增 label
|
||||
- `Steps` 新增 `responsive`、`percent`
|
||||
- `Collapse` 新增 `ghost`、`collapsible`
|
||||
- `Popconfirm` 新增 `cancelButton`、`okButton`, 以及 `esc` 按键隐藏
|
||||
- `ConfigProvider` 新增 ConfigProvider.config,定义 `Modal.xxx` `message` `notification` 的配置
|
||||
- `Tree` `TreeSlelct`
|
||||
|
||||
- 新增了虚拟滚动,废弃使用 `a-tree-node` `a-tree-select-node` 构建节点,使用 `treeData` 属性替代,提升组件性能
|
||||
- 废弃 `scopedSlots` `slots` 自定义渲染节点,使用 `v-slot:title` 替换,提升易用性,避免插槽配置膨胀,同时也避免了插槽冲突问题
|
||||
|
||||
- `Table`
|
||||
|
||||
- 移除了 Table 的 `rowSelection.hideDefaultSelections` 属性,请在 `rowSelection.selections` 中使用 `SELECTION_ALL` 和 `SELECTION_INVERT` 替代,[自定义选择项](/components/table/#components-table-demo-row-selection-custom)。
|
||||
- 移除了 Column slots,分别使用 `v-slot:headerCell` `v-slot:headerCell` `v-slot:bodyCell` `v-slot:customFilterDropdown` `v-slot:customFilterIcon` 替换,提升易用性,避免插槽配置膨胀,同时也避免了插槽冲突问题
|
||||
- 新增 expandFixed 控制展开图标是否固定
|
||||
- 新增 showSorterTooltip 表头是否显示下一次排序的 tooltip 提示。
|
||||
- 新增 sticky 用于设置粘性头部和滚动条
|
||||
- 新增 rowExpandable 用于设置是否允许行展开
|
||||
- 新增插槽 headerCell 用于个性化头部单元格
|
||||
- 新增插槽 bodyCell 用于个性化单元格
|
||||
- 新增插槽 customFilterDropdown 用于自定义筛选菜单,需要配合 `column.customFilterDropdown` 使用
|
||||
- 新增插槽 customFilterIcon 用于自定义筛选图标
|
||||
- 新增插槽 emptyText 用于自定义空数据时的显示内容
|
||||
- 新增插槽 summary 用于总结栏
|
||||
|
||||
- `DatePicker` `TimePicker` `Calendar`
|
||||
|
||||
- 默认使用更加轻量级的 dayjs 替换 momentjs,如果你的项目过大,使用了大量的 momentjs 的方法,你可以参考文档[自定义时间库](/docs/vue/replace-date-cn),替换成 momentjs。
|
||||
- UI 交互调整,对其 antd 4.x 交互规范
|
||||
|
||||
- `Form` 这次更新主要目标是提升性能,如果你没有自定义表单控件,几乎可以忽略该部分
|
||||
|
||||
- 自 3.0 版本以后,Form.Item 不再劫持子元素,而是通过 provider / inject 依赖注入的方式进行自动校验,这种方式可以提高组件性能,子元素也不会限制个数,同样子元素也可以是进一步封装的高级组件。你可以参考[自定义表单控件示例](#components-form-demo-customized-form-controls)
|
||||
|
||||
但它同样会有一些缺点:
|
||||
|
||||
1、自定义组件如果希望 Form.Item 进行校验展示,你需要 `const {id, onFieldChange, onFieldBlur} = useFormItemContext()` 注入,并调用相应的方法。
|
||||
|
||||
2、一个 Form.Item 只能收集一个表单项的数据,如果有多个表单项,会导致收集错乱,例如,
|
||||
|
||||
```html
|
||||
<a-form-item>
|
||||
<a-input name="a"></a-input>
|
||||
<a-input name="b"></a-input>
|
||||
</a-form-item>
|
||||
```
|
||||
## 4.2.6
|
||||
|
||||
如上 Form.Item 并不知道需要收集 `name="a"` 还是 `name=`b``,你可以通过如下三种方式去解决此类问题:
|
||||
|
||||
第一种,使用多个 `a-form-item`:
|
||||
|
||||
```html
|
||||
<a-form-item>
|
||||
<a-input name="a"></a-input>
|
||||
<a-form-item><a-input name="b"></a-input></a-form-item>
|
||||
</a-form-item>
|
||||
```
|
||||
|
||||
第二种,使用自定义组件包裹,并在自定义组件中调用 `useFormItemContext`,相当于把多个表单项合并成了一个
|
||||
- 🐞 修复 Modal 组件在 chrome 下,aria-hidden 报错问题 [#7823](https://github.com/vueComponent/ant-design-vue/issues/7823)
|
||||
- 🐞 修复 Safari 下自带输入法 input 组件输入中文时,自动填写小数点问题 [#7918](https://github.com/vueComponent/ant-design-vue/issues/7918)
|
||||
- 🐞 修复 InputNumber 组件 disabled 样式问题 [#7776](https://github.com/vueComponent/ant-design-vue/issues/7776)
|
||||
- 🐞 修复 Select 无法失焦问题 [#7819](https://github.com/vueComponent/ant-design-vue/issues/7819)
|
||||
|
||||
```html
|
||||
<script>
|
||||
// 自定义组件
|
||||
import { Form } from 'ant-desing-vue';
|
||||
export default {
|
||||
setup() {
|
||||
const formItemContext = Form.useFormItemContext();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
```html
|
||||
<a-form-item>
|
||||
<custom-com>
|
||||
<a-input name="a"></a-input>
|
||||
<a-input name="b"></a-input>
|
||||
</custom-com>
|
||||
</a-form-item>
|
||||
```
|
||||
## 4.2.5
|
||||
|
||||
第三种,组件库提供了一个 `a-form-item-rest` 组件,它会阻止数据的收集,你可以将不需要收集校验的表单项放到这个组件中即可,它和第一种方式很类似,但它不会产生额外的 dom 节点。
|
||||
- 🐞 修复 Empty 组件内存泄漏问题
|
||||
- 🐞 修复 Image width & height 属性不生效问题
|
||||
|
||||
```html
|
||||
<a-form-item>
|
||||
<a-input name="a"></a-input>
|
||||
<a-form-item-rest><a-input name="b"></a-input></a-form-item-rest>
|
||||
</a-form-item>
|
||||
```
|
||||
## 4.2.4
|
||||
|
||||
## 2.2.8
|
||||
- 🐞 修复 Wave 内存泄漏问题
|
||||
|
||||
`2021-09-17`
|
||||
## 4.2.3
|
||||
|
||||
- 🌟 Upload method 支持 patch [#4637](https://github.com/vueComponent/ant-design-vue/issues/4637)
|
||||
- 🌟 List gutter 支持数组 [d2b721](https://github.com/vueComponent/ant-design-vue/commit/d2b72143f0e15c8716b4ea8f68b2b72eff5cf510)
|
||||
- 🐞 修复 Modal 类型错误 [#4632](https://github.com/vueComponent/ant-design-vue/issues/4632)
|
||||
- 🐞 修复 AutoComplete 无法重置 undefined 问题 [741718](https://github.com/vueComponent/ant-design-vue/commit/741718a0f92c790266e7a07d8d129c5673344a7e)
|
||||
- 🐞 修复 Tag 关闭图标样式丢失问题 [#4649](https://github.com/vueComponent/ant-design-vue/issues/4649)
|
||||
- 🐞 修复 TreeSelect 清楚按钮在特殊条件下不显示问题 [#4655](https://github.com/vueComponent/ant-design-vue/issues/4655)
|
||||
- 🐞 修复 useForm immdiate 不生效问题 [#4646](https://github.com/vueComponent/ant-design-vue/issues/4646)
|
||||
- 🌟 TourStep 自定义 Button,支持函数 children [#7628](https://github.com/vueComponent/ant-design-vue/pull/7628)
|
||||
- 🐞 修复 Select 和 Cascader 搜索多选模式下,输入值被隐藏问题 [#7640](https://github.com/vueComponent/ant-design-vue/issues/7640)
|
||||
|
||||
## 2.2.7
|
||||
## 4.2.2
|
||||
|
||||
`2021-09-08`
|
||||
- 🐞 修复 TreeSelect placeholder 插槽无效 [#7545](https://github.com/vueComponent/ant-design-vue/issues/7545)
|
||||
- 🐞 修复 Tree 插槽响应式无效问题 [40ad45](https://github.com/vueComponent/ant-design-vue/commit/40ad45bc05b2bf9d0a2445d9f6ff365468ba90b7)
|
||||
- 🐞 修复 FloatButton target 类型错误问题 [#7576](https://github.com/vueComponent/ant-design-vue/issues/7576)
|
||||
- 🐞 修复 FormItem className 错误问题 [#7582](https://github.com/vueComponent/ant-design-vue/issues/7582)
|
||||
- 🐞 修复 Input lazy 下无法输入问题 [#7543](https://github.com/vueComponent/ant-design-vue/issues/7543)
|
||||
- 🐞 修复 Select 输入中文时,placeholder 未隐藏问题 [#7611](https://github.com/vueComponent/ant-design-vue/issues/7611)
|
||||
- 🐞 修复 DatePicker 点击预设选项时,弹窗闪动问题 [#7550](https://github.com/vueComponent/ant-design-vue/issues/7550)
|
||||
|
||||
- 🌟 Menu 支持 overflowedIndicator 插槽 [#4515](https://github.com/vueComponent/ant-design-vue/issues/4515)
|
||||
- 🌟 useForm 支持动态 rule [#4498](https://github.com/vueComponent/ant-design-vue/issues/4498)
|
||||
- 🌟 Select 支持 Number 类型 [#4570](https://github.com/vueComponent/ant-design-vue/issues/4570)
|
||||
- 🐞 修复 css zoom 引起的 warning 问题 [#4554](https://github.com/vueComponent/ant-design-vue/issues/4554)
|
||||
- 🐞 修复 Mentions 输入中文报错问题 [#4524](https://github.com/vueComponent/ant-design-vue/issues/4524)
|
||||
- 🐞 修复 AutoComplete 不支持全局 prefixCls 问题 [#4566](https://github.com/vueComponent/ant-design-vue/issues/4566)
|
||||
- 🐞 修复 Table 嵌套表格报错问题 [#4600](https://github.com/vueComponent/ant-design-vue/issues/4600)
|
||||
- 🐞 修复 Dropdown 下的 MenuItem danger 属性无样式问题 [#4618](https://github.com/vueComponent/ant-design-vue/issues/4618)
|
||||
- 🐞 修复 Modal.xxx 等方法传递 appContext 失效问题 [#4627](https://github.com/vueComponent/ant-design-vue/issues/4627)
|
||||
- 🐞 修复一些 TS 类型错误
|
||||
## 4.2.1
|
||||
|
||||
## 2.2.6
|
||||
- 🐞 修复 Input 清空操作才报错问题 [#7523](https://github.com/vueComponent/ant-design-vue/issues/7523)
|
||||
|
||||
`2021-08-12`
|
||||
## 4.2.0
|
||||
|
||||
- 🐞 修复 `Table` 展开列表渲染错位问题 [#4507](https://github.com/vueComponent/ant-design-vue/issues/4507)
|
||||
- 🐞 修复 `Rate` 自定义 `character` 插槽未生效问题 [#4509](https://github.com/vueComponent/ant-design-vue/issues/4509)
|
||||
- 🐞 添加 resize-observer-polyfill, 修复在低版本 Chrome 下报错问题 [#4508](https://github.com/vueComponent/ant-design-vue/issues/4508)
|
||||
|
||||
## 2.2.5
|
||||
|
||||
`2021-08-11`
|
||||
|
||||
- 🌟 `Select` 支持通过 option 插槽定制化节点 [68c1f4](https://github.com/vueComponent/ant-design-vue/commit/68c1f4550108a3a6bbe4f1b2c5c168523fd6c84a)
|
||||
- 🐞 修复开发环境下弹窗类组件在低版本 chrome 下,不显示问题,并避免弹窗闪动 [#4409](https://github.com/vueComponent/ant-design-vue/issues/4409)
|
||||
- 🐞 修复 `Select` 打开时没有滚动到激活位置问题 [ccb240](https://github.com/vueComponent/ant-design-vue/commit/ccb24016c07632f49550646c971060c402586c67)
|
||||
|
||||
## 2.2.4
|
||||
|
||||
`2021-08-10`
|
||||
|
||||
- 🌟 支持 Vue@3.2 [#4490](https://github.com/vueComponent/ant-design-vue/issues/4490)
|
||||
- 🌟 自动隐藏 `Table` 横向滚动条 [#4484](https://github.com/vueComponent/ant-design-vue/issues/4484)
|
||||
- 🐞 修复 `Progress` trailColor 不生效问题 [#4483](https://github.com/vueComponent/ant-design-vue/issues/4483)
|
||||
|
||||
## 2.2.3
|
||||
|
||||
`2021-08-07`
|
||||
|
||||
- 🌟 `Table` 固定列使用 `position: sticky` , 提升性能,解决部分场景不对齐问题 [38569c](https://github.com/vueComponent/ant-design-vue/commit/38569c28c7eb4eaa34f2cc096982daea901062d4)
|
||||
- 🌟 `Collapse` 支持 number 类型 key [#4405](https://github.com/vueComponent/ant-design-vue/issues/4405)
|
||||
- 🌟 优化 `Tabs` 在 windows 下选中时闪动问题 [#4241](https://github.com/vueComponent/ant-design-vue/issues/4241)
|
||||
- 🌟 `InputPassword` 支持全局设置 prefixCls [#4430](https://github.com/vueComponent/ant-design-vue/issues/4430)
|
||||
- 🐞 修复 `Select` 无法滚动问题 [#4396](https://github.com/vueComponent/ant-design-vue/issues/4396)
|
||||
- 🐞 修复 `Badge` 在 ssr 下报错问题 [#4384](https://github.com/vueComponent/ant-design-vue/issues/4384)
|
||||
- 🐞 修复 `Form` 多出无效数据字段问题 [#4435](https://github.com/vueComponent/ant-design-vue/issues/4435)
|
||||
- 🐞 修复 `FormItem` 子元素是原生标签时报错问题 [#4383](https://github.com/vueComponent/ant-design-vue/issues/4383)
|
||||
- 🐞 修复 `TreeSelect` 通过 slot 自定义 title 时报错问题 [#4459](https://github.com/vueComponent/ant-design-vue/issues/4459)
|
||||
|
||||
## 2.2.2
|
||||
|
||||
`2021-07-11`
|
||||
|
||||
- 🌟 Switch 新增 checkedValue、unCheckedValue 属性用于自定义 checked 绑定值 [#4329](https://github.com/vueComponent/ant-design-vue/issues/4329)
|
||||
- 🐞 修复 SubMenu 动画丢失的问题 [#4325](https://github.com/vueComponent/ant-design-vue/issues/4325)
|
||||
- 🐞 修复 TimePicker 在 Form 下验证错误时没有红框问题 [#4331](https://github.com/vueComponent/ant-design-vue/issues/4331)
|
||||
- 🐞 修复 UploadDragger 不支持 vite-plugin-components 按需加载问题 [#4334](https://github.com/vueComponent/ant-design-vue/issues/4334)
|
||||
- 🐞 修复 TreeSelect 通过 slot 自定义 title 时报错问题 [1152e8](https://github.com/vueComponent/ant-design-vue/commit/1152e8cd71cadf9e8fb4797916adca20c0e35974)
|
||||
- 🐞 修复 Dropdown submenu 样式丢失问题 [#4351](https://github.com/vueComponent/ant-design-vue/issues/4351)
|
||||
- TS
|
||||
- 修复 Table 在 ts 4.3.5 版本下类型报错问题 [#4296](https://github.com/vueComponent/ant-design-vue/issues/4296)
|
||||
- 完善 notification 类型 [#4346](https://github.com/vueComponent/ant-design-vue/issues/4346)
|
||||
|
||||
## 2.2.1
|
||||
|
||||
`2021-07-06`
|
||||
|
||||
- 🐞 修复 Space 组件在不支持 flex 的浏览器中样式不生效问题
|
||||
- 🐞 修复 DatePicker 在 safari 下触发滚动问题 [#4323](https://github.com/vueComponent/ant-design-vue/issues/4323)
|
||||
|
||||
## 2.2.0
|
||||
|
||||
`2021-07-06`
|
||||
|
||||
- 🎉 重构 Button 组件,移除 type="danger",新增 `danger` 属性 [#4291](https://github.com/vueComponent/ant-design-vue/issues/4291)
|
||||
- 🐞 修复 Rate 组件不更新问题 [#4294](https://github.com/vueComponent/ant-design-vue/issues/4294)
|
||||
- 🐞 修复 Tree replaceFields 报错问题 [#4298](https://github.com/vueComponent/ant-design-vue/issues/4298)
|
||||
- 🐞 修复 Modal 缺少 parentContext 类型问题 [#4305](https://github.com/vueComponent/ant-design-vue/issues/4305)
|
||||
|
||||
## 2.2.0-rc.1
|
||||
|
||||
`2021-06-29`
|
||||
|
||||
- 🌟 更改 babel 配置,较小构建包大小
|
||||
- 🌟 Form 原生提供 useForm 功能,废弃 @ant-design-vue/use 库
|
||||
- 🐞 修复 Form validateFirst 属性在多个校验规则时不触发 reject 问题 [#4273](https://github.com/vueComponent/ant-design-vue/issues/4273)
|
||||
- 🐞 修复 List 循环引用导致 Vite 下报错问题 [#4263](https://github.com/vueComponent/ant-design-vue/issues/4263)
|
||||
- 🐞 修复 Menu 事件回调缺少 item 属性问题 [#4290](https://github.com/vueComponent/ant-design-vue/issues/4290)
|
||||
|
||||
## 2.2.0-beta.6
|
||||
|
||||
`2021-06-26`
|
||||
|
||||
- 🌟 Menu 性能优化 [e8b957](https://github.com/vueComponent/ant-design-vue/commit/e8b95784eb1ee0554b0d6b17bdc14e18775f2ae6)
|
||||
- 🐞 修复 Layout、RangePicker、WeekPicker、Textarea 按需加载失效
|
||||
|
||||
## 2.2.0-beta.5
|
||||
|
||||
`2021-06-24`
|
||||
|
||||
- 🎉 支持 vite-plugin-components 按需加载
|
||||
- 🎉 重构 List 组件
|
||||
- 🌟 Select 新增响应式折叠选项 [656d14](https://github.com/vueComponent/ant-design-vue/commit/656d14fc4e4ef0f781324438f0d58cfb6816d583)
|
||||
- 🐞 修复 Select 动态更新选项时虚拟列表无法滚动问题 [b2aa49d](https://github.com/vueComponent/ant-design-vue/commit/b2aa49d064a83c6ce786a6bb4cd9fc5266a5964d)
|
||||
- 🐞 修复 Select 键盘事件位置不正确问题 [604372](https://github.com/vueComponent/ant-design-vue/commit/604372ff2da521dd580ad5229f7dbd445c1c6190)
|
||||
- 🐞 修复 AutoComplete 不支持 options slot 问题 [#4012](https://github.com/vueComponent/ant-design-vue/issues/4012)
|
||||
|
||||
## 2.2.0-beta.4
|
||||
|
||||
`2021-06-21`
|
||||
|
||||
- 🎉 重构 Descriptions 组件 [#4219](https://github.com/vueComponent/ant-design-vue/issues/4219)
|
||||
- 🐞 修复 Countdown 不触发 finish 事件问题 [#4222](https://github.com/vueComponent/ant-design-vue/issues/4222)
|
||||
- 🐞 修复 ConfigProvider 在 vue 3.1 下报错问题 [#4225](https://github.com/vueComponent/ant-design-vue/issues/4225)
|
||||
- 🐞 修复 Dropdown 下使用 SubMenu 报错问题 [#4205](https://github.com/vueComponent/ant-design-vue/issues/4205)
|
||||
- 🐞 修复 Col 类型错误 [#4226](https://github.com/vueComponent/ant-design-vue/issues/4226)
|
||||
- 🐞 修复 Typography 失焦时不触发 onEnd 问题 [#4227](https://github.com/vueComponent/ant-design-vue/issues/4227)
|
||||
- 🐞 修复 ImagePreview 样式丢失问题 [#4231](https://github.com/vueComponent/ant-design-vue/issues/4231)
|
||||
|
||||
## 2.2.0-beta.3
|
||||
|
||||
`2021-06-11`
|
||||
|
||||
- 🎉 重构 Breadcrumb、Statistic、Tag 组件
|
||||
- 🌟 Statistic 支持 loading 属性
|
||||
- 🐞 修复 Menu 渲染多次子组件问题,提升性能 [6ae707](https://github.com/vueComponent/ant-design-vue/commit/6ae707edf508a9c5e8dca7dacf1410de5251bcf8)
|
||||
- 🐞 修复 FormItem 自定义 class 失效 [617e53](https://github.com/vueComponent/ant-design-vue/commit/617e534fda2ae6d468b5e9d3eb43370f8a4b0000)
|
||||
- 🐞 修复 MenuDivider class 错误问题 [#4195](https://github.com/vueComponent/ant-design-vue/issues/4195)
|
||||
- 🐞 修复 Tag、Image 类型错误
|
||||
- 🐞 修复 Modal 等组件动画丢失问题 [#4191](https://github.com/vueComponent/ant-design-vue/issues/4191)
|
||||
- 🐞 修复 Select class 不能动态更新问题 [#4194](https://github.com/vueComponent/ant-design-vue/issues/4194)
|
||||
- 🐞 修复 Dropdown 邮件展开,不能点击收起的问题 [#4198](https://github.com/vueComponent/ant-design-vue/issues/4198)
|
||||
- 🐞 修复 FormItem 缺少部分导出方法问题 [#4183](https://github.com/vueComponent/ant-design-vue/issues/4183)
|
||||
|
||||
## 2.2.0-beta.2
|
||||
|
||||
`2021-06-08`
|
||||
|
||||
- 🐞 修复 PageHeader 显示多余字符问题 [4de773](https://github.com/vueComponent/ant-design-vue/commit/4de7737907d485d3dd3be44b70e599cc53edb171)
|
||||
- 🐞 修复部分组件不能在 Vue3.1 下不能正常渲染问题 [#4173](https://github.com/vueComponent/ant-design-vue/issues/4173)
|
||||
- 🐞 修复 Menu.Divider 名称错误问题 [6c5c84](https://github.com/vueComponent/ant-design-vue/commit/6c5c84a3fc4b8abcd7aed0922852a64e0ac293c7)
|
||||
|
||||
## 2.2.0-beta.1
|
||||
|
||||
`2021-06-07`
|
||||
|
||||
- 🔥🔥🔥 虚拟 Table 独立库发布 https://www.npmjs.com/package/@surely-vue/table , 该组件是一个独立的库,目前文档示例尚未完善,他是一个完全 ts 开发的组件,有较好的类型提示,npm 上已有 API 文档,着急使用的的可以摸索着用起来了,这里有个在线体验示例,https://store.antdv.com/pro/preview/list/big-table-list
|
||||
- 🔥🔥🔥 重构大量组件,源码更加易读,性能更优,ts 类型更加全面
|
||||
- 本版本重构组件 Anchor、Alert、Avatar、Badge、BackTop、Col、Form、Layout、Menu、Space、Spin、Switch、Row、Result、Rate
|
||||
- 🎉 Menu
|
||||
|
||||
- 性能更优 [#3300](https://github.com/vueComponent/ant-design-vue/issues/3300)
|
||||
- 修复高亮不正确问题 [#4053](https://github.com/vueComponent/ant-design-vue/issues/4053)
|
||||
- 修复控制台无效 warning [#4169](https://github.com/vueComponent/ant-design-vue/issues/4169)
|
||||
- 更加易用,更加简单的使用单文件递归 [#4133](https://github.com/vueComponent/ant-design-vue/issues/4133)
|
||||
- 💄 图标 icon 需要通过 slot 传递
|
||||
|
||||
- Skeleton
|
||||
|
||||
- 🌟 支持 Skeleton.Avatar 占位组件。
|
||||
- 🌟 支持 Skeleton.Button 占位组件。
|
||||
- 🌟 支持 Skeleton.Input 占位组件。
|
||||
|
||||
- 💄 破坏性更新
|
||||
|
||||
- `a-menu-item`、`a-sub-menu` 图标需要通过 slot 传递,不在通过子节点自动获取图标
|
||||
- row gutter 支持 row-wrap, 无需使用多个 row 划分 col
|
||||
- Menu 移除 defaultOpenKeys、defaultSelectedKeys; Switch 移除 defaultChecked; Rate 移除 defaultValue; 其它未重构组件的 defaultXxx 命名的属性请谨慎使用,在未来的版本中也会被移除。
|
||||
|
||||
- 🌟 新增 Avatar.Group 组件
|
||||
- 🐞 修复 AutoComplete filterOptions 不生效问题 [#4170](https://github.com/vueComponent/ant-design-vue/issues/4170)
|
||||
- 🐞 修复 Select 自动宽度失效问题 [#4118](https://github.com/vueComponent/ant-design-vue/issues/4118)
|
||||
- 🐞 修复 dist 缺少国际化文件问题 [#3684](https://github.com/vueComponent/ant-design-vue/issues/3684)
|
||||
|
||||
## 2.1.6
|
||||
|
||||
`2021-05-13`
|
||||
|
||||
- 🐞 使用 vue@3.0.10 重新构建,避免控制台 warning [#3998](https://github.com/vueComponent/ant-design-vue/issues/3998)
|
||||
|
||||
## 2.1.5
|
||||
|
||||
`2021-05-12`
|
||||
|
||||
- 🐞 修复 SSR 时报错问题 [#3983](https://github.com/vueComponent/ant-design-vue/issues/3983)
|
||||
|
||||
## 2.1.4
|
||||
|
||||
`2021-05-09`
|
||||
|
||||
- 🐞 修复 `Table` 滚动错位问题 [#4045](https://github.com/vueComponent/ant-design-vue/issues/4045)
|
||||
- 🐞 修复 `Typography` editable 模式触发链接跳转问题 [#4105](https://github.com/vueComponent/ant-design-vue/issues/4105)
|
||||
- 🐞 修复 `Carousel` variableWidth 不生效问题 [#3977](https://github.com/vueComponent/ant-design-vue/issues/3977)
|
||||
- 🐞 修复 `TreeSelect` 无法通过键盘同时删除父子节点问题 [#3508](https://github.com/vueComponent/ant-design-vue/issues/3508)
|
||||
- 🐞 修复若干类型错误问题
|
||||
|
||||
## 2.1.3
|
||||
|
||||
`2021-04-25`
|
||||
|
||||
- 🎉🎉🎉 移除 npm 安装时的广告
|
||||
- 🐞 `Select`
|
||||
- 修复默认激活第一项问题 [#3842](https://github.com/vueComponent/ant-design-vue/issues/3842)
|
||||
- 修复分组显示异常问题 [#3841](https://github.com/vueComponent/ant-design-vue/issues/3841)
|
||||
- 修复动态更新选择项后滚动异常问题 [#3972](https://github.com/vueComponent/ant-design-vue/issues/3972)
|
||||
- 🐞 修复 `Checkbox` 触发两次 `update:checked` 问题 [#3838](https://github.com/vueComponent/ant-design-vue/issues/3838)
|
||||
- 🌟 `Table` column group 支持 fixed [#3882](https://github.com/vueComponent/ant-design-vue/issues/3882)
|
||||
- 🌟 `Table` column 支持 v-for [#3934](https://github.com/vueComponent/ant-design-vue/issues/3934)
|
||||
- 🐞 修复 `Table` 在 windows 显示横向滚动条问题 [6d33d6](https://github.com/vueComponent/ant-design-vue/commit/6d33d60d2bca98825f274e48bcc3badd1857f742)
|
||||
- 🌟 `Form` scrollToFirstError 支持选项参数传递 [#3918](https://github.com/vueComponent/ant-design-vue/issues/3918)
|
||||
- 🐞 修复 `Calendar` 月份选择器显示错误字符问题 [#3915](https://github.com/vueComponent/ant-design-vue/issues/3915)
|
||||
- 🌟 重构 `Switch` 组件,移除 defaultChecked 属性 [#3885](https://github.com/vueComponent/ant-design-vue/issues/3885)
|
||||
- 🐞 修复使用 Vite 时,抛出 process 异常问题 [#3930](https://github.com/vueComponent/ant-design-vue/issues/3930)
|
||||
- 🐞 修复 `Radio` 阴影遮挡问题 [#3955](https://github.com/vueComponent/ant-design-vue/issues/3955)
|
||||
- 🐞 修复 `Form` inline 模式下, span 不生效问题 [#3862](https://github.com/vueComponent/ant-design-vue/issues/3862)
|
||||
- 🐞 修复 `Cascader` keydown 选择不生效问题 [#958](https://github.com/vueComponent/ant-design-vue/issues/958)
|
||||
- 🐞 修复 `Image` 预览功能失败问题 [#3701](https://github.com/vueComponent/ant-design-vue/issues/3701)
|
||||
- 🐞 修复一些 TS 类型问题
|
||||
|
||||
## 2.1.2
|
||||
|
||||
`2021-03-28`
|
||||
|
||||
- 🌟 使用 Vue 3.0.9 重新编译,兼容 3.0.7 及以下版本
|
||||
|
||||
## 2.1.1
|
||||
|
||||
`2021-03-27`
|
||||
|
||||
- 🌟 兼容 Vue 3.0.8,注意:由于 3.0.8 的破坏性更新,2.1.1 无法兼容 3.0.7 以下版本 [vue#3493](https://github.com/vuejs/vue-next/issues/3493)
|
||||
- 🐞 修复 Modal.confirm 缺失 closable ts 类型 [#3684](https://github.com/vueComponent/ant-design-vue/issues/3845)
|
||||
- 🐞 修复 Upload 自定义 method 不生效问题 [#3843](https://github.com/vueComponent/ant-design-vue/issues/3843)
|
||||
|
||||
## 2.1.0
|
||||
|
||||
`2021-03-20`
|
||||
|
||||
- 🎉🎉🎉 新增 `Typography` 组件 [#3807](https://github.com/vueComponent/ant-design-vue/issues/3807)
|
||||
- 🌟 Modal 方法新增关闭图标定制 [#3753](https://github.com/vueComponent/ant-design-vue/issues/3753)
|
||||
- 🐞 修复缺失包含国际化的构建文件 [#3684](https://github.com/vueComponent/ant-design-vue/issues/3684)
|
||||
- 🐞 修复 Drawer 销毁后报错问题 [#848d64](https://github.com/vueComponent/ant-design-vue/commit/848d6497e68c87566790dfa889a1913199a6699a)
|
||||
- 🐞 修复 BackTop 在 KeepAlive 激活时,位置不对的问题 [#3803](https://github.com/vueComponent/ant-design-vue/issues/3803)
|
||||
- 🐞 修复 TreeNode class 不生效问题 [#3822](https://github.com/vueComponent/ant-design-vue/issues/3822)
|
||||
- 🐞 修复 Table tags 为数组时报错问题 [#3812](https://github.com/vueComponent/ant-design-vue/issues/3812)
|
||||
- 🐞 修复 Table 自定义 filterIcon 时,触发排序问题 [#3819](https://github.com/vueComponent/ant-design-vue/issues/3819)
|
||||
- 🐞 修复 Select 样式在 Form 下错位问题 [#3781](https://github.com/vueComponent/ant-design-vue/issues/3781)
|
||||
|
||||
## 2.0.1
|
||||
|
||||
`2021-02-27`
|
||||
|
||||
- 🌟 `Badge` 新增 `Ribbon` [#3681](https://github.com/vueComponent/ant-design-vue/issues/3681)
|
||||
- 🌟 调整 `SearchInput` search 事件触发顺序 [#3725](https://github.com/vueComponent/ant-design-vue/issues/3725)
|
||||
- 🐞 修复 `Table` 销毁时卡死问题 [#3531](https://github.com/vueComponent/ant-design-vue/issues/3531)
|
||||
- 🐞 修复 `Menu` css 中引入了 less 文件问题 [#3678](https://github.com/vueComponent/ant-design-vue/issues/3678)
|
||||
- 🐞 修复 `Alert` 自定义图标错位问题 [#3712](https://github.com/vueComponent/ant-design-vue/issues/3712)
|
||||
|
||||
## 2.0.0
|
||||
|
||||
`2021-02-06`
|
||||
|
||||
- 🎉🎉🎉 2.0 正式版发布
|
||||
- 🎉🎉🎉 支持暗黑主题 [#3410](https://github.com/vueComponent/ant-design-vue/issues/3410)
|
||||
- 🎉🎉🎉 新版文档上线,使用 Composition API 完全重构文档示例,提供 TS、JS 双版本源码
|
||||
- 🌟 使用 Composition API 重构 `Alert` 组件 [#3654](https://github.com/vueComponent/ant-design-vue/pull/3654)
|
||||
- 🌟 `Tooltip` 支持自定义颜色 [#3603](https://github.com/vueComponent/ant-design-vue/issues/3603)
|
||||
- 🐞 修复 `TimePicker` 没有自动滚动到已选位置问题 [#ab7537](https://github.com/vueComponent/ant-design-vue/commit/ab75379f0c2f5e54ab7c348284a7391939ab5aaf)
|
||||
|
||||
## 2.0.0-rc.9
|
||||
|
||||
`2021-01-24`
|
||||
|
||||
- 🌟 `@ant-design/icons-vue` 升级至 6.0,默认使用 es module
|
||||
- 🌟 `Tabs` 增加 `centered` 居中模式 [#3501](https://github.com/vueComponent/ant-design-vue/issues/3501)
|
||||
- 🐞 `Progress` 添加 opacity 动画 [#3505](https://github.com/vueComponent/ant-design-vue/issues/3505)
|
||||
- 🐞 修复 npm 安装时报错问题 [#3515](https://github.com/vueComponent/ant-design-vue/issues/3515)
|
||||
- 🐞 修复 `Breadcrumn` 分割线不显示问题 [#3522](https://github.com/vueComponent/ant-design-vue/issues/3522)
|
||||
- 🐞 修复 `Radio` 不受控问题 [#3517](https://github.com/vueComponent/ant-design-vue/issues/3517)
|
||||
- 🐞 修复 `FormItem` 不换行问题 [#3538](https://github.com/vueComponent/ant-design-vue/issues/3538)
|
||||
- 🐞 修复 `Carousel` `pauseOnDotsHover` 不生效问题 [#3519](https://github.com/vueComponent/ant-design-vue/issues/3519)
|
||||
- 🐞 修复 `Input.Search` `class` 不生效问题 [#3541](https://github.com/vueComponent/ant-design-vue/issues/3541)
|
||||
- 🐞 修复 `InputNumber` 在微软输入法下多次触发 change 事件问题 [#3550](https://github.com/vueComponent/ant-design-vue/issues/3550)
|
||||
- 🐞 修复 `Tabs` disabled 状态下依然可以通过键盘切换问题 [#3575](https://github.com/vueComponent/ant-design-vue/issues/3575)
|
||||
- 🐞 修复 `Switch` 在 table 中切换不生效问题 [#3512](https://github.com/vueComponent/ant-design-vue/issues/3512)
|
||||
|
||||
## 2.0.0-rc.8
|
||||
|
||||
`2021-01-07`
|
||||
|
||||
- 🌟 支持 Vite 2 [#3490](https://github.com/vueComponent/ant-design-vue/issues/3490)
|
||||
- 🌟 使用 Composition API 重构 Affix 组件 [#3447](https://github.com/vueComponent/ant-design-vue/issues/3447)
|
||||
- 🐞 修复 Image 组件类型定义错误 [#3488](https://github.com/vueComponent/ant-design-vue/issues/3488)
|
||||
- 🐞 升级 icons-vue 修复 IconFont 组件类型错误 [#3474](https://github.com/vueComponent/ant-design-vue/issues/3474)
|
||||
- 🐞 修复 less 4 下 Tooltip 箭头样式错误问题 [#3477](https://github.com/vueComponent/ant-design-vue/issues/3477)
|
||||
- 🐞 修复 Vue 3.0.5 下 DatePicker 类型定义解析错误问题 [#bf7c62](https://github.com/vueComponent/ant-design-vue/commit/bf7c62f457fc14624881f69c5baf9a62219383f7)
|
||||
|
||||
## 2.0.0-rc.7
|
||||
|
||||
`2020-12-28`
|
||||
|
||||
- 🐞 修复 Switch `change`、`click` 不生效问题 [#3453](https://github.com/vueComponent/ant-design-vue/issues/3453)
|
||||
|
||||
## 2.0.0-rc.6
|
||||
|
||||
`2020-12-27`
|
||||
|
||||
- 🌟 支持 Less 4 [#3449](https://github.com/vueComponent/ant-design-vue/issues/3449)
|
||||
- 🌟 新增 Image 组件 [#3235](https://github.com/vueComponent/ant-design-vue/issues/3235)
|
||||
- 🌟 函数式组件,添加 displayName 属性 [#3445](https://github.com/vueComponent/ant-design-vue/issues/3445)
|
||||
- 🐞 Message 新增自定义 class style 功能 [#3443](https://github.com/vueComponent/ant-design-vue/issues/3443)
|
||||
- 🐞 修复 Tabs 组件初始 disabled 状态没生效 [#3366](https://github.com/vueComponent/ant-design-vue/issues/3366)
|
||||
- 🐞 修复 Slider 精准度问题 [#3346](https://github.com/vueComponent/ant-design-vue/issues/3346)
|
||||
- 🐞 修复 Select 滚动高度不正确问题 [#3419](https://github.com/vueComponent/ant-design-vue/issues/3419)
|
||||
- 🐞 修复 Input small 大小时,高度偏大 2px 问题 [#3396](https://github.com/vueComponent/ant-design-vue/issues/3396)
|
||||
- 🐞 修复 TreeSelect 触发两次 change 事件问题
|
||||
- 🐞 修复 TreeSelect 通过 slot 定义 title 死循环问题
|
||||
- 🐞 修复 Drawer handle slot 触发两次 click 事件问题
|
||||
- 🌟 新增 Checkbox、Switch 事件声明
|
||||
|
||||
## 2.0.0-rc.5
|
||||
|
||||
`2020-12-13`
|
||||
|
||||
- 🐞 修复 Drawer 组件控制台输出 this.dom 未定义的 warning 问题
|
||||
- 🐞 修复 Menu 在 Vue 3.0.3 及以上版本,出现显示错乱问题 [#3354](https://github.com/vueComponent/ant-design-vue/issues/3354)
|
||||
|
||||
## 2.0.0-rc.4
|
||||
|
||||
`2020-12-10`
|
||||
|
||||
- 🌟 Input.Password 支持自定义图标 [#3320](https://github.com/vueComponent/ant-design-vue/issues/3320)
|
||||
- 🐞 修复 Select Option click 事件不触发问题 [#4ea00d](https://github.com/vueComponent/ant-design-vue/commit/4ea00d3a70d0afd7bea07f814df03ab7d0b25ebd)
|
||||
- 🐞 修复 Menu 超出宽度后 dark 主题不生效问题 [#10f35a](https://github.com/vueComponent/ant-design-vue/commit/10f35a1fa510de91e9484b07fcfff253920cee29)
|
||||
- 🐞 修复 Menu 控制台 vue key some waring [#520d6a](https://github.com/vueComponent/ant-design-vue/commit/520d6a5e85eb391e5294211c9d7b2ea598c59119)
|
||||
- 🐞 移除控制台 passive 提示日志 [#8d1669](https://github.com/vueComponent/ant-design-vue/commit/8d1669b8896d84a67c61d3a00d0b13c42d70f30f)
|
||||
|
||||
## 2.0.0-rc.3
|
||||
|
||||
`2020-12-05`
|
||||
|
||||
- 🐞 修复函数式组件在 Vue 3.0.3 下报类型错误问题 [#f5cf7e](https://github.com/vueComponent/ant-design-vue/commit/f5cf7e0920a51f0ac024046996c99260aa41becf)
|
||||
- 🐞 修复 Menu 超出宽度后显示错误问题 [#3262](https://github.com/vueComponent/ant-design-vue/issues/3262)
|
||||
- 🐞 修复 Menu subMenuOpenDelay subMenuCloseDelay 不生效问题 [#3291](https://github.com/vueComponent/ant-design-vue/pull/3291)
|
||||
- 🐞 修复 TreeSelect 堆栈溢出问题 [#28aeea](https://github.com/vueComponent/ant-design-vue/commit/28aeea6f0b142ed68950a3738f7cf2c1581a7a5b)
|
||||
- 🐞 修复 Input 自定义 style class 被覆盖问题 [#3273](https://github.com/vueComponent/ant-design-vue/issues/3273)
|
||||
- 🐞 修复 InputNumber 在生产环境下 parse 错误 [#3249](https://github.com/vueComponent/ant-design-vue/issues/3249)
|
||||
|
||||
## 2.0.0-rc.2
|
||||
|
||||
`2020-11-24`
|
||||
|
||||
- 🌟 优化 Menu 性能,默认开启懒加载 [#3243](https://github.com/vueComponent/ant-design-vue/pull/3243)
|
||||
- 🌟 Tag 支持通过 slot 定义 icon [#3185](https://github.com/vueComponent/ant-design-vue/pull/3185)
|
||||
- 🌟 small 类型的 table 改成无边框 [#3221](https://github.com/vueComponent/ant-design-vue/issues/3221)
|
||||
- 🌟 @ant-design/icons-vue 升级到 5.1.6,支持 SSR,支持 spin 属性简写
|
||||
- 🐞 修复 Alert 的关闭按钮在 Safari 下样式问题 [#3184](https://github.com/vueComponent/ant-design-vue/issues/3184)
|
||||
- 🐞 修复 Notification top 属性类型错误问题 [#3187](https://github.com/vueComponent/ant-design-vue/issues/3187)
|
||||
- 🐞 修复 DirectoryTree 自定义图标不生效问题 [#3183](https://github.com/vueComponent/ant-design-vue/issues/3183)
|
||||
- 🐞 修复 Button loading delay 不生效问题 [#3194](https://github.com/vueComponent/ant-design-vue/issues/3194)
|
||||
- 💄 Select optionFilterProp 不在支持按照 children 来过滤 [#3204](https://github.com/vueComponent/ant-design-vue/issues/3204)
|
||||
- 🐞 修复 Select labelInValue 时报错问题 [#3216](https://github.com/vueComponent/ant-design-vue/issues/3216)
|
||||
- 🐞 修复 ConfigProvider transformCellText 丢失问题 [#3206](https://github.com/vueComponent/ant-design-vue/issues/3206)
|
||||
- 🐞 修复 Dropdown Button 混合使用时,样式错乱问题 [#3244](https://github.com/vueComponent/ant-design-vue/issues/3244)
|
||||
- 🐞 修复 RangePicker 自定义宽度失效问题 [#3244](https://github.com/vueComponent/ant-design-vue/issues/3245)
|
||||
- 🐞 修复多处 Ts 类型错误或缺失问题
|
||||
|
||||
## 2.0.0-rc.1
|
||||
|
||||
`2020-11-14`
|
||||
|
||||
- 🎉🎉🎉
|
||||
- 🌟 Menu 取消默认懒加载,提升首次动画效果,优化贝塞尔曲线函数,更加流畅 [#3177](https://github.com/vueComponent/ant-design-vue/pull/3177)
|
||||
- 🐞 修复 Select 搜索功能失效问题 [#3144](https://github.com/vueComponent/ant-design-vue/issues/3144)
|
||||
- 🐞 修复 Drawer 组件没有自动 focus,导致不能直接通过 ESC 按键关闭 [#3148](https://github.com/vueComponent/ant-design-vue/issues/3148)
|
||||
- 🐞 修复 Popover 弹出元素位置不正确问题 [#3147](https://github.com/vueComponent/ant-design-vue/issues/3147)
|
||||
- 🐞 修复 CountDown 不更新问题 [#3170](https://github.com/vueComponent/ant-design-vue/pull/3170)
|
||||
- 🐞 修复多处 Ts 类型错误或缺失问题
|
||||
|
||||
## 2.0.0-beta.15
|
||||
|
||||
`2020-11-08`
|
||||
|
||||
- 🌟 优化 Menu 动画,更加流畅 [#3095](https://github.com/vueComponent/ant-design-vue/issues/3095)
|
||||
- 🌟 优化 VirtualList,避免无效 render [#2e61e9](https://github.com/vueComponent/ant-design-vue/commit/2e61e9cb502f2bb6910f59abfb483fd2517e594f)
|
||||
- 🐞 修复 Menu overflowedIndicator 未生效问题 [#689113](https://github.com/vueComponent/ant-design-vue/commit/689113b3c9c19e929607567a4c8252c6511bff5c)
|
||||
- 🐞 Select
|
||||
- 修复 dropdownRender 不支持 slot 问题 [#3098](https://github.com/vueComponent/ant-design-vue/issues/3098)
|
||||
- 修复 tag 模式下,空值异常问题 [#3100](https://github.com/vueComponent/ant-design-vue/issues/3100)
|
||||
- 修复单选模式下选择项不更新问题 [#3099](https://github.com/vueComponent/ant-design-vue/issues/3099)
|
||||
- 修复特殊场景下 foucs 状态不生效问题 [#3099](https://github.com/vueComponent/ant-design-vue/issues/3099)
|
||||
- 🐞 修复 DatePicker 默认格式化失效问题 [#3091](https://github.com/vueComponent/ant-design-vue/issues/3091)
|
||||
- 🐞 修复 Table customRow 配置事件不生效问题 [#3121](https://github.com/vueComponent/ant-design-vue/issues/3121)
|
||||
- 🐞 修复 TreeSelect 搜索框样式错乱问题 [ee4cd3c](https://github.com/vueComponent/ant-design-vue/commit/ ee4cd3c35a84658cbbb148ce368bc247a927d528)
|
||||
- 🐞 修复 Ts 类型错误或缺失问题
|
||||
|
||||
## 2.0.0-beta.13
|
||||
|
||||
`2020-11-02`
|
||||
|
||||
- 🐞 修复 npm install 报错问题 [#3080](https://github.com/vueComponent/ant-design-vue/issues/3080)
|
||||
- 🐞 修复 Select maxPlaceHolder 显示错误问题 [#3085](https://github.com/vueComponent/ant-design-vue/issues/3085)
|
||||
- 🐞 修复弹窗类组件,弹出位置不更新问题 [#3085](https://github.com/vueComponent/ant-design-vue/issues/3085)
|
||||
- 🐞 修复 Table 数据为空时的 warning 问题 [#3082](https://github.com/vueComponent/ant-design-vue/issues/3082)
|
||||
- 🐞 修复 Input 在 Form 中显示多个边框问题 [#3084](https://github.com/vueComponent/ant-design-vue/issues/3084)
|
||||
|
||||
## 2.0.0-beta.12
|
||||
|
||||
`2020-11-01`
|
||||
|
||||
- 🐞 修复 dist/antd.css 缺失组件样式问题 [#3069](https://github.com/vueComponent/ant-design-vue/issues/3069)
|
||||
- 🐞 修复 Input 样式问题 [#3074](https://github.com/vueComponent/ant-design-vue/issues/3074)
|
||||
- 🐞 修复 Form layout="vertical" 样式问题 [#3075](https://github.com/vueComponent/ant-design-vue/issues/3075)
|
||||
- 🐞 修复 Select 无法打开弹窗问题 [#3070](https://github.com/vueComponent/ant-design-vue/issues/3070)
|
||||
|
||||
## 2.0.0-beta.11
|
||||
|
||||
`2020-10-30`
|
||||
|
||||
- 🎉🎉🎉 重构 Select、AutoComplete 组件,支持虚拟列表,性能大幅提升
|
||||
- 🔥🔥🔥 使用 Typescript 重构所有组件,类型支持更加友好
|
||||
- 🔥 优化底层动画组件,性能更好,更流畅
|
||||
- 🌟 Textarea 组件添加 showCount 支持统计字数功能
|
||||
- 🌟 递归 Menu 组件,支持任意嵌套其他元素 [#1452](https://github.com/vueComponent/ant-design-vue/issues/1452)
|
||||
- 🇮🇪 添加爱尔兰语国际化支持
|
||||
- 🐞 修复 webpack 5 兼容问题。
|
||||
- 🐞 修复 Upload method 属性不生效问题 [#2837](https://github.com/vueComponent/ant-design-vue/issues/2837)
|
||||
- 🐞 修复 Table 组件 filter 不支持 number 类型问题 [#3052](https://github.com/vueComponent/ant-design-vue/issues/3052)
|
||||
- 🐞 修复 Table 固定列 ellipsis 不生效问题 [#2916](https://github.com/vueComponent/ant-design-vue/issues/2916)
|
||||
- 🐞 修复 Table 自定义 expandIcon 不生效问题 [#3013](https://github.com/vueComponent/ant-design-vue/issues/3013)
|
||||
- 🐞 修复 TreeSelect 不能自定义 slot 问题 [#2827](https://github.com/vueComponent/ant-design-vue/issues/2827)
|
||||
- 🛎 更改 Avatar 的 srcSet 为 srcset
|
||||
|
||||
## 2.0.0-beta.10
|
||||
|
||||
`2020-09-24`
|
||||
|
||||
- 🌟 更新 Vue 依赖到 release 版本
|
||||
- 🐞 修复 Menu 在 Layout 中不折叠问题 [#2819](https://github.com/vueComponent/ant-design-vue/issues/2819)
|
||||
- 🐞 修复 Tabs 切换时出现 warning 问题 [#2865](https://github.com/vueComponent/ant-design-vue/issues/2865)
|
||||
- 🐞 修复输入框在 compositionend 时不触发 change 事件问题
|
||||
- 🐞 修复 Upload 上传按钮不消失问题 [#2884](https://github.com/vueComponent/ant-design-vue/issues/2884)
|
||||
- 🐞 修复 Upload 自定义 method 不生效问题 [#2837](https://github.com/vueComponent/ant-design-vue/issues/2837)
|
||||
- 🐞 修复若干 ts 类型错误
|
||||
|
||||
## 2.0.0-beta.8
|
||||
|
||||
- 🐞 修复 ts 类型错误
|
||||
|
||||
## 2.0.0-beta.7
|
||||
|
||||
- 🐞 修复 Descriptions Item 不支持 v-for 问题 [#2793](https://github.com/vueComponent/ant-design-vue/issues/2793)
|
||||
- 🐞 修复 Modal button loading 效果不生效问题 [9257c1](https://github.com/vueComponent/ant-design-vue/commit/9257c1ea685db4339239589153aee3189d0434fe)
|
||||
- 🐞 修复 Steps 组件使用 v-model 时不可点击的问题 [ec7309](https://github.com/vueComponent/ant-design-vue/commit/ec73097d9b6ea8e2f2942ac28853c19191ca3298)
|
||||
- 🌟 Checkbox、Radio 添加事件声明
|
||||
- 🐞 修复 ts 类型错误 [802446](https://github.com/vueComponent/ant-design-vue/commit/8024469b8832cfc4fe85498b639bfb48820531aa)
|
||||
|
||||
## 2.0.0-beta.6
|
||||
|
||||
- 🐞 修复 TreeSelectNode 子组件 TreeSelectNode 没有注册的问题
|
||||
|
||||
## 2.0.0-beta.5
|
||||
|
||||
- 🔥 支持 Vite。
|
||||
|
||||
## 2.0.0-beta.4
|
||||
|
||||
- 🌟 移除不再使用的 polyfill
|
||||
- 🐞 修复 `Modal` afterClose 调用两次的问题
|
||||
- 🐞 补充 ts 类型文件缺少原生属性的声明
|
||||
|
||||
## 2.0.0-beta.3
|
||||
|
||||
- 🔥 支持 Typescript。
|
||||
- 🔥 新增 `Space` 组件。
|
||||
- 🐞 修复部分组件无法使用 css scope 问题 [4bdb24](https://github.com/vueComponent/ant-design-vue/commit/4bdb241aa674b50fafa29b3b98e291643f2a06cc)。
|
||||
- 🐞 修复 `List.Meta` 注册失败的问题 [03a42a](https://github.com/vueComponent/ant-design-vue/commit/03a42a5b35e7d42a39aedb1aba8346995be2c27e)
|
||||
- 🐞 修复 `Table` 固定列情况下错位问题 [#1493](https://github.com/vueComponent/ant-design-vue/issues/1493)
|
||||
- 🐞 修复 `Button` 没有垂直居中的问题 [bd71e3](https://github.com/vueComponent/ant-design-vue/commit/bd71e3806b73881f9a95028982d17a10b2cd0b5c)
|
||||
- 🐞 修复 `Tabs` 多次出发 `change` 事件问题 [8ed937](https://github.com/vueComponent/ant-design-vue/commit/8ed937344a57142a575e5272f50933c9c4459a43)
|
||||
|
||||
## 2.0.0-beta.2
|
||||
|
||||
`2020-08-14`
|
||||
- 🌟 优化 layout 组件切换 dark 模式时 textColor 变化 [#7498](https://github.com/vueComponent/ant-design-vue/issues/7498)
|
||||
- 🌟 Tooltip 新增 arrow 隐藏配置 [#7459](https://github.com/vueComponent/ant-design-vue/issues/7459)
|
||||
- 🌟 优化 Table hover 性能 [#7451](https://github.com/vueComponent/ant-design-vue/issues/7451)
|
||||
- 🐞 修复 useForm 校验时更改 model,导致校验错误问题 [#ffd4d8](https://github.com/vueComponent/ant-design-vue/commit/ffd4d8fe927f9ea40cbb6358ad997c447bd9a74e)
|
||||
- 🐞 修复 Tabs 折叠计算错误问题 [#7491](https://github.com/vueComponent/ant-design-vue/issues/7491)
|
||||
- 🐞 修复 Qrcode 缺少类型提示问题 [#7502](https://github.com/vueComponent/ant-design-vue/issues/7502)
|
||||
- 🐞 修复 Menu 在 SSR 下渲染错误问题 [#7349](https://github.com/vueComponent/ant-design-vue/issues/7349)
|
||||
- 🐞 修复 Select、Cascader 在 SSR 下渲染错误问题 [#7377](https://github.com/vueComponent/ant-design-vue/issues/7377)
|
||||
- 🐞 修复 AutoComplete 缺少 option slot 声明问题 [#7396](https://github.com/vueComponent/ant-design-vue/issues/7396)
|
||||
- 🐞 修复 Textarea autoSize 不生效问题 [#7478](https://github.com/vueComponent/ant-design-vue/issues/7478)
|
||||
- 🐞 修复 Pagination 回车键触发两次翻页问题 [#7368](https://github.com/vueComponent/ant-design-vue/issues/7368)
|
||||
- 🐞 修复输入框输入中文问题 [#7391](https://github.com/vueComponent/ant-design-vue/issues/7391)[#7516](https://github.com/vueComponent/ant-design-vue/issues/7516)
|
||||
- 🐞 修复 Carousel beforeChange current 参数错误问题 [#7419](https://github.com/vueComponent/ant-design-vue/issues/7419)
|
||||
|
||||
## 4.1.2
|
||||
|
||||
- 🐞 修复 table resize 在 vue 3.4 下报错问题 [#7291](https://github.com/vueComponent/ant-design-vue/issues/7291)
|
||||
- 🐞 修复 Segmented title 属性不显示问题 [#7302](https://github.com/vueComponent/ant-design-vue/issues/7302)
|
||||
|
||||
## 4.1.1
|
||||
|
||||
- 🌟 QRcode 新增 scanned 状态 [#7242](https://github.com/vueComponent/ant-design-vue/issues/7242)
|
||||
- 🐞 修复 css prefix 在 nuxt 问题 [#7256](https://github.com/vueComponent/ant-design-vue/issues/7256)
|
||||
- 🐞 修复 dropdown 关闭问题 [#7246](https://github.com/vueComponent/ant-design-vue/issues/7246)
|
||||
- 🐞 修复 divider vertical dashed 不显示问题 [#7218](https://github.com/vueComponent/ant-design-vue/issues/7218)
|
||||
- 🐞 修复 hook 模式 message 控制台 warning 问题 [#7281](https://github.com/vueComponent/ant-design-vue/issues/7281)
|
||||
- 🐞 修复 table 展开在 vue 3.4 下报错问题 [#7265](https://github.com/vueComponent/ant-design-vue/issues/7265)
|
||||
- 🐞 修复 table group 过滤状态错误问题 [#7233](https://github.com/vueComponent/ant-design-vue/issues/7233)
|
||||
|
||||
## 4.1.0
|
||||
|
||||
- 🐞 适配 vue 3.4 [#7239](https://github.com/vueComponent/ant-design-vue/issues/7239)
|
||||
|
||||
## 4.0.8
|
||||
|
||||
- 🐞 修复在 Nuxt 下 theme 响应式失效问题 [#7180](https://github.com/vueComponent/ant-design-vue/issues/7180)
|
||||
- 🐞 修复 Wave 引起的报错问题 [#7108](https://github.com/vueComponent/ant-design-vue/issues/7108)
|
||||
- 🐞 修复 Upload disabled 继承问题 [#7110](https://github.com/vueComponent/ant-design-vue/issues/7110)
|
||||
- 🐞 修复 Tooltip popupAlign 未生效问题 [#7112](https://github.com/vueComponent/ant-design-vue/issues/7112)
|
||||
- 🐞 修复 Typography 闪动问题 [#7146](https://github.com/vueComponent/ant-design-vue/issues/7146)
|
||||
- 🐞 修复 RangePicker prevIcon nextIcon 未生效问题 [#7127](https://github.com/vueComponent/ant-design-vue/issues/7127)
|
||||
- 🐞 修复 watermark 未监听子元素变动问题 [#7149](https://github.com/vueComponent/ant-design-vue/issues/7149)
|
||||
- 🐞 修复 Menu 动画丢失问题 [#7130](https://github.com/vueComponent/ant-design-vue/issues/7130)
|
||||
- 🐞 修复 TextArea autosize 时光标变化问题 [#7121](https://github.com/vueComponent/ant-design-vue/issues/7121)
|
||||
|
||||
## 4.0.7
|
||||
|
||||
- 🌟 新增 Flex 组件 [#7052](https://github.com/vueComponent/ant-design-vue/issues/7052)
|
||||
- 🌟 ConfigProvider 新增 wave 配置 [#7036](https://github.com/vueComponent/ant-design-vue/issues/7036)
|
||||
- 🌟 Watermark 支持暗黑模式 [#7067](https://github.com/vueComponent/ant-design-vue/issues/7067)
|
||||
- 🐞 修复 Space 重复 Key 问题 [#7048](https://github.com/vueComponent/ant-design-vue/issues/7048)
|
||||
- 🐞 修复 Upload disabled 优先级错误问题 [#7047](https://github.com/vueComponent/ant-design-vue/issues/7047)
|
||||
- 🐞 修复 Carousel 在 jsx 中渲染错误问题 [#7077](https://github.com/vueComponent/ant-design-vue/issues/7077)
|
||||
- 🐞 修复 Message 偏移位置问题 [#7093](https://github.com/vueComponent/ant-design-vue/issues/7093)
|
||||
- 🐞 修复 Collapse 自定义 prefix 时动画失效问题 [#7074](https://github.com/vueComponent/ant-design-vue/issues/7074)
|
||||
|
||||
## 4.0.6
|
||||
|
||||
- 🐞 修复 4.0.4 引入的 Dropdown onVisibleChange 失效问题 [#7031](https://github.com/vueComponent/ant-design-vue/issues/7031)
|
||||
|
||||
## 4.0.5
|
||||
|
||||
- 🐞 修复 cssinjs 性能问题 [#7023](https://github.com/vueComponent/ant-design-vue/issues/7023)
|
||||
|
||||
## 4.0.4
|
||||
|
||||
- 🌟 新增 esm 目标文件
|
||||
- 🌟 FormItem 新增 tooltip 属性 [#7014](https://github.com/vueComponent/ant-design-vue/issues/7014)
|
||||
- 🐞 修复 useMessage getContainer 不生效问题 [#6942](https://github.com/vueComponent/ant-design-vue/issues/6942)
|
||||
- 🐞 修复 Image 多次触发 onPreviewVisibleChange 事件问题 [#6945](https://github.com/vueComponent/ant-design-vue/issues/6945)
|
||||
- 🐞 修复 Checkbox 全局 disabled 不生效问题 [#6970](https://github.com/vueComponent/ant-design-vue/issues/6970)
|
||||
- 🐞 修复 Drawer contentWrapperStyle 不生效问题 [#6983](https://github.com/vueComponent/ant-design-vue/issues/6983)
|
||||
- 🐞 优化 Select Dropdown 等下拉列表滚动条显示隐藏逻辑 [#6987](https://github.com/vueComponent/ant-design-vue/issues/6987)
|
||||
- 🐞 修复 Select Dropdown 等下拉列表中有 input 等组件时,隐藏问题 [#7020](https://github.com/vueComponent/ant-design-vue/issues/7020)
|
||||
|
||||
## 4.0.3
|
||||
|
||||
- 🐞 修复 shadow Dom 下样式丢失问题 [#6912](https://github.com/vueComponent/ant-design-vue/issues/6912)
|
||||
- 🐞 升级 Icon 依赖,修复 shadow Dom 下 icon css 丢失问题 [#6914](https://github.com/vueComponent/ant-design-vue/issues/6914)
|
||||
|
||||
## 4.0.2
|
||||
|
||||
- 🐞 修复 useMessage 导致 body 被移除问题 [#6880](https://github.com/vueComponent/ant-design-vue/issues/6880)
|
||||
- 🐞 修复 Button loading 切换后,水波纹效果不消失问题 [#6895](https://github.com/vueComponent/ant-design-vue/issues/6895)
|
||||
- 🐞 修复 Image 关闭后 flip 没有重置问题 [#6913](https://github.com/vueComponent/ant-design-vue/issues/6913)
|
||||
- 🐞 修复 ImageGroup 动画效果丢失问题 [#6898](https://github.com/vueComponent/ant-design-vue/issues/6898)
|
||||
- 🐞 修复 Modal 缺少 onUpdate:open 属性声明 [#6876](https://github.com/vueComponent/ant-design-vue/issues/6876)
|
||||
- 🐞 修复 Transfer 的 Checkbox 边缘处会触发多次 click 问题 [#6902](https://github.com/vueComponent/ant-design-vue/issues/6902)
|
||||
|
||||
## 4.0.1
|
||||
|
||||
- 🌟 FloatButton 添加 Badge 支持 [#6738](https://github.com/vueComponent/ant-design-vue/issues/6738)
|
||||
- 🌟 Image 预览放大缩小灵敏度调整 [#6784](https://github.com/vueComponent/ant-design-vue/issues/6784)
|
||||
- 🌟 Image 新增翻转特性 [#6785](https://github.com/vueComponent/ant-design-vue/issues/6785)
|
||||
- 🌟 新增 App 组件,用于提供上下文 [#6735](https://github.com/vueComponent/ant-design-vue/issues/6735)
|
||||
- 🌟 样式抽离特性用于 SSR [#6757](https://github.com/vueComponent/ant-design-vue/issues/6757)
|
||||
- 🌟 支持 px2rem [#6817](https://github.com/vueComponent/ant-design-vue/issues/6817)
|
||||
- 🌟 Tag 支持无边框模式 [#6819](https://github.com/vueComponent/ant-design-vue/issues/6819)
|
||||
- 🌟 Avatar group 模式支持 shape [#6822](https://github.com/vueComponent/ant-design-vue/issues/6822)
|
||||
- 🌟 AutoComplete 支持无边框和自定义 clearIcon [#6829](https://github.com/vueComponent/ant-design-vue/issues/6829)
|
||||
- 🌟 InputPassword 支持受控 visible [#6863](https://github.com/vueComponent/ant-design-vue/issues/6863)
|
||||
- 🐞 修复 InputGroup 在 large 时样式错位问题 [#6866](https://github.com/vueComponent/ant-design-vue/issues/6866)
|
||||
- 🐞 修复 Checkable Tag 无法自定义 class 问题 [#6854](https://github.com/vueComponent/ant-design-vue/issues/6854)
|
||||
- 🐞 修复 Tabs 动画模式下渲染问题 [#6855](https://github.com/vueComponent/ant-design-vue/issues/6855)
|
||||
- 🐞 修复 Image height 属性不生效问题 [#6840](https://github.com/vueComponent/ant-design-vue/issues/6840)
|
||||
- 🐞 修复 InputNumber 触发 mouseup 事件问题 [#6772](https://github.com/vueComponent/ant-design-vue/issues/6772)
|
||||
- 🐞 修复 Tabs 折叠时 Dropdown 样式问题 [#6757](https://github.com/vueComponent/ant-design-vue/issues/6757)
|
||||
- 🐞 修复 Table expandedRowRender 属性不生效 [#6783](https://github.com/vueComponent/ant-design-vue/issues/6783)
|
||||
- 🐞 修复 dayjs 未打包进 dist 问题 [#6767](https://github.com/vueComponent/ant-design-vue/issues/6767)
|
||||
- 🐞 解决 clipPath 浏览器兼容问题 [#6770](https://github.com/vueComponent/ant-design-vue/issues/6770)
|
||||
- 🐞 修复 Carousel autoplay 响应式问题 [#6768](https://github.com/vueComponent/ant-design-vue/issues/6768)
|
||||
- 🐞 修复 PageHeader ghost 样式问题 [#6761](https://github.com/vueComponent/ant-design-vue/issues/6761)
|
||||
- 🐞 修复 Checkbox 没有触发 Form 校验问题 [#6741](https://github.com/vueComponent/ant-design-vue/issues/6741)
|
||||
- 🐞 修复 Input prefix 属性未生效问题 [#6810](https://github.com/vueComponent/ant-design-vue/issues/6810)
|
||||
- 🐞 修复 Badge 在 Avatar 中样式问题 [#6874](https://github.com/vueComponent/ant-design-vue/issues/6874)
|
||||
|
||||
## 4.0
|
||||
|
||||
### 🔥🔥🔥 4.0 正式版发布 🔥🔥🔥
|
||||
|
||||
### 设计规范调整
|
||||
|
||||
- 行高从 `1.5`(`21px`) 调整为 `1.5715`(`22px`)。
|
||||
- 基础圆角调整,由`4px` 改为 `2px`。
|
||||
- 分割线颜色明度降低,由 `#E8E8E8` 改为 `#F0F0F0`。
|
||||
- Table 默认背景颜色从透明修改为白色。
|
||||
- 基础圆角调整,由统一的 `2px` 改为四级圆角,分别为 `2px` `4px` `6px` `8px`,分别应用于不同场景,比如默认尺寸的 Button 的圆角调整为了 `6px`。
|
||||
- 主色调整,由 `#1890ff` 改为 `#1677ff`。
|
||||
- 整体阴影调整,由原本的三级阴影调整为两级,分别用于常驻页面的组件(如 Card)和交互反馈(如 Dropdown)。
|
||||
- 部分组件内间距调整。
|
||||
- 整体去线框化。
|
||||
|
||||
### 兼容性调整
|
||||
### 新增 5 个组件
|
||||
|
||||
- Vue 最低支持版本为 Vue 3.0。
|
||||
- Segmented 分段控制器
|
||||
- WaterMark 水印
|
||||
- QrCode 二维码
|
||||
- FloatButton 悬浮按钮
|
||||
- Tour 漫游式引导
|
||||
|
||||
#### 调整的 API
|
||||
### 技术调整
|
||||
|
||||
- 移除了 LocaleProvider,请使用 `ConfigProvider` 替代。
|
||||
- 移除了 Tag 的 afterClose 属性。
|
||||
- 合并了 FormModel、Form,详见下方的 Form 重构部分。
|
||||
- `tabIndex`、`maxLength`、`readOnly`、`autoComplete`、`autoFocus` 更改为全小写。
|
||||
- 为了在 template 语法中更友好的使用插槽,所有涉及到 xxxRender, renderXxxx 的均改成单参数,涉及到 `itemRender`、`renderItem`、`customRender`、`dropdownRender`、`dateCellRender`、`dateFullCellRender`、`monthCellRender`、`monthFullCellRender`、`renderTabBar`。
|
||||
- 所有配置 scopedSlots 的地方统一改成 slots。
|
||||
- `{ on, props, attrs, ... }` 配置进行扁平化处理,如 `{ props: {type: 'xxx'}, on: {click: this.handleClick}}` 改成 `{ type: 'xxx', onClick: this.handleClick }`, 涉及相关字段:`okButtonProps`、`cancelButtonProps`。
|
||||
- xxx.sync 改成 v-model:xxx
|
||||
- v-model 更改成 v-model:xxx,具体涉及组件:
|
||||
- 弃用 less,采用 CSS-in-JS,更好地支持动态主题。
|
||||
- 所有 less 文件全部移除,less 变量不再支持透出。
|
||||
- 产物中不再包含 css 文件。由于 CSS-in-JS 支持按需引入,原本的 `ant-design-vue/dist/antd.css` 也已经移除,如果需要重置一些基本样式请引入 `ant-design-vue/dist/reset.css`。
|
||||
- 如果需要组件重置样式,又不想引入 `ant-design-vue/dist/reset.css` 从而导致污染全局样式的话,可以尝试在应用最外层使用[App 组件](/components/app-cn),解决原生元素没有 ant-design-vue 规范样式的问题。
|
||||
- 移除 css variables 以及在此之上构筑的动态主题方案。
|
||||
- LocaleProvider 在 3.x 中已经废弃(使用 `<ConfigProvider locale />` 替代),我们在 4.x 里彻底移除了相关目录 `ant-design-vue/es/locale-provider`、`ant-design-vue/lib/locale-provider`。
|
||||
- 不再支持 `babel-plugin-import`,CSS-in-JS 本身具有按需加载的能力,不再需要插件支持。
|
||||
|
||||
- v-model 改成 v-model:checked 的组件有: CheckableTag、Checkbox、Switch
|
||||
- v-model 改成 v-model:value 的组件有: Radio、Mentions、CheckboxGroup、Rate、DatePicker
|
||||
- v-model 改成 v-model:visible 的组件有: Tag、Popconfirm、Popove、Tooltip、Moda、Dropdown
|
||||
- v-model 改成 v-model:activeKey 的组件有: Collaps、Tabs
|
||||
- v-model 改成 v-model:current 的组件有: Steps
|
||||
- v-model 改成 v-model:selectedKeys 的组件有: Menu
|
||||
#### 组件 API 调整
|
||||
|
||||
#### 图标升级
|
||||
- 组件弹框的 classname API 统一为 `popupClassName`,`dropdownClassName` 等类似 API 都会被替换。
|
||||
|
||||
在 `ant-design-vue@1.2.0` 中,我们引入了 svg 图标([为何使用 svg 图标?](https://github.com/ant-design/ant-design/issues/10353))。使用了字符串命名的图标 API 无法做到按需加载,因而全量引入了 svg 图标文件,这大大增加了打包产物的尺寸。在 2.0 中,我们调整了图标的使用 API 从而支持 tree shaking,减少默认包体积约 150 KB(Gzipped)。
|
||||
- AutoComplete 组件
|
||||
- Cascader 组件
|
||||
- Select 组件
|
||||
- TreeSelect 组件
|
||||
- TimePicker 组件
|
||||
- DatePicker 组件
|
||||
- Mentions 组件
|
||||
|
||||
旧版 Icon 使用方式将被废弃:
|
||||
- 组件弹框的受控可见 API 统一为 `open`,`visible` 等类似 API 都会被替换。
|
||||
- Drawer 组件 `visible` 变为 `open`。
|
||||
- Modal 组件 `visible` 变为 `open`。
|
||||
- Dropdown 组件 `visible` 变为 `open`。
|
||||
- Tooltip 组件 `visible` 变为 `open`。
|
||||
- Tag 组件 `visible` 已移除。
|
||||
- Slider 组件 `tooltip` 相关 API 收敛到 `tooltip` 属性中。
|
||||
- Table 组件 `filterDropdownVisible` 变为 `filterDropdownOpen`。
|
||||
- `getPopupContainer`: 所有的 `getPopupContainer` 都需要保证返回的是唯一的 div。
|
||||
- Drawer `style` 和 `class` 迁移至 Drawer 弹层区域上,原属性替换为 `rootClassName` 和 `rootStyle`。
|
||||
|
||||
```html
|
||||
<a-icon type="smile" />
|
||||
<a-button icon="smile" />
|
||||
```
|
||||
#### 组件重构与移除
|
||||
|
||||
2.0 中会采用按需引入的方式:
|
||||
- 移除 `locale-provider` 目录。`LocaleProvider` 在 v4 中已移除,请使用 `ConfigProvider` 替代。
|
||||
|
||||
```html
|
||||
<template>
|
||||
<smile-outlined />
|
||||
<a-button>
|
||||
<template v-slot:icon><smile-outlined /></template>
|
||||
</a-buttom>
|
||||
</template>
|
||||
<script>
|
||||
import SmileOutlined from '@ant-design/icons-vue/SmileOutlined';
|
||||
export default {
|
||||
components: {
|
||||
SmileOutlined
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
- 移除栅格布局中的`xxxl`断点属性。 `xxxl`属性已经在 v4 被移除,您可以使用 [主题定制](/docs/vue/customize-theme-cn) 修改 `screen[XS|SM|MD|LG|XL|XXL]` 来修改断点值实现。
|
||||
|
||||
#### 组件重构
|
||||
- BackTop 组件在 `4.0.0` 中废弃,移至 FloatButton 悬浮按钮中。如需使用,可以从 FloatButton 中引入。
|
||||
|
||||
在 1.x 中我们提供了 Form、FormModel 两个表单组件,原有的 Form 组件使用 v-decorator 进行数据绑定,在 Vue2 中我们通过上下文进行强制更新组件,但是在 Vue3 中,由于引入 patchFlag 等优化方式,强制刷新会破坏 patchFlag 带来的性能优势。所以在 2.0 版本中我们将 Form、FormModel 进行合并,保留了 FormModel 的使用方式,丰富了相关功能,并改名成 Form。
|
||||
### [升级指南](/docs/vue/migration-v4-cn)
|
||||
|
||||
涉及改动:
|
||||
## 3.x
|
||||
|
||||
- Form 新增 `scrollToFirstError`,`name`,`validateTrigger` 属性,新增 `finish`、`finishFailed` 事件,新增 `scrollToField` 方法。
|
||||
- Form.Item 新增 `validateFirst`, `validateTrigger`, 废弃 `prop` 属性,使用 `name` 替换。
|
||||
- 嵌套字段路径使用数组,过去版本我们通过 . 代表嵌套路径(诸如 user.name 来代表 { user: { name: '' } })。然而在一些后台系统中,变量名中也会带上 .。这造成用户需要额外的代码进行转化,因而新版中,嵌套路径通过数组来表示以避免错误的处理行为(如 ['user', 'name'])。
|
||||
- validateFields 不再支持 callback。validateFields 会返回 Promise 对象,因而你可以通过 async/await 或者 then/catch 来执行对应的错误处理。不再需要判断 errors 是否为空:
|
||||
去 [GitHub](https://github.com/vueComponent/ant-design-vue/blob/3.x/CHANGELOG.zh-CN.md) 查看 `3.x` 的 Change Log。
|
||||
|
||||
```js
|
||||
// v1
|
||||
// eslint-disable-next-line no-undef,no-unused-vars
|
||||
validateFields((err, value) => {
|
||||
if (!err) {
|
||||
// Do something with value
|
||||
}
|
||||
});
|
||||
```
|
||||
## 2.x
|
||||
|
||||
改成
|
||||
|
||||
```js
|
||||
// v2
|
||||
// eslint-disable-next-line no-undef,no-unused-vars
|
||||
validateFields().then(values => {
|
||||
// Do something with value
|
||||
});
|
||||
```
|
||||
去 [GitHub](https://github.com/vueComponent/ant-design-vue/blob/2.x/CHANGELOG.zh-CN.md) 查看 `2.x` 的 Change Log。
|
||||
|
||||
## 1.x
|
||||
|
||||
|
|
22
LICENSE
22
LICENSE
|
@ -44,3 +44,25 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019-PRESENT Anthony Fu<https://github.com/antfu>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<p align="center">
|
||||
<a href="https://www.antdv.com/">
|
||||
<img width="200" src="https://qn.antdv.com/logo.png">
|
||||
<img width="200" src="https://aliyuncdn.antdv.com/logo.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
|||
|
||||
<div align="center">
|
||||
|
||||
An enterprise-class UI components based on Ant Design and Vue 3.
|
||||
基于 Ant Design 和 Vue 3 的企业级 UI 组件库。
|
||||
|
||||
 [](https://codecov.io/gh/vueComponent/ant-design-vue) [](https://www.npmjs.org/package/ant-design-vue) [](http://www.npmtrends.com/ant-design-vue) [](#backers) [](#sponsors) [](https://marketplace.visualstudio.com/items?itemName=ant-design-vue.vscode-ant-design-vue-helper) [](https://github.com/actions-cool/issues-helper)
|
||||
|
||||
|
@ -26,6 +26,12 @@ An enterprise-class UI components based on Ant Design and Vue 3.
|
|||
- 开箱即用的高质量 Vue 组件。
|
||||
- 共享 [Ant Design of React](http://ant-design.gitee.io/docs/spec/introduce-cn) 设计工具体系。
|
||||
|
||||
## 关注我们
|
||||
|
||||
收藏加关注,第一时间获取更新动态!
|
||||
|
||||

|
||||
|
||||
## 支持环境
|
||||
|
||||
- 现代浏览器。1.x 版本支持 IE 9+(需要 [polyfills](https://www.antdv.com/docs/vue/getting-started-cn/#兼容性))
|
||||
|
@ -65,6 +71,9 @@ $ yarn add ant-design-vue
|
|||
| [ant-design-vue-helper](https://marketplace.visualstudio.com/items?itemName=ant-design-vue.vscode-ant-design-vue-helper) | ant-design-vue 的 vscode 扩展 |
|
||||
| [vue-cli-plugin-ant-design](https://github.com/vueComponent/vue-cli-plugin-ant-design) | 使用 vue-cli3 快速使用 ant-design-vue 组件库 |
|
||||
| [vue-dash-event](https://github.com/vueComponent/vue-dash-event) | 在 DOM 模板中,您可以使用 ant-design-vue 组件的自定义事件(camelCase) |
|
||||
| [@formily/antdv](https://github.com/formilyjs/antdv) | 这是一个结合了 Formily 和 ant-design-vue 的组件库 |
|
||||
| [@ant-design-vue/nuxt](https://github.com/vueComponent/ant-design-vue-nuxt) | ant-design-vue 的 nuxt 模块扩展 |
|
||||
| [ant-design-x-vue](https://github.com/wzc520pyfm/ant-design-x-vue) | 基于 Ant Design X 设计规范的 Vue AI 界面解决方案 |
|
||||
|
||||
## 问答
|
||||
|
||||
|
@ -79,24 +88,33 @@ ant-design-vue 是 MIT 协议的开源项目。为了项目能够更好的持续
|
|||
- [Patreon](https://www.patreon.com/tangjinzhou)
|
||||
- [opencollective](https://opencollective.com/ant-design-vue)
|
||||
- [paypal](https://www.paypal.me/tangjinzhou)
|
||||
- [支付宝或微信](https://qn.antdv.com/alipay-and-wechat.png)
|
||||
- [支付宝或微信](https://aliyuncdn.antdv.com/alipay-and-wechat.png)
|
||||
- ETH: 0x30cc48515d8ae9fefa20ab87226ad7e8ab9c3bc2
|
||||
|
||||
## Sponsors
|
||||
## 赞助商
|
||||
|
||||
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/ant-design-vue#sponsor)]
|
||||
成为赞助商,并在 Github 上的自述文件上获得您的徽标,并链接到您的网站。 [[成为赞助商](https://opencollective.com/ant-design-vue#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/ant-design-vue/sponsor/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/0/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/1/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/2/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/2/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/3/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/3/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/4/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/4/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/5/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/5/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/6/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/6/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/7/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/7/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/8/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/8/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/9/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/10/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/10/avatar.svg"></a>
|
||||
<a href="http://www.jeecg.com/" target="_blank"><img src="https://aliyuncdn.antdv.com/jeecg-logo.png" height="64"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/0/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/1/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/2/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/2/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/3/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/3/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/4/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/4/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/5/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/5/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/6/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/6/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/7/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/7/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/8/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/8/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/9/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/10/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/10/avatar.svg"></a>
|
||||
|
||||
## Backers
|
||||
## 支持者
|
||||
|
||||
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/ant-design-vue#backer)]
|
||||
每月捐款支持我们,帮助我们继续我们的活动。 [[成为支持者](https://opencollective.com/ant-design-vue#backer)]
|
||||
|
||||
<a href="https://github.com/chuzhixin/vue-admin-beautiful" target="_blank"><img width="64" style="border-radius: 50%;" src="https://gitee.com/chu1204505056/image/raw/master/vue-admin-beautiful.png" title="vue-admin-beautiful"></a> <a href="https://opencollective.com/ant-design-vue/backer/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/0/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/1/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/2/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/2/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/3/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/3/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/4/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/4/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/5/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/5/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/6/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/6/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/7/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/7/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/8/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/8/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/9/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/10/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/10/avatar.svg"></a>
|
||||
|
||||
## Patreon
|
||||
|
||||
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://www.patreon.com/tangjinzhou)]
|
||||
每月捐款支持我们,帮助我们继续我们的活动。 [[成为支持者](https://www.patreon.com/tangjinzhou)]
|
||||
|
||||
<a href="https://www.mokeyjay.com" target="_blank"><img width="64" style="border-radius: 50%;" src="https://www.mokeyjay.com/headimg.png" title="donation by Patreon"></a>
|
||||
|
||||
## [更多赞助者 (通过 Patreon、支付宝、微信、paypal 等等)](https://github.com/vueComponent/ant-design-vue/blob/master/BACKERS.md)
|
||||
|
||||
## 贡献者
|
||||
|
||||
感谢所有为 ant-design-vue 做出贡献的人!
|
||||
|
||||
<a href="https://github.com/vueComponent/ant-design-vue/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=vueComponent/ant-design-vue&max=100&columns=15" />
|
||||
</a>
|
||||
|
|
44
README.md
44
README.md
|
@ -1,6 +1,6 @@
|
|||
<p align="center">
|
||||
<a href="https://www.antdv.com/">
|
||||
<img width="200" src="https://qn.antdv.com/logo.png">
|
||||
<img width="200" src="https://aliyuncdn.antdv.com/logo.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
@ -26,9 +26,15 @@ English | [简体中文](./README-zh_CN.md)
|
|||
- A set of high-quality Vue components out of the box.
|
||||
- Shared [Ant Design of React](https://ant.design/docs/spec/introduce) design resources.
|
||||
|
||||
## Getting started & staying tuned with us.
|
||||
|
||||
Star us, and you will receive all releases notifications from GitHub without any delay!
|
||||
|
||||

|
||||
|
||||
## Environment Support
|
||||
|
||||
- Modern browsers. v1.x support Internet Explorer 9+ (with [polyfills](https://www.antdv.com/docs/vue/getting-started/#Compatibility))
|
||||
- Modern browsers. v1.x support Internet Explorer 9+ (with [polyfills](https://www.antdv.com/docs/vue/getting-started/#compatibility))
|
||||
- Server-side Rendering
|
||||
- Support Vue 2 & Vue 3
|
||||
- [Electron](https://electronjs.org/)
|
||||
|
@ -39,7 +45,7 @@ English | [简体中文](./README-zh_CN.md)
|
|||
|
||||
## Using npm or yarn
|
||||
|
||||
**We recommend using npm or yarn to install**,it not only makes development easier,but also allow you to take advantage of the rich ecosystem of Javascript packages and tooling.
|
||||
**We recommend using npm or yarn to install**, it not only makes development easier, but also allow you to take advantage of the rich ecosystem of Javascript packages and tooling.
|
||||
|
||||
```bash
|
||||
$ npm install ant-design-vue --save
|
||||
|
@ -49,7 +55,7 @@ $ npm install ant-design-vue --save
|
|||
$ yarn add ant-design-vue
|
||||
```
|
||||
|
||||
If you are in a bad network environment,you can try other registries and tools like [cnpm](https://github.com/cnpm/cnpm).
|
||||
If you are in a bad network environment, you can try other registries and tools like [cnpm](https://github.com/cnpm/cnpm).
|
||||
|
||||
## Links
|
||||
|
||||
|
@ -65,6 +71,9 @@ If you are in a bad network environment,you can try other registries and tools
|
|||
| [ant-design-vue-helper](https://marketplace.visualstudio.com/items?itemName=ant-design-vue.vscode-ant-design-vue-helper) | A vscode extension for ant-design-vue |
|
||||
| [vue-cli-plugin-ant-design](https://github.com/vueComponent/vue-cli-plugin-ant-design) | Vue-cli 3 plugin to add ant-design-vue |
|
||||
| [vue-dash-event](https://github.com/vueComponent/vue-dash-event) | The library function, implemented in the DOM template, can use the custom event of the ant-design-vue component (camelCase) |
|
||||
| [@formily/antdv](https://github.com/formilyjs/antdv) | The Library with Formily and ant-design-vue |
|
||||
| [@ant-design-vue/nuxt](https://github.com/vueComponent/ant-design-vue-nuxt) | A nuxt module for ant-design-vue |
|
||||
| [ant-design-x-vue](https://github.com/wzc520pyfm/ant-design-x-vue) | A Vue AI interface solutions base on the Ant Design X design specification |
|
||||
|
||||
## Donation
|
||||
|
||||
|
@ -73,26 +82,25 @@ ant-design-vue is an MIT-licensed open source project. In order to achieve bette
|
|||
- [Patreon](https://www.patreon.com/tangjinzhou)
|
||||
- [opencollective](https://opencollective.com/ant-design-vue)
|
||||
- [paypal](https://www.paypal.me/tangjinzhou)
|
||||
- [支付宝或微信](https://qn.antdv.com/alipay-and-wechat.png)
|
||||
- [支付宝或微信](https://aliyuncdn.antdv.com/alipay-and-wechat.png)
|
||||
- ETH: 0x30cc48515d8ae9fefa20ab87226ad7e8ab9c3bc2
|
||||
|
||||
## Sponsors
|
||||
|
||||
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/ant-design-vue#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/ant-design-vue/sponsor/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/0/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/1/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/2/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/2/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/3/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/3/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/4/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/4/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/5/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/5/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/6/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/6/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/7/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/7/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/8/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/8/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/9/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/10/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/10/avatar.svg"></a>
|
||||
|
||||
## Backers
|
||||
|
||||
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/ant-design-vue#backer)]
|
||||
|
||||
<a href="https://github.com/chuzhixin/vue-admin-beautiful" target="_blank"><img width="64" style="border-radius: 50%;" src="https://gitee.com/chu1204505056/image/raw/master/vue-admin-beautiful.png" title="vue-admin-beautiful"></a> <a href="https://opencollective.com/ant-design-vue/backer/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/0/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/1/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/2/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/2/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/3/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/3/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/4/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/4/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/5/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/5/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/6/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/6/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/7/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/7/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/8/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/8/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/9/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/10/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/10/avatar.svg"></a><a href="https://opencollective.com/ant-design-vue/backer/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/9/avatar.svg"></a>
|
||||
|
||||
## Patreon
|
||||
|
||||
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://www.patreon.com/tangjinzhou)]
|
||||
|
||||
<a href="https://www.mokeyjay.com" target="_blank"><img width="64" style="border-radius: 50%;" src="https://www.mokeyjay.com/headimg.png" title="donation by Patreon"></a>
|
||||
<a href="http://www.jeecg.com/" target="_blank"><img src="https://aliyuncdn.antdv.com/jeecg-logo.png" height="64"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/0/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/1/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/2/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/2/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/3/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/3/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/4/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/4/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/5/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/5/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/6/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/6/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/7/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/7/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/8/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/8/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/9/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/sponsor/10/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/sponsor/10/avatar.svg"></a>
|
||||
|
||||
## [More Sponsor (From Patreon、alipay、wechat、paypal...)](https://github.com/vueComponent/ant-design-vue/blob/master/BACKERS.md)
|
||||
|
||||
## Contributors
|
||||
|
||||
Thank you to all the people who already contributed to ant-design-vue!
|
||||
|
||||
<a href="https://github.com/vueComponent/ant-design-vue/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=vueComponent/ant-design-vue&max=100&columns=15" />
|
||||
</a>
|
||||
|
||||
[](https://issuehunt.io/repos/104172832)
|
||||
|
||||
This project is tested with BrowserStack.
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Use this section to tell people about which versions of your project are currently being supported with security updates.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.x | :white_check_mark: |
|
||||
| 2.x | :x: |
|
||||
| 3.x | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Use this section to tell people how to report a vulnerability.
|
||||
|
||||
Tell them where to go, how often they can expect to get an update on a reported vulnerability, what to expect if the vulnerability is accepted or declined, etc.
|
|
@ -0,0 +1,68 @@
|
|||
// Read all the api from current documents
|
||||
|
||||
const glob = require('glob');
|
||||
const fs = require('fs');
|
||||
|
||||
const COMPONENT_NAME = /components\/([^/]*)/;
|
||||
const PROP_NAME = /^\s*\|\s*([^\s|]*)/;
|
||||
|
||||
const components = {};
|
||||
|
||||
function mappingPropLine(component, line) {
|
||||
const propMatch = line.match(PROP_NAME);
|
||||
if (!propMatch) return;
|
||||
|
||||
const propName = propMatch[1];
|
||||
if (!/^[a-z]/.test(propName)) return;
|
||||
|
||||
components[component] = Array.from(new Set([...(components[component] || []), propName]));
|
||||
}
|
||||
|
||||
function apiReport(entities) {
|
||||
const apis = {};
|
||||
Object.keys(entities).forEach(component => {
|
||||
const apiList = entities[component];
|
||||
apiList.forEach(api => {
|
||||
if (typeof apis[api] === 'function') {
|
||||
apis[api] = [];
|
||||
}
|
||||
apis[api] = [...(apis[api] || []), component];
|
||||
});
|
||||
});
|
||||
|
||||
return apis;
|
||||
}
|
||||
|
||||
function printReport(apis) {
|
||||
const apiList = Object.keys(apis).map(api => ({
|
||||
name: api,
|
||||
componentList: apis[api],
|
||||
}));
|
||||
apiList.sort((a, b) => b.componentList.length - a.componentList.length);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('| name | components | comments |');
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('| ---- | ---------- | -------- |');
|
||||
apiList.forEach(({ name, componentList }) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('|', name, '|', componentList.join(', '), '| |');
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = () => {
|
||||
glob('components/*/*.md', (error, files) => {
|
||||
files.forEach(filePath => {
|
||||
// Read md file to parse content
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
const component = filePath.match(COMPONENT_NAME)[1];
|
||||
|
||||
// Parse lines to get API
|
||||
const lines = content.split(/[\r\n]+/);
|
||||
lines.forEach(line => {
|
||||
mappingPropLine(component, line);
|
||||
});
|
||||
});
|
||||
|
||||
printReport(apiReport(components));
|
||||
});
|
||||
};
|
|
@ -4,7 +4,6 @@
|
|||
'use strict';
|
||||
|
||||
require('colorful').colorful();
|
||||
require('colorful').isatty = true;
|
||||
const gulp = require('gulp');
|
||||
const program = require('commander');
|
||||
|
||||
|
|
|
@ -3,18 +3,21 @@ const pkg = require('../../package.json');
|
|||
const { parseAndWrite } = require('./lib/index.js');
|
||||
const rootPath = path.resolve(__dirname, '../../');
|
||||
|
||||
try {
|
||||
parseAndWrite({
|
||||
version: pkg.version,
|
||||
name: 'types',
|
||||
path: path.resolve(rootPath, './v2-doc/src/docs'),
|
||||
name: 'ant-design-vue',
|
||||
path: path.resolve(rootPath, './components'),
|
||||
typingsPath: path.resolve(rootPath, './typings/global.d.ts'),
|
||||
// default match lang
|
||||
test: /en-US\.md/,
|
||||
outputDir: path.resolve(rootPath, './vetur'),
|
||||
tagPrefix: 'a-',
|
||||
});
|
||||
})
|
||||
.then(result => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('generator types success');
|
||||
} catch (e) {
|
||||
console.error('generator types error', e);
|
||||
}
|
||||
console.log(`generator types success: ${result} tags generated`);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('generator types error', error);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
|
|
@ -34,14 +34,19 @@ function parserProps(tag: VueTag, line: any) {
|
|||
});
|
||||
}
|
||||
|
||||
export function formatter(articals: Articals, componentName: string, tagPrefix = '') {
|
||||
export function formatter(
|
||||
articals: Articals,
|
||||
componentName: string,
|
||||
kebabComponentName: string,
|
||||
tagPrefix = '',
|
||||
) {
|
||||
if (!articals.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tags: VueTag[] = [];
|
||||
const tag: VueTag = {
|
||||
name: getComponentName(componentName, tagPrefix),
|
||||
name: kebabComponentName,
|
||||
slots: [],
|
||||
events: [],
|
||||
attributes: [],
|
||||
|
@ -80,9 +85,13 @@ export function formatter(articals: Articals, componentName: string, tagPrefix =
|
|||
}
|
||||
|
||||
// 额外的子组件
|
||||
if (tableTitle.includes(componentName) && !tableTitle.includes('events')) {
|
||||
if (
|
||||
tableTitle.includes(componentName) &&
|
||||
!tableTitle.includes('events') &&
|
||||
!tableTitle.includes('()')
|
||||
) {
|
||||
const childTag: VueTag = {
|
||||
name: getComponentName(tableTitle.replace('.', ''), tagPrefix),
|
||||
name: getComponentName(tableTitle.replace(/\.|\//g, ''), tagPrefix),
|
||||
slots: [],
|
||||
events: [],
|
||||
attributes: [],
|
||||
|
@ -93,6 +102,7 @@ export function formatter(articals: Articals, componentName: string, tagPrefix =
|
|||
tags.push(childTag);
|
||||
return;
|
||||
}
|
||||
|
||||
// 额外的子组件事件
|
||||
if (tableTitle.includes(componentName) && tableTitle.includes('events')) {
|
||||
const childTagName = getComponentName(
|
||||
|
|
|
@ -1,52 +1,84 @@
|
|||
import glob from 'fast-glob';
|
||||
import { join, dirname } from 'path';
|
||||
import { dirname, join } from 'path';
|
||||
import { mdParser } from './parser';
|
||||
import { formatter } from './formatter';
|
||||
import { genWebTypes } from './web-types';
|
||||
import { readFileSync, outputFileSync } from 'fs-extra';
|
||||
import { outputFileSync, readFileSync } from 'fs-extra';
|
||||
import type { Options, VueTag } from './type';
|
||||
import { normalizePath, getComponentName } from './utils';
|
||||
import { genVeturTags, genVeturAttributes } from './vetur';
|
||||
import { getComponentName, normalizePath, toKebabCase } from './utils';
|
||||
import { flatMap } from 'lodash';
|
||||
|
||||
async function readMarkdown(options: Options) {
|
||||
// const mds = await glob(normalizePath(`${options.path}/**/*.md`))
|
||||
const mds = await glob(normalizePath(`${options.path}/**/*.md`));
|
||||
return mds
|
||||
async function readMarkdown(options: Options): Promise<Map<String, VueTag>> {
|
||||
const mdPaths = await glob(normalizePath(`${options.path}/**/*.md`));
|
||||
const data = mdPaths
|
||||
.filter(md => options.test.test(md))
|
||||
.map(path => {
|
||||
const docPath = dirname(path);
|
||||
const componentName = docPath.substring(docPath.lastIndexOf('/') + 1);
|
||||
return {
|
||||
componentName: getComponentName(componentName || ''),
|
||||
md: readFileSync(path, 'utf-8'),
|
||||
};
|
||||
});
|
||||
const kebabComponentName =
|
||||
options.tagPrefix + docPath.substring(docPath.lastIndexOf('/') + 1) || '';
|
||||
const componentName = getComponentName(docPath.substring(docPath.lastIndexOf('/') + 1) || '');
|
||||
const fileContent = readFileSync(path, 'utf-8');
|
||||
return formatter(mdParser(fileContent), componentName, kebabComponentName, options.tagPrefix);
|
||||
})
|
||||
.filter(item => item) as VueTag[][];
|
||||
const tags = new Map<String, VueTag>();
|
||||
flatMap(data, item => item).forEach(mergedTag => mergeTag(tags, mergedTag));
|
||||
return tags;
|
||||
}
|
||||
|
||||
export async function parseAndWrite(options: Options) {
|
||||
function readTypings(options: Options): Map<String, VueTag> {
|
||||
const tags = new Map<String, VueTag>();
|
||||
const fileContent = readFileSync(options.typingsPath, 'utf-8');
|
||||
fileContent
|
||||
.split('\n')
|
||||
.filter(line => line && line.includes('typeof'))
|
||||
.map(line => {
|
||||
const l = line.trim();
|
||||
return toKebabCase(l.substring(0, l.indexOf(':')));
|
||||
})
|
||||
.forEach(tagName =>
|
||||
tags.set(tagName, {
|
||||
name: tagName,
|
||||
slots: [],
|
||||
events: [],
|
||||
attributes: [],
|
||||
}),
|
||||
);
|
||||
return tags;
|
||||
}
|
||||
|
||||
function mergeTag(tags: Map<String, VueTag>, mergedTag: VueTag) {
|
||||
const tagName = mergedTag.name;
|
||||
const vueTag = tags.get(tagName);
|
||||
if (vueTag) {
|
||||
vueTag.slots = [...vueTag.slots, ...mergedTag.slots];
|
||||
vueTag.events = [...vueTag.events, ...mergedTag.events];
|
||||
vueTag.attributes = [...vueTag.attributes, ...mergedTag.attributes];
|
||||
} else {
|
||||
tags.set(tagName, mergedTag);
|
||||
}
|
||||
}
|
||||
|
||||
function mergeTags(mergedTagsArr: Map<String, VueTag>[]): VueTag[] {
|
||||
if (mergedTagsArr.length === 1) return [...mergedTagsArr[0].values()];
|
||||
const tags = new Map<String, VueTag>();
|
||||
if (mergedTagsArr.length === 0) return [];
|
||||
mergedTagsArr.forEach(mergedTags => {
|
||||
mergedTags.forEach(mergedTag => mergeTag(tags, mergedTag));
|
||||
});
|
||||
return [...tags.values()];
|
||||
}
|
||||
|
||||
export async function parseAndWrite(options: Options): Promise<Number> {
|
||||
if (!options.outputDir) {
|
||||
throw new Error('outputDir can not be empty.');
|
||||
}
|
||||
|
||||
const docs = await readMarkdown(options);
|
||||
const datas = docs
|
||||
.map(doc => formatter(mdParser(doc.md), doc.componentName, options.tagPrefix))
|
||||
.filter(item => item) as VueTag[][];
|
||||
const tags: VueTag[] = [];
|
||||
datas.forEach(arr => {
|
||||
tags.push(...arr);
|
||||
});
|
||||
|
||||
const tagsFromMarkdown = await readMarkdown(options);
|
||||
const tagsFromTypings = await readTypings(options);
|
||||
const tags = mergeTags([tagsFromMarkdown, tagsFromTypings]);
|
||||
const webTypes = genWebTypes(tags, options);
|
||||
const veturTags = genVeturTags(tags);
|
||||
const veturAttributes = genVeturAttributes(tags);
|
||||
|
||||
outputFileSync(join(options.outputDir, 'tags.json'), JSON.stringify(veturTags, null, 2));
|
||||
outputFileSync(
|
||||
join(options.outputDir, 'attributes.json'),
|
||||
JSON.stringify(veturAttributes, null, 2),
|
||||
);
|
||||
outputFileSync(join(options.outputDir, 'web-types.json'), JSON.stringify(webTypes, null, 2));
|
||||
return tags.length;
|
||||
}
|
||||
|
||||
export default { parseAndWrite };
|
||||
|
|
|
@ -21,13 +21,13 @@ export type Articals = Artical[];
|
|||
function readLine(input: string) {
|
||||
const end = input.indexOf('\n');
|
||||
|
||||
return input.substr(0, end !== -1 ? end : input.length);
|
||||
return input.substring(0, end !== -1 ? end : input.length);
|
||||
}
|
||||
|
||||
function splitTableLine(line: string) {
|
||||
line = line.replace('\\|', 'JOIN');
|
||||
line = line.replace(/\\\|/g, 'JOIN');
|
||||
|
||||
const items = line.split('|').map(item => item.trim().replace('JOIN', '|'));
|
||||
const items = line.split('|').map(item => item.trim().replace(/JOIN/g, '|'));
|
||||
|
||||
// remove pipe character on both sides
|
||||
items.pop();
|
||||
|
@ -47,7 +47,7 @@ function tableParse(input: string) {
|
|||
};
|
||||
|
||||
while (start < end) {
|
||||
const target = input.substr(start);
|
||||
const target = input.substring(start);
|
||||
const line = readLine(target);
|
||||
|
||||
if (!/^\|/.test(target)) {
|
||||
|
@ -77,14 +77,9 @@ export function mdParser(input: string): Articals {
|
|||
const artical = [];
|
||||
let start = 0;
|
||||
const end = input.length;
|
||||
// artical.push({
|
||||
// type: 'title',
|
||||
// content: title,
|
||||
// level: 0,
|
||||
// });
|
||||
|
||||
while (start < end) {
|
||||
const target = input.substr(start);
|
||||
const target = input.substring(start);
|
||||
|
||||
let match;
|
||||
if ((match = TITLE_REG.exec(target))) {
|
||||
|
@ -96,7 +91,7 @@ export function mdParser(input: string): Articals {
|
|||
|
||||
start += match.index + match[0].length;
|
||||
} else if ((match = TABLE_REG.exec(target))) {
|
||||
const { table, usedLength } = tableParse(target.substr(match.index));
|
||||
const { table, usedLength } = tableParse(target.substring(match.index));
|
||||
artical.push({
|
||||
type: 'table',
|
||||
table,
|
||||
|
@ -108,6 +103,5 @@ export function mdParser(input: string): Articals {
|
|||
}
|
||||
}
|
||||
|
||||
// artical[0].content = title
|
||||
return artical;
|
||||
}
|
||||
|
|
|
@ -28,34 +28,16 @@ export type VueAttribute = {
|
|||
|
||||
export type VueTag = {
|
||||
name: string;
|
||||
slots?: VueSlot[];
|
||||
events?: VueEvent[];
|
||||
attributes?: VueAttribute[];
|
||||
slots: VueSlot[];
|
||||
events: VueEvent[];
|
||||
attributes: VueAttribute[];
|
||||
description?: string;
|
||||
};
|
||||
|
||||
export type VeturTag = {
|
||||
description?: string;
|
||||
attributes: string[];
|
||||
};
|
||||
|
||||
export type VeturTags = Record<string, VeturTag>;
|
||||
|
||||
export type VeturAttribute = {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
export type VeturAttributes = Record<string, VeturAttribute>;
|
||||
|
||||
export type VeturResult = {
|
||||
tags: VeturTags;
|
||||
attributes: VeturAttributes;
|
||||
};
|
||||
|
||||
export type Options = {
|
||||
name: string;
|
||||
path: PathLike;
|
||||
typingsPath: PathLike;
|
||||
test: RegExp;
|
||||
version: string;
|
||||
outputDir?: string;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// myName -> my-name
|
||||
export function toKebabCase(input: string): string {
|
||||
return input.replace(/[A-Z]/g, (val, index) => (index === 0 ? '' : '-') + val.toLowerCase());
|
||||
export function toKebabCase(camel: string): string {
|
||||
return camel.replace(/((?<=[a-z\d])[A-Z]|(?<=[A-Z\d])[A-Z](?=[a-z]))/g, '-$1').toLowerCase();
|
||||
}
|
||||
|
||||
// name `v2.0.0` -> name
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
import type { VueTag, VeturTags, VeturAttributes } from './type';
|
||||
|
||||
export function genVeturTags(tags: VueTag[]) {
|
||||
const veturTags: VeturTags = {};
|
||||
|
||||
tags.forEach(tag => {
|
||||
veturTags[tag.name] = {
|
||||
attributes: tag.attributes ? tag.attributes.map(item => item.name) : [],
|
||||
};
|
||||
});
|
||||
|
||||
return veturTags;
|
||||
}
|
||||
|
||||
export function genVeturAttributes(tags: VueTag[]) {
|
||||
const veturAttributes: VeturAttributes = {};
|
||||
|
||||
tags.forEach(tag => {
|
||||
if (tag.attributes) {
|
||||
tag.attributes.forEach(attr => {
|
||||
veturAttributes[`${tag.name}/${attr.name}`] = {
|
||||
type: attr.value.type,
|
||||
description: `${attr.description}, Default: ${attr.default}`,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return veturAttributes;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
const { resolve } = require('./utils/projectHelper');
|
||||
const { resolve, isThereHaveBrowserslistConfig } = require('./utils/projectHelper');
|
||||
|
||||
module.exports = function (modules) {
|
||||
const plugins = [
|
||||
|
@ -20,7 +20,8 @@ module.exports = function (modules) {
|
|||
resolve('@babel/plugin-transform-runtime'),
|
||||
{
|
||||
useESModules: modules === false,
|
||||
version: '^7.10.4',
|
||||
version:
|
||||
require(`${process.cwd()}/package.json`).dependencies['@babel/runtime'] || '^7.10.4',
|
||||
},
|
||||
],
|
||||
// resolve('babel-plugin-inline-import-data-uri'),
|
||||
|
@ -38,8 +39,10 @@ module.exports = function (modules) {
|
|||
resolve('@babel/preset-env'),
|
||||
{
|
||||
modules,
|
||||
targets: {
|
||||
browsers: ['last 2 versions', 'Firefox ESR', '> 1%', 'not ie 11'],
|
||||
targets: isThereHaveBrowserslistConfig()
|
||||
? undefined
|
||||
: {
|
||||
browsers: ['last 2 versions', 'Firefox ESR', '> 1%', 'ie >= 11'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
const runCmd = require('./runCmd');
|
||||
|
||||
module.exports = function (done) {
|
||||
if (process.env.NPM_CLI) {
|
||||
done(process.env.NPM_CLI);
|
||||
return;
|
||||
}
|
||||
runCmd('which', ['tnpm'], code => {
|
||||
let npm = 'npm';
|
||||
if (!code) {
|
||||
npm = 'tnpm';
|
||||
}
|
||||
done(npm);
|
||||
});
|
||||
};
|
|
@ -1,7 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const assign = require('object-assign');
|
||||
const { getProjectPath } = require('./utils/projectHelper');
|
||||
|
||||
module.exports = function () {
|
||||
|
@ -9,7 +8,7 @@ module.exports = function() {
|
|||
if (fs.existsSync(getProjectPath('tsconfig.json'))) {
|
||||
my = require(getProjectPath('tsconfig.json'));
|
||||
}
|
||||
return assign(
|
||||
return Object.assign(
|
||||
{
|
||||
noUnusedParameters: true,
|
||||
noUnusedLocals: true,
|
||||
|
|
|
@ -22,7 +22,7 @@ const imageOptions = {
|
|||
limit: 10000,
|
||||
};
|
||||
|
||||
function getWebpackConfig(modules) {
|
||||
function getWebpackConfig(modules, esm = false) {
|
||||
const pkg = require(getProjectPath('package.json'));
|
||||
const babelConfig = require('./getBabelCommonConfig')(modules || false);
|
||||
|
||||
|
@ -75,7 +75,7 @@ function getWebpackConfig(modules) {
|
|||
'readline',
|
||||
'repl',
|
||||
'tls',
|
||||
].reduce((acc, name) => Object.assign({}, acc, { [name]: false }), {}),
|
||||
].reduce((acc, name) => Object.assign({}, acc, { [name]: 'empty' }), {}),
|
||||
},
|
||||
|
||||
module: {
|
||||
|
@ -150,36 +150,6 @@ function getWebpackConfig(modules) {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
postcssOptions: {
|
||||
plugins: ['autoprefixer'],
|
||||
},
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'less-loader',
|
||||
options: {
|
||||
lessOptions: {
|
||||
sourceMap: true,
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// Images
|
||||
{
|
||||
test: svgRegex,
|
||||
|
@ -200,7 +170,7 @@ function getWebpackConfig(modules) {
|
|||
new webpack.BannerPlugin(`
|
||||
${pkg.name} v${pkg.version}
|
||||
|
||||
Copyright 2017-present, ant-design-vue.
|
||||
Copyright 2017-present, Ant Design Vue.
|
||||
All rights reserved.
|
||||
`),
|
||||
new WebpackBar({
|
||||
|
@ -215,17 +185,37 @@ All rights reserved.
|
|||
};
|
||||
|
||||
if (process.env.RUN_ENV === 'PRODUCTION') {
|
||||
const entry = ['./index'];
|
||||
config.externals = {
|
||||
let entry = ['./index'];
|
||||
config.externals = [
|
||||
{
|
||||
vue: {
|
||||
root: 'Vue',
|
||||
commonjs2: 'vue',
|
||||
commonjs: 'vue',
|
||||
amd: 'vue',
|
||||
module: 'vue',
|
||||
},
|
||||
},
|
||||
];
|
||||
if (esm) {
|
||||
entry = ['./index.esm'];
|
||||
config.experiments = {
|
||||
...config.experiments,
|
||||
outputModule: true,
|
||||
};
|
||||
config.output.library = distFileBaseName;
|
||||
config.output.chunkFormat = 'module';
|
||||
config.output.library = {
|
||||
type: 'module',
|
||||
};
|
||||
config.target = 'es2019';
|
||||
} else {
|
||||
config.output.libraryTarget = 'umd';
|
||||
config.output.library = distFileBaseName;
|
||||
config.output.globalObject = 'this';
|
||||
}
|
||||
|
||||
const entryName = esm ? `${distFileBaseName}.esm` : distFileBaseName;
|
||||
|
||||
config.optimization = {
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
|
@ -236,11 +226,10 @@ All rights reserved.
|
|||
}),
|
||||
],
|
||||
};
|
||||
|
||||
// Development
|
||||
const uncompressedConfig = merge({}, config, {
|
||||
entry: {
|
||||
[distFileBaseName]: entry,
|
||||
[entryName]: entry,
|
||||
},
|
||||
mode: 'development',
|
||||
plugins: [
|
||||
|
@ -253,11 +242,10 @@ All rights reserved.
|
|||
// Production
|
||||
const prodConfig = merge({}, config, {
|
||||
entry: {
|
||||
[`${distFileBaseName}.min`]: entry,
|
||||
[`${entryName}.min`]: entry,
|
||||
},
|
||||
mode: 'production',
|
||||
plugins: [
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
minimize: true,
|
||||
}),
|
||||
|
@ -274,7 +262,7 @@ All rights reserved.
|
|||
return [prodConfig, uncompressedConfig];
|
||||
}
|
||||
|
||||
return config;
|
||||
return [config];
|
||||
}
|
||||
|
||||
getWebpackConfig.webpack = webpack;
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/* eslint-disable no-console */
|
||||
const { getProjectPath } = require('./utils/projectHelper');
|
||||
const { getProjectPath, getConfig } = require('./utils/projectHelper');
|
||||
const runCmd = require('./runCmd');
|
||||
const getBabelCommonConfig = require('./getBabelCommonConfig');
|
||||
const merge2 = require('merge2');
|
||||
const { execSync } = require('child_process');
|
||||
const through2 = require('through2');
|
||||
const transformLess = require('./transformLess');
|
||||
const webpack = require('webpack');
|
||||
const babel = require('gulp-babel');
|
||||
const argv = require('minimist')(process.argv.slice(2));
|
||||
|
@ -17,22 +16,31 @@ const chalk = require('chalk');
|
|||
const getNpmArgs = require('./utils/get-npm-args');
|
||||
const getChangelog = require('./utils/getChangelog');
|
||||
const path = require('path');
|
||||
// const watch = require('gulp-watch')
|
||||
const ts = require('gulp-typescript');
|
||||
const gulp = require('gulp');
|
||||
const fg = require('fast-glob');
|
||||
const fs = require('fs');
|
||||
const rimraf = require('rimraf');
|
||||
const { createCompilerHost, createProgram } = require('typescript');
|
||||
const stripCode = require('gulp-strip-code');
|
||||
const compareVersions = require('compare-versions');
|
||||
// const getTSCommonConfig = require('./getTSCommonConfig');
|
||||
const getTSCommonConfig = require('./getTSCommonConfig');
|
||||
const replaceLib = require('./replaceLib');
|
||||
const sortApiTable = require('./sortApiTable');
|
||||
const { glob } = require('glob');
|
||||
|
||||
const packageJson = require(getProjectPath('package.json'));
|
||||
const tsDefaultReporter = ts.reporter.defaultReporter();
|
||||
const cwd = process.cwd();
|
||||
const libDir = getProjectPath('lib');
|
||||
const esDir = getProjectPath('es');
|
||||
const localeDir = getProjectPath('locale');
|
||||
|
||||
// const tsConfig = getTSCommonConfig();
|
||||
const tsConfig = getTSCommonConfig();
|
||||
|
||||
// FIXME: hard code, not find typescript can modify the path resolution
|
||||
const localeDts = `import type { Locale } from '../lib/locale-provider';
|
||||
declare const localeValues: Locale;
|
||||
export default localeValues;`;
|
||||
|
||||
function dist(done) {
|
||||
rimraf.sync(path.join(cwd, 'dist'));
|
||||
|
@ -48,11 +56,17 @@ function dist(done) {
|
|||
}
|
||||
|
||||
const info = stats.toJson();
|
||||
const { dist: { finalize } = {}, bail } = getConfig();
|
||||
|
||||
if (stats.hasErrors()) {
|
||||
console.error(info.errors);
|
||||
(info.errors || []).forEach(error => {
|
||||
console.error(error);
|
||||
});
|
||||
// https://github.com/ant-design/ant-design/pull/31662
|
||||
if (bail) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (stats.hasWarnings()) {
|
||||
console.warn(info.warnings);
|
||||
}
|
||||
|
@ -67,55 +81,43 @@ function dist(done) {
|
|||
version: false,
|
||||
});
|
||||
console.log(buildInfo);
|
||||
// Additional process of dist finalize
|
||||
if (finalize) {
|
||||
console.log('[Dist] Finalization...');
|
||||
finalize();
|
||||
}
|
||||
done(0);
|
||||
});
|
||||
}
|
||||
|
||||
async function compileTs(modules = false, cb) {
|
||||
const options = {
|
||||
allowJs: true,
|
||||
declaration: true,
|
||||
emitDeclarationOnly: true,
|
||||
};
|
||||
const tsFiles = ['**/*.ts', '**/*.tsx', '!node_modules/**/*.*', 'typings/**/*.d.ts'];
|
||||
|
||||
const createdFiles = {};
|
||||
const host = createCompilerHost(options);
|
||||
host.writeFile = (fileName, contents) => {
|
||||
createdFiles[path.isAbsolute(fileName) ? path.relative(cwd, fileName) : fileName] = contents;
|
||||
};
|
||||
|
||||
const files = await fg(
|
||||
[
|
||||
'components/**/*.js',
|
||||
'components/**/*.jsx',
|
||||
'components/**/*.tsx',
|
||||
'components/**/*.ts',
|
||||
'!components/*/__tests__/*',
|
||||
'!components/*/style/*',
|
||||
'!components/styles.ts',
|
||||
],
|
||||
{ cwd },
|
||||
);
|
||||
|
||||
const program = createProgram(files, options, host);
|
||||
program.emit();
|
||||
|
||||
Object.keys(createdFiles).forEach(fileName => {
|
||||
const contents = createdFiles[fileName];
|
||||
const filePath = path.join(
|
||||
cwd,
|
||||
fileName.replace(/^components/, modules === false ? 'es' : 'lib'),
|
||||
);
|
||||
const dir = path.dirname(filePath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
function compileTs(stream) {
|
||||
return stream
|
||||
.pipe(ts(tsConfig))
|
||||
.js.pipe(
|
||||
through2.obj(function (file, encoding, next) {
|
||||
// console.log(file.path, file.base);
|
||||
file.path = file.path.replace(/\.[jt]sx$/, '.js');
|
||||
this.push(file);
|
||||
next();
|
||||
}),
|
||||
)
|
||||
.pipe(gulp.dest(process.cwd()));
|
||||
}
|
||||
fs.writeFileSync(filePath, contents);
|
||||
|
||||
gulp.task('tsc', () =>
|
||||
compileTs(
|
||||
gulp.src(tsFiles, {
|
||||
base: cwd,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
gulp.task('clean', () => {
|
||||
rimraf.sync(getProjectPath('_site'));
|
||||
rimraf.sync(getProjectPath('_data'));
|
||||
});
|
||||
cb(0);
|
||||
}
|
||||
|
||||
gulp.task('tsc', () => compileTs());
|
||||
|
||||
function babelify(js, modules) {
|
||||
const babelConfig = getBabelCommonConfig(modules);
|
||||
|
@ -124,20 +126,10 @@ function babelify(js, modules) {
|
|||
if (modules === false) {
|
||||
babelConfig.plugins.push(replaceLib);
|
||||
}
|
||||
let stream = js.pipe(babel(babelConfig)).pipe(
|
||||
const stream = js.pipe(babel(babelConfig)).pipe(
|
||||
through2.obj(function z(file, encoding, next) {
|
||||
this.push(file.clone());
|
||||
if (file.path.match(/\/style\/index\.(js|jsx|ts|tsx)$/)) {
|
||||
const content = file.contents.toString(encoding);
|
||||
file.contents = Buffer.from(
|
||||
content
|
||||
.replace(/\/style\/?'/g, "/style/css'")
|
||||
.replace(/\/style\/?"/g, '/style/css"')
|
||||
.replace(/\.less/g, '.css'),
|
||||
);
|
||||
file.path = file.path.replace(/index\.(js|jsx|ts|tsx)$/, 'css.js');
|
||||
this.push(file);
|
||||
} else if (modules !== false) {
|
||||
if (modules !== false) {
|
||||
const content = file.contents.toString(encoding);
|
||||
file.contents = Buffer.from(
|
||||
content
|
||||
|
@ -149,48 +141,36 @@ function babelify(js, modules) {
|
|||
next();
|
||||
}),
|
||||
);
|
||||
if (modules === false) {
|
||||
stream = stream.pipe(
|
||||
stripCode({
|
||||
start_comment: '@remove-on-es-build-begin',
|
||||
end_comment: '@remove-on-es-build-end',
|
||||
}),
|
||||
);
|
||||
}
|
||||
return stream.pipe(gulp.dest(modules === false ? esDir : libDir));
|
||||
}
|
||||
|
||||
function compile(modules) {
|
||||
const { compile: { transformTSFile, transformFile } = {} } = getConfig();
|
||||
rimraf.sync(modules !== false ? libDir : esDir);
|
||||
const less = gulp
|
||||
.src(['components/**/*.less'])
|
||||
.pipe(
|
||||
through2.obj(function (file, encoding, next) {
|
||||
this.push(file.clone());
|
||||
if (
|
||||
file.path.match(/\/style\/index\.less$/) ||
|
||||
file.path.match(/\/style\/v2-compatible-reset\.less$/)
|
||||
) {
|
||||
transformLess(file.path)
|
||||
.then(css => {
|
||||
file.contents = Buffer.from(css);
|
||||
file.path = file.path.replace(/\.less$/, '.css');
|
||||
this.push(file);
|
||||
next();
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}),
|
||||
)
|
||||
.pipe(gulp.dest(modules === false ? esDir : libDir));
|
||||
|
||||
const assets = gulp
|
||||
.src(['components/**/*.@(png|svg)'])
|
||||
.pipe(gulp.dest(modules === false ? esDir : libDir));
|
||||
// let error = 0;
|
||||
let error = 0;
|
||||
|
||||
// =============================== FILE ===============================
|
||||
let transformFileStream;
|
||||
|
||||
if (transformFile) {
|
||||
transformFileStream = gulp
|
||||
.src(['components/**/*.tsx'])
|
||||
.pipe(
|
||||
through2.obj(function (file, encoding, next) {
|
||||
let nextFile = transformFile(file) || file;
|
||||
nextFile = Array.isArray(nextFile) ? nextFile : [nextFile];
|
||||
nextFile.forEach(f => this.push(f));
|
||||
next();
|
||||
}),
|
||||
)
|
||||
.pipe(gulp.dest(modules === false ? esDir : libDir));
|
||||
}
|
||||
|
||||
// ================================ TS ================================
|
||||
const source = [
|
||||
'components/**/*.js',
|
||||
'components/**/*.jsx',
|
||||
|
@ -200,8 +180,68 @@ function compile(modules) {
|
|||
'!components/*/__tests__/*',
|
||||
];
|
||||
|
||||
const jsFilesStream = babelify(gulp.src(source), modules);
|
||||
return merge2([less, jsFilesStream, assets]);
|
||||
// Strip content if needed
|
||||
let sourceStream = gulp.src(source);
|
||||
if (modules === false) {
|
||||
sourceStream = sourceStream.pipe(
|
||||
stripCode({
|
||||
start_comment: '@remove-on-es-build-begin',
|
||||
end_comment: '@remove-on-es-build-end',
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (transformTSFile) {
|
||||
sourceStream = sourceStream.pipe(
|
||||
through2.obj(function (file, encoding, next) {
|
||||
let nextFile = transformTSFile(file) || file;
|
||||
nextFile = Array.isArray(nextFile) ? nextFile : [nextFile];
|
||||
nextFile.forEach(f => this.push(f));
|
||||
next();
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const tsResult = sourceStream.pipe(
|
||||
ts(tsConfig, {
|
||||
error(e) {
|
||||
tsDefaultReporter.error(e);
|
||||
error = 1;
|
||||
},
|
||||
finish: tsDefaultReporter.finish,
|
||||
}),
|
||||
);
|
||||
|
||||
function check() {
|
||||
if (error && !argv['ignore-error']) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
tsResult.on('finish', check);
|
||||
tsResult.on('end', check);
|
||||
const tsFilesStream = babelify(tsResult.js, modules);
|
||||
const tsd = tsResult.dts.pipe(gulp.dest(modules === false ? esDir : libDir));
|
||||
return merge2([tsFilesStream, tsd, assets, transformFileStream].filter(s => s));
|
||||
}
|
||||
|
||||
function generateLocale() {
|
||||
if (!fs.existsSync(localeDir)) {
|
||||
fs.mkdirSync(localeDir);
|
||||
}
|
||||
|
||||
const localeFiles = glob.sync('components/locale/*.ts?(x)');
|
||||
localeFiles.forEach(item => {
|
||||
const match = item.match(/components\/locale\/(.*)\.tsx?/);
|
||||
if (match) {
|
||||
const locale = match[1];
|
||||
fs.writeFileSync(
|
||||
path.join(localeDir, `${locale}.js`),
|
||||
`module.exports = require('../lib/locale/${locale}');`,
|
||||
);
|
||||
fs.writeFileSync(path.join(localeDir, `${locale}.d.ts`), localeDts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function tag() {
|
||||
|
@ -328,9 +368,8 @@ function pub(done) {
|
|||
}
|
||||
}
|
||||
|
||||
let startTime = new Date();
|
||||
const startTime = new Date();
|
||||
gulp.task('compile-with-es', done => {
|
||||
startTime = new Date();
|
||||
console.log('start compile at ', startTime);
|
||||
console.log('[Parallel] Compile to es...');
|
||||
compile(false).on('finish', done);
|
||||
|
@ -338,34 +377,29 @@ gulp.task('compile-with-es', done => {
|
|||
|
||||
gulp.task('compile-with-lib', done => {
|
||||
console.log('[Parallel] Compile to js...');
|
||||
compile().on('finish', done);
|
||||
compile().on('finish', () => {
|
||||
generateLocale();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('compile-with-es-ts-type', async done => {
|
||||
console.log('[Parallel] Compile to es ts type...');
|
||||
await compileTs(false, done);
|
||||
});
|
||||
|
||||
gulp.task('compile-with-lib-ts-type', async done => {
|
||||
console.log('[Parallel] Compile to lib ts type...');
|
||||
await compileTs(true, done);
|
||||
gulp.task('compile-finalize', done => {
|
||||
// Additional process of compile finalize
|
||||
const { compile: { finalize } = {} } = getConfig();
|
||||
if (finalize) {
|
||||
console.log('[Compile] Finalization...');
|
||||
finalize();
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
gulp.task(
|
||||
'compile',
|
||||
gulp.series(
|
||||
gulp.parallel(
|
||||
'compile-with-es',
|
||||
'compile-with-lib',
|
||||
'compile-with-es-ts-type',
|
||||
'compile-with-lib-ts-type',
|
||||
),
|
||||
done => {
|
||||
gulp.series(gulp.parallel('compile-with-es', 'compile-with-lib'), 'compile-finalize', done => {
|
||||
console.log('end compile at ', new Date());
|
||||
console.log('compile time ', (new Date() - startTime) / 1000, 's');
|
||||
done();
|
||||
},
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
gulp.task(
|
||||
|
@ -418,7 +452,7 @@ gulp.task(
|
|||
newVersion.trim() === version
|
||||
) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
runCmd('npm', ['run', 'pub'], code => {
|
||||
runCmd('npm', ['run', 'pub'], _code => {
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
|
@ -441,7 +475,11 @@ gulp.task(
|
|||
const npmArgs = getNpmArgs();
|
||||
if (npmArgs) {
|
||||
for (let arg = npmArgs.shift(); arg; arg = npmArgs.shift()) {
|
||||
if (/^pu(b(l(i(sh?)?)?)?)?$/.test(arg) && npmArgs.indexOf('--with-antd-tools') < 0) {
|
||||
if (
|
||||
/^pu(b(l(i(sh?)?)?)?)?$/.test(arg) &&
|
||||
npmArgs.indexOf('--with-antd-tools') < 0 &&
|
||||
!process.env.npm_config_with_antd_tools
|
||||
) {
|
||||
reportError();
|
||||
done(1);
|
||||
return;
|
||||
|
@ -451,3 +489,11 @@ gulp.task(
|
|||
done();
|
||||
}),
|
||||
);
|
||||
|
||||
gulp.task(
|
||||
'sort-api-table',
|
||||
gulp.series(done => {
|
||||
sortApiTable();
|
||||
done();
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -12,6 +12,19 @@ function replacePath(path) {
|
|||
path.node.source.value = esModule;
|
||||
}
|
||||
}
|
||||
|
||||
// @ant-design/icons-vue/xxx => @ant-design/icons-vue/es/icons/xxx
|
||||
const antdIconMatcher = /@ant-design\/icons-vue\/([^/]*)$/;
|
||||
if (path.node.source && antdIconMatcher.test(path.node.source.value)) {
|
||||
const esModule = path.node.source.value.replace(
|
||||
antdIconMatcher,
|
||||
(_, iconName) => `@ant-design/icons-vue/es/icons/${iconName}`,
|
||||
);
|
||||
const esPath = dirname(getProjectPath('node_modules', esModule));
|
||||
if (fs.existsSync(esPath)) {
|
||||
path.node.source.value = esModule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replaceLib() {
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
const isWindows = require('is-windows');
|
||||
const getRunCmdEnv = require('./utils/getRunCmdEnv');
|
||||
|
||||
function runCmd(cmd, _args, fn) {
|
||||
const args = _args || [];
|
||||
|
||||
if (isWindows()) {
|
||||
args.unshift(cmd);
|
||||
args.unshift('/c');
|
||||
cmd = process.env.ComSpec;
|
||||
}
|
||||
|
||||
const runner = require('child_process').spawn(cmd, args, {
|
||||
// keep color
|
||||
stdio: 'inherit',
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
const program = require('commander');
|
||||
const majo = require('majo');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const chalk = require('chalk');
|
||||
|
||||
const unified = require('unified');
|
||||
const parse = require('remark-parse');
|
||||
const stringify = require('remark-stringify');
|
||||
|
||||
const yamlConfig = require('remark-yaml-config');
|
||||
const frontmatter = require('remark-frontmatter');
|
||||
|
||||
let fileAPIs = {};
|
||||
const remarkWithYaml = unified()
|
||||
.use(parse)
|
||||
.use(stringify, {
|
||||
paddedTable: false,
|
||||
listItemIndent: 1,
|
||||
stringLength: () => 3,
|
||||
})
|
||||
.use(frontmatter)
|
||||
.use(yamlConfig);
|
||||
|
||||
const stream = majo.majo();
|
||||
|
||||
function getCellValue(node) {
|
||||
return node.children[0].children[0].value;
|
||||
}
|
||||
|
||||
// from small to large
|
||||
const sizeBreakPoints = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
|
||||
|
||||
const whiteMethodList = ['afterChange', 'beforeChange'];
|
||||
|
||||
const groups = {
|
||||
isDynamic: val => /^on[A-Z]/.test(val) || whiteMethodList.indexOf(val) > -1,
|
||||
isSize: val => sizeBreakPoints.indexOf(val) > -1,
|
||||
};
|
||||
|
||||
function asciiSort(prev, next) {
|
||||
if (prev > next) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (prev < next) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// follow the alphabet order
|
||||
function alphabetSort(nodes) {
|
||||
// use toLowerCase to keep `case insensitive`
|
||||
return nodes.sort((...comparison) =>
|
||||
asciiSort(...comparison.map(val => getCellValue(val).toLowerCase())),
|
||||
);
|
||||
}
|
||||
|
||||
function sizeSort(nodes) {
|
||||
return nodes.sort((...comparison) =>
|
||||
asciiSort(...comparison.map(val => sizeBreakPoints.indexOf(getCellValue(val).toLowerCase()))),
|
||||
);
|
||||
}
|
||||
|
||||
function sort(ast, filename) {
|
||||
const nameMatch = filename.match(/^components\/([^/]*)\//);
|
||||
const componentName = nameMatch[1];
|
||||
fileAPIs[componentName] = fileAPIs[componentName] || {
|
||||
static: new Set(),
|
||||
size: new Set(),
|
||||
dynamic: new Set(),
|
||||
};
|
||||
|
||||
ast.children.forEach(child => {
|
||||
const staticProps = [];
|
||||
// prefix with `on`
|
||||
const dynamicProps = [];
|
||||
// one of ['xs', 'sm', 'md', 'lg', 'xl']
|
||||
const sizeProps = [];
|
||||
|
||||
// find table markdown type
|
||||
if (child.type === 'table') {
|
||||
// slice will create new array, so sort can affect the original array.
|
||||
// slice(1) cut down the thead
|
||||
child.children.slice(1).forEach(node => {
|
||||
const value = getCellValue(node);
|
||||
if (groups.isDynamic(value)) {
|
||||
dynamicProps.push(node);
|
||||
fileAPIs[componentName].dynamic.add(value);
|
||||
} else if (groups.isSize(value)) {
|
||||
sizeProps.push(node);
|
||||
fileAPIs[componentName].size.add(value);
|
||||
} else {
|
||||
staticProps.push(node);
|
||||
fileAPIs[componentName].static.add(value);
|
||||
}
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
child.children = [
|
||||
child.children[0],
|
||||
...alphabetSort(staticProps),
|
||||
...sizeSort(sizeProps),
|
||||
...alphabetSort(dynamicProps),
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
function sortAPI(md, filename) {
|
||||
return remarkWithYaml.stringify(sort(remarkWithYaml.parse(md), filename));
|
||||
}
|
||||
|
||||
function sortMiddleware(ctx) {
|
||||
Object.keys(ctx.files).forEach(filename => {
|
||||
const content = ctx.fileContents(filename);
|
||||
ctx.writeContents(filename, sortAPI(content, filename));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = () => {
|
||||
fileAPIs = {};
|
||||
|
||||
program
|
||||
.version('0.1.0')
|
||||
.option(
|
||||
'-f, --file [file]',
|
||||
'Specify which file to be transformed',
|
||||
// default value
|
||||
'components/**/index.+(zh-CN|en-US).md',
|
||||
)
|
||||
.option('-o, --output [output]', 'Specify component api output path', '~component-api.json')
|
||||
.parse(process.argv);
|
||||
// Get the markdown file all need to be transformed
|
||||
|
||||
/* eslint-disable no-console */
|
||||
stream
|
||||
.source(program.file)
|
||||
.use(sortMiddleware)
|
||||
.dest('.')
|
||||
.then(() => {
|
||||
if (program.output) {
|
||||
const data = {};
|
||||
Object.keys(fileAPIs).forEach(componentName => {
|
||||
data[componentName] = {
|
||||
static: [...fileAPIs[componentName].static],
|
||||
size: [...fileAPIs[componentName].size],
|
||||
dynamic: [...fileAPIs[componentName].dynamic],
|
||||
};
|
||||
});
|
||||
|
||||
const reportPath = path.resolve(program.output);
|
||||
fs.writeFileSync(reportPath, JSON.stringify(data, null, 2), 'utf8');
|
||||
console.log(chalk.cyan(`API list file: ${reportPath}`));
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
console.log(chalk.green(`sort ant-design-vue api successfully!`));
|
||||
});
|
||||
/* eslint-enable no-console */
|
||||
};
|
|
@ -1,30 +0,0 @@
|
|||
const less = require('less');
|
||||
const { readFileSync } = require('fs');
|
||||
const path = require('path');
|
||||
const postcss = require('postcss');
|
||||
const NpmImportPlugin = require('less-plugin-npm-import');
|
||||
const autoprefixer = require('autoprefixer');
|
||||
|
||||
function transformLess(lessFile, config = {}) {
|
||||
const { cwd = process.cwd() } = config;
|
||||
const resolvedLessFile = path.resolve(cwd, lessFile);
|
||||
|
||||
let data = readFileSync(resolvedLessFile, 'utf-8');
|
||||
data = data.replace(/^\uFEFF/, '');
|
||||
|
||||
// Do less compile
|
||||
const lessOpts = {
|
||||
paths: [path.dirname(resolvedLessFile)],
|
||||
filename: resolvedLessFile,
|
||||
plugins: [new NpmImportPlugin({ prefix: '~' })],
|
||||
javascriptEnabled: true,
|
||||
};
|
||||
return less
|
||||
.render(data, lessOpts)
|
||||
.then(result => postcss([autoprefixer]).process(result.css, { from: undefined }))
|
||||
.then(r => {
|
||||
return r.css;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = transformLess;
|
|
@ -24,13 +24,13 @@ class CleanUpStatsPlugin {
|
|||
|
||||
apply(compiler) {
|
||||
compiler.hooks.done.tap('CleanUpStatsPlugin', stats => {
|
||||
const { children } = stats.compilation;
|
||||
const { children, warnings } = stats.compilation;
|
||||
if (Array.isArray(children)) {
|
||||
stats.compilation.children = children.filter(child => this.shouldPickStatChild(child));
|
||||
}
|
||||
// if (Array.isArray(warnings)) {
|
||||
// stats.compilation.warnings = warnings.filter(message => this.shouldPickWarning(message));
|
||||
// }
|
||||
if (Array.isArray(warnings)) {
|
||||
stats.compilation.warnings = warnings.filter(message => this.shouldPickWarning(message));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
// NOTE: the following code was partially adopted from https://github.com/iarna/in-publish
|
||||
module.exports = function getNpmArgs() {
|
||||
// https://github.com/iarna/in-publish/pull/14
|
||||
if (process.env.npm_command) {
|
||||
return [process.env.npm_command];
|
||||
}
|
||||
|
||||
let npmArgv = null;
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
const fs = require('fs');
|
||||
|
||||
module.exports = function getChangelog(file, version) {
|
||||
const lines = fs
|
||||
.readFileSync(file)
|
||||
.toString()
|
||||
.split('\n');
|
||||
const lines = fs.readFileSync(file).toString().split('\n');
|
||||
const changeLog = [];
|
||||
const startPattern = new RegExp(`^## ${version}`);
|
||||
const stopPattern = /^## /; // 前一个版本
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const isWindows = require('is-windows');
|
||||
|
||||
module.exports = function getRunCmdEnv() {
|
||||
const env = {};
|
||||
|
@ -11,16 +12,12 @@ module.exports = function getRunCmdEnv() {
|
|||
const nodeModulesBinDir = path.join(__dirname, '../../node_modules/.bin');
|
||||
|
||||
Object.entries(env)
|
||||
.filter(
|
||||
v =>
|
||||
v
|
||||
.slice(0, 1)
|
||||
.pop()
|
||||
.toLowerCase() === 'path',
|
||||
)
|
||||
.filter(v => v.slice(0, 1).pop().toLowerCase() === 'path')
|
||||
.forEach(v => {
|
||||
const key = v.slice(0, 1).pop();
|
||||
env[key] = env[key] ? `${nodeModulesBinDir}:${env[key]}` : nodeModulesBinDir;
|
||||
env[key] = env[key]
|
||||
? `${nodeModulesBinDir}${isWindows() ? ';' : ':'}${env[key]}`
|
||||
: nodeModulesBinDir;
|
||||
});
|
||||
return env;
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@ function resolve(moduleName) {
|
|||
|
||||
// We need hack the require to ensure use package module first
|
||||
// For example, `typescript` is required by `gulp-typescript` but provided by `antd`
|
||||
// we do not need for ant-design-vue
|
||||
let injected = false;
|
||||
function injectRequire() {
|
||||
if (injected) return;
|
||||
|
@ -45,9 +46,35 @@ function getConfig() {
|
|||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在可用的browserslist config
|
||||
* https://github.com/browserslist/browserslist#queries
|
||||
* @returns
|
||||
*/
|
||||
function isThereHaveBrowserslistConfig() {
|
||||
try {
|
||||
const packageJson = require(getProjectPath('package.json'));
|
||||
if (packageJson.browserslist) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
if (fs.existsSync(getProjectPath('.browserslistrc'))) {
|
||||
return true;
|
||||
}
|
||||
if (fs.existsSync(getProjectPath('browserslist'))) {
|
||||
return true;
|
||||
}
|
||||
// parent项目的配置支持,需要再补充
|
||||
// ROWSERSLIST ROWSERSLIST_ENV 变量的形式,需要再补充。
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getProjectPath,
|
||||
resolve,
|
||||
injectRequire,
|
||||
getConfig,
|
||||
isThereHaveBrowserslistConfig,
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
test: {
|
||||
presets: [['@babel/preset-env', { targets: { node: true } }]],
|
||||
presets: [['@babel/preset-env']],
|
||||
plugins: [
|
||||
['@vue/babel-plugin-jsx', { mergeProps: false, enableObjectSlots: false }],
|
||||
'@babel/plugin-proposal-optional-chaining',
|
||||
|
@ -12,6 +12,7 @@ module.exports = {
|
|||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-transform-runtime',
|
||||
'transform-require-context',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
import type { ExtractPropTypes, PropType } from 'vue';
|
||||
import { shallowRef, onMounted, defineComponent, onBeforeUnmount } from 'vue';
|
||||
import Button from '../button';
|
||||
import type { ButtonProps } from '../button';
|
||||
import type { LegacyButtonType } from '../button/buttonTypes';
|
||||
import { convertLegacyProps } from '../button/buttonTypes';
|
||||
import useDestroyed from './hooks/useDestroyed';
|
||||
import { objectType } from './type';
|
||||
import { findDOMNode } from './props-util';
|
||||
|
||||
const actionButtonProps = {
|
||||
type: {
|
||||
type: String as PropType<LegacyButtonType>,
|
||||
},
|
||||
actionFn: Function as PropType<(...args: any[]) => any | PromiseLike<any>>,
|
||||
close: Function,
|
||||
autofocus: Boolean,
|
||||
prefixCls: String,
|
||||
buttonProps: objectType<ButtonProps>(),
|
||||
emitEvent: Boolean,
|
||||
quitOnNullishReturnValue: Boolean,
|
||||
};
|
||||
|
||||
export type ActionButtonProps = ExtractPropTypes<typeof actionButtonProps>;
|
||||
|
||||
function isThenable<T>(thing?: PromiseLike<T>): boolean {
|
||||
return !!(thing && thing.then);
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
compatConfig: { MODE: 3 },
|
||||
name: 'ActionButton',
|
||||
props: actionButtonProps,
|
||||
setup(props, { slots }) {
|
||||
const clickedRef = shallowRef<boolean>(false);
|
||||
const buttonRef = shallowRef();
|
||||
const loading = shallowRef(false);
|
||||
let timeoutId: any;
|
||||
const isDestroyed = useDestroyed();
|
||||
onMounted(() => {
|
||||
if (props.autofocus) {
|
||||
timeoutId = setTimeout(() => findDOMNode(buttonRef.value)?.focus?.());
|
||||
}
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
clearTimeout(timeoutId);
|
||||
});
|
||||
|
||||
const onInternalClose = (...args: any[]) => {
|
||||
props.close?.(...args);
|
||||
};
|
||||
|
||||
const handlePromiseOnOk = (returnValueOfOnOk?: PromiseLike<any>) => {
|
||||
if (!isThenable(returnValueOfOnOk)) {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
returnValueOfOnOk!.then(
|
||||
(...args: any[]) => {
|
||||
if (!isDestroyed.value) {
|
||||
loading.value = false;
|
||||
}
|
||||
onInternalClose(...args);
|
||||
clickedRef.value = false;
|
||||
},
|
||||
(e: Error) => {
|
||||
// See: https://github.com/ant-design/ant-design/issues/6183
|
||||
if (!isDestroyed.value) {
|
||||
loading.value = false;
|
||||
}
|
||||
clickedRef.value = false;
|
||||
return Promise.reject(e);
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const onClick = (e: MouseEvent) => {
|
||||
const { actionFn } = props;
|
||||
if (clickedRef.value) {
|
||||
return;
|
||||
}
|
||||
clickedRef.value = true;
|
||||
if (!actionFn) {
|
||||
onInternalClose();
|
||||
return;
|
||||
}
|
||||
let returnValueOfOnOk: PromiseLike<any>;
|
||||
if (props.emitEvent) {
|
||||
returnValueOfOnOk = actionFn(e);
|
||||
if (props.quitOnNullishReturnValue && !isThenable(returnValueOfOnOk)) {
|
||||
clickedRef.value = false;
|
||||
onInternalClose(e);
|
||||
return;
|
||||
}
|
||||
} else if (actionFn.length) {
|
||||
returnValueOfOnOk = actionFn(props.close);
|
||||
// https://github.com/ant-design/ant-design/issues/23358
|
||||
clickedRef.value = false;
|
||||
} else {
|
||||
returnValueOfOnOk = actionFn();
|
||||
if (!returnValueOfOnOk) {
|
||||
onInternalClose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
handlePromiseOnOk(returnValueOfOnOk);
|
||||
};
|
||||
return () => {
|
||||
const { type, prefixCls, buttonProps } = props;
|
||||
return (
|
||||
<Button
|
||||
{...convertLegacyProps(type)}
|
||||
onClick={onClick}
|
||||
loading={loading.value}
|
||||
prefixCls={prefixCls}
|
||||
{...buttonProps}
|
||||
ref={buttonRef}
|
||||
v-slots={slots}
|
||||
></Button>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
|
@ -1,50 +1,167 @@
|
|||
import { defineComponent, ref, withDirectives } from 'vue';
|
||||
import antInput from './antInputDirective';
|
||||
import type { PropType } from 'vue';
|
||||
import { computed, defineComponent, shallowRef, ref, watch } from 'vue';
|
||||
import PropTypes from './vue-types';
|
||||
const BaseInput = defineComponent({
|
||||
props: {
|
||||
value: PropTypes.string.def(''),
|
||||
},
|
||||
emits: ['change', 'input'],
|
||||
setup(_p, { emit }) {
|
||||
const inputRef = ref(null);
|
||||
const handleChange = (e: Event) => {
|
||||
const { composing } = e.target as any;
|
||||
if ((e as any).isComposing || composing) {
|
||||
emit('input', e);
|
||||
} else {
|
||||
emit('input', e);
|
||||
emit('change', e);
|
||||
import type { BaseInputInnerExpose } from './BaseInputInner';
|
||||
import BaseInputInner from './BaseInputInner';
|
||||
import { styleObjectToString } from '../vc-util/Dom/css';
|
||||
|
||||
export interface BaseInputExpose {
|
||||
focus: () => void;
|
||||
blur: () => void;
|
||||
input: HTMLInputElement | HTMLTextAreaElement | null;
|
||||
setSelectionRange: (
|
||||
start: number,
|
||||
end: number,
|
||||
direction?: 'forward' | 'backward' | 'none',
|
||||
) => void;
|
||||
select: () => void;
|
||||
getSelectionStart: () => number | null;
|
||||
getSelectionEnd: () => number | null;
|
||||
getScrollTop: () => number | null;
|
||||
setScrollTop: (scrollTop: number) => void;
|
||||
}
|
||||
const BaseInput = defineComponent({
|
||||
compatConfig: { MODE: 3 },
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
disabled: PropTypes.looseBool,
|
||||
type: PropTypes.string,
|
||||
value: PropTypes.any,
|
||||
lazy: PropTypes.bool.def(true),
|
||||
tag: {
|
||||
type: String as PropType<'input' | 'textarea'>,
|
||||
default: 'input',
|
||||
},
|
||||
size: PropTypes.string,
|
||||
style: PropTypes.oneOfType([String, Object]),
|
||||
class: PropTypes.string,
|
||||
},
|
||||
emits: [
|
||||
'change',
|
||||
'input',
|
||||
'blur',
|
||||
'keydown',
|
||||
'focus',
|
||||
'compositionstart',
|
||||
'compositionend',
|
||||
'keyup',
|
||||
'paste',
|
||||
'mousedown',
|
||||
],
|
||||
setup(props, { emit, attrs, expose }) {
|
||||
const inputRef = shallowRef<BaseInputInnerExpose>(null);
|
||||
const renderValue = ref();
|
||||
const isComposing = ref(false);
|
||||
watch(
|
||||
[() => props.value, isComposing],
|
||||
() => {
|
||||
if (isComposing.value) return;
|
||||
renderValue.value = props.value;
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
const handleChange = (e: Event) => {
|
||||
emit('change', e);
|
||||
};
|
||||
return {
|
||||
inputRef,
|
||||
focus: () => {
|
||||
const onCompositionstart = (e: CompositionEvent) => {
|
||||
isComposing.value = true;
|
||||
(e.target as any).composing = true;
|
||||
emit('compositionstart', e);
|
||||
};
|
||||
const onCompositionend = (e: CompositionEvent) => {
|
||||
isComposing.value = false;
|
||||
(e.target as any).composing = false;
|
||||
emit('compositionend', e);
|
||||
const event = document.createEvent('HTMLEvents');
|
||||
event.initEvent('input', true, true);
|
||||
e.target.dispatchEvent(event);
|
||||
handleChange(e);
|
||||
};
|
||||
const handleInput = (e: Event) => {
|
||||
if (isComposing.value && props.lazy) {
|
||||
renderValue.value = (e.target as HTMLInputElement).value;
|
||||
return;
|
||||
}
|
||||
emit('input', e);
|
||||
};
|
||||
|
||||
const handleBlur = (e: Event) => {
|
||||
emit('blur', e);
|
||||
};
|
||||
const handleFocus = (e: Event) => {
|
||||
emit('focus', e);
|
||||
};
|
||||
|
||||
const focus = () => {
|
||||
if (inputRef.value) {
|
||||
inputRef.value.focus();
|
||||
}
|
||||
},
|
||||
blur: () => {
|
||||
};
|
||||
const blur = () => {
|
||||
if (inputRef.value) {
|
||||
inputRef.value.blur();
|
||||
}
|
||||
},
|
||||
handleChange,
|
||||
};
|
||||
},
|
||||
render() {
|
||||
return withDirectives(
|
||||
(
|
||||
<input
|
||||
{...this.$props}
|
||||
{...this.$attrs}
|
||||
onInput={this.handleChange}
|
||||
onChange={this.handleChange}
|
||||
ref="inputRef"
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
emit('keydown', e);
|
||||
};
|
||||
const handleKeyUp = (e: KeyboardEvent) => {
|
||||
emit('keyup', e);
|
||||
};
|
||||
const setSelectionRange = (
|
||||
start: number,
|
||||
end: number,
|
||||
direction?: 'forward' | 'backward' | 'none',
|
||||
) => {
|
||||
inputRef.value?.setSelectionRange(start, end, direction);
|
||||
};
|
||||
|
||||
const select = () => {
|
||||
inputRef.value?.select();
|
||||
};
|
||||
expose({
|
||||
focus,
|
||||
blur,
|
||||
input: computed(() => inputRef.value?.input),
|
||||
setSelectionRange,
|
||||
select,
|
||||
getSelectionStart: () => inputRef.value?.getSelectionStart(),
|
||||
getSelectionEnd: () => inputRef.value?.getSelectionEnd(),
|
||||
getScrollTop: () => inputRef.value?.getScrollTop(),
|
||||
});
|
||||
const handleMousedown = (e: MouseEvent) => {
|
||||
emit('mousedown', e);
|
||||
};
|
||||
const handlePaste = (e: ClipboardEvent) => {
|
||||
emit('paste', e);
|
||||
};
|
||||
const styleString = computed(() => {
|
||||
return props.style && typeof props.style !== 'string'
|
||||
? styleObjectToString(props.style)
|
||||
: props.style;
|
||||
});
|
||||
return () => {
|
||||
const { style, lazy, ...restProps } = props;
|
||||
return (
|
||||
<BaseInputInner
|
||||
{...restProps}
|
||||
{...attrs}
|
||||
style={styleString.value}
|
||||
onInput={handleInput}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
onFocus={handleFocus}
|
||||
ref={inputRef}
|
||||
value={renderValue.value}
|
||||
onCompositionstart={onCompositionstart}
|
||||
onCompositionend={onCompositionend}
|
||||
onKeyup={handleKeyUp}
|
||||
onKeydown={handleKeyDown}
|
||||
onPaste={handlePaste}
|
||||
onMousedown={handleMousedown}
|
||||
/>
|
||||
) as any,
|
||||
[[antInput]],
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
import type { PropType } from 'vue';
|
||||
import { defineComponent, shallowRef } from 'vue';
|
||||
import PropTypes from './vue-types';
|
||||
|
||||
export interface BaseInputInnerExpose {
|
||||
focus: () => void;
|
||||
blur: () => void;
|
||||
input: HTMLInputElement | HTMLTextAreaElement | null;
|
||||
setSelectionRange: (
|
||||
start: number,
|
||||
end: number,
|
||||
direction?: 'forward' | 'backward' | 'none',
|
||||
) => void;
|
||||
select: () => void;
|
||||
getSelectionStart: () => number | null;
|
||||
getSelectionEnd: () => number | null;
|
||||
getScrollTop: () => number | null;
|
||||
setScrollTop: (scrollTop: number) => void;
|
||||
}
|
||||
const BaseInputInner = defineComponent({
|
||||
compatConfig: { MODE: 3 },
|
||||
// inheritAttrs: false,
|
||||
props: {
|
||||
disabled: PropTypes.looseBool,
|
||||
type: PropTypes.string,
|
||||
value: PropTypes.any,
|
||||
tag: {
|
||||
type: String as PropType<'input' | 'textarea'>,
|
||||
default: 'input',
|
||||
},
|
||||
size: PropTypes.string,
|
||||
onChange: Function as PropType<(e: Event) => void>,
|
||||
onInput: Function as PropType<(e: Event) => void>,
|
||||
onBlur: Function as PropType<(e: Event) => void>,
|
||||
onFocus: Function as PropType<(e: Event) => void>,
|
||||
onKeydown: Function as PropType<(e: Event) => void>,
|
||||
onCompositionstart: Function as PropType<(e: Event) => void>,
|
||||
onCompositionend: Function as PropType<(e: Event) => void>,
|
||||
onKeyup: Function as PropType<(e: Event) => void>,
|
||||
onPaste: Function as PropType<(e: Event) => void>,
|
||||
onMousedown: Function as PropType<(e: Event) => void>,
|
||||
},
|
||||
emits: [
|
||||
'change',
|
||||
'input',
|
||||
'blur',
|
||||
'keydown',
|
||||
'focus',
|
||||
'compositionstart',
|
||||
'compositionend',
|
||||
'keyup',
|
||||
'paste',
|
||||
'mousedown',
|
||||
],
|
||||
setup(props, { expose }) {
|
||||
const inputRef = shallowRef(null);
|
||||
|
||||
const focus = () => {
|
||||
if (inputRef.value) {
|
||||
inputRef.value.focus();
|
||||
}
|
||||
};
|
||||
const blur = () => {
|
||||
if (inputRef.value) {
|
||||
inputRef.value.blur();
|
||||
}
|
||||
};
|
||||
const setSelectionRange = (
|
||||
start: number,
|
||||
end: number,
|
||||
direction?: 'forward' | 'backward' | 'none',
|
||||
) => {
|
||||
inputRef.value?.setSelectionRange(start, end, direction);
|
||||
};
|
||||
|
||||
const select = () => {
|
||||
inputRef.value?.select();
|
||||
};
|
||||
expose({
|
||||
focus,
|
||||
blur,
|
||||
input: inputRef,
|
||||
setSelectionRange,
|
||||
select,
|
||||
getSelectionStart: () => inputRef.value?.selectionStart,
|
||||
getSelectionEnd: () => inputRef.value?.selectionEnd,
|
||||
getScrollTop: () => inputRef.value?.scrollTop,
|
||||
});
|
||||
return () => {
|
||||
const { tag: Tag, value, ...restProps } = props;
|
||||
return <Tag {...restProps} ref={inputRef} value={value} />;
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default BaseInputInner;
|
|
@ -3,7 +3,7 @@ import { getOptionProps } from './props-util';
|
|||
|
||||
export default {
|
||||
methods: {
|
||||
setState(state = {}, callback) {
|
||||
setState(state = {}, callback: () => any) {
|
||||
let newState = typeof state === 'function' ? state(this.$data, this.$props) : state;
|
||||
if (this.getDerivedStateFromProps) {
|
||||
const s = this.getDerivedStateFromProps(getOptionProps(this), {
|
||||
|
@ -26,6 +26,7 @@ export default {
|
|||
},
|
||||
__emit() {
|
||||
// 直接调用事件,底层组件不需要vueTool记录events
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
const args = [].slice.call(arguments, 0);
|
||||
let eventName = args[0];
|
||||
eventName = `on${eventName[0].toUpperCase()}${eventName.substring(1)}`;
|
|
@ -1,10 +1,19 @@
|
|||
export type FocusEventHandler = (e: FocusEvent) => void;
|
||||
export type MouseEventHandler = (e: MouseEvent) => void;
|
||||
export type KeyboardEventHandler = (e: KeyboardEvent) => void;
|
||||
export type CompositionEventHandler = (e: CompositionEvent) => void;
|
||||
export type ClipboardEventHandler = (e: ClipboardEvent) => void;
|
||||
export type ChangeEventHandler = (e: ChangeEvent) => void;
|
||||
export type WheelEventHandler = (e: WheelEvent) => void;
|
||||
export type ChangeEvent = Event & {
|
||||
target: {
|
||||
value?: string | undefined;
|
||||
};
|
||||
};
|
||||
export type CheckboxChangeEvent = Event & {
|
||||
target: {
|
||||
checked?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export type EventHandler = (...args: any[]) => void;
|
||||
|
|
|
@ -1,28 +1,71 @@
|
|||
import PropTypes from './vue-types';
|
||||
import { defineComponent, nextTick, onBeforeUnmount, onUpdated, Teleport } from 'vue';
|
||||
import {
|
||||
defineComponent,
|
||||
nextTick,
|
||||
onBeforeMount,
|
||||
onMounted,
|
||||
onUpdated,
|
||||
Teleport,
|
||||
watch,
|
||||
} from 'vue';
|
||||
import { useInjectPortal } from '../vc-trigger/context';
|
||||
|
||||
export default defineComponent({
|
||||
compatConfig: { MODE: 3 },
|
||||
name: 'Portal',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
getContainer: PropTypes.func.isRequired,
|
||||
didUpdate: PropTypes.func,
|
||||
didUpdate: Function,
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
let isSSR = true;
|
||||
// getContainer 不会改变,不用响应式
|
||||
const container = props.getContainer();
|
||||
let container: HTMLElement;
|
||||
const { shouldRender } = useInjectPortal();
|
||||
|
||||
onUpdated(() => {
|
||||
nextTick(() => {
|
||||
props.didUpdate?.(props);
|
||||
function setContainer() {
|
||||
if (shouldRender.value) {
|
||||
container = props.getContainer();
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
isSSR = false;
|
||||
// drawer
|
||||
setContainer();
|
||||
});
|
||||
onMounted(() => {
|
||||
if (container) return;
|
||||
// https://github.com/vueComponent/ant-design-vue/issues/6937
|
||||
setContainer();
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
if (container && container.parentNode) {
|
||||
container.parentNode.removeChild(container);
|
||||
|
||||
const stopWatch = watch(shouldRender, () => {
|
||||
if (shouldRender.value && !container) {
|
||||
container = props.getContainer();
|
||||
}
|
||||
if (container) {
|
||||
stopWatch();
|
||||
}
|
||||
});
|
||||
onUpdated(() => {
|
||||
nextTick(() => {
|
||||
if (shouldRender.value) {
|
||||
props.didUpdate?.(props);
|
||||
}
|
||||
});
|
||||
});
|
||||
// onBeforeUnmount(() => {
|
||||
// if (container && container.parentNode) {
|
||||
// container.parentNode.removeChild(container);
|
||||
// }
|
||||
// });
|
||||
return () => {
|
||||
if (!shouldRender.value) return null;
|
||||
if (isSSR) {
|
||||
return slots.default?.();
|
||||
}
|
||||
return container ? <Teleport to={container} v-slots={slots}></Teleport> : null;
|
||||
};
|
||||
},
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
import PropTypes from './vue-types';
|
||||
import switchScrollingEffect from './switchScrollingEffect';
|
||||
import setStyle from './setStyle';
|
||||
import Portal from './Portal';
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
shallowRef,
|
||||
watch,
|
||||
onMounted,
|
||||
onBeforeUnmount,
|
||||
onUpdated,
|
||||
getCurrentInstance,
|
||||
nextTick,
|
||||
computed,
|
||||
} from 'vue';
|
||||
import canUseDom from './canUseDom';
|
||||
import ScrollLocker from '../vc-util/Dom/scrollLocker';
|
||||
import wrapperRaf from './raf';
|
||||
import { nextTick } from 'process';
|
||||
import raf from './raf';
|
||||
import { booleanType } from './type';
|
||||
import useScrollLocker from './hooks/useScrollLocker';
|
||||
|
||||
let openCount = 0;
|
||||
const supportDom = canUseDom();
|
||||
|
@ -24,17 +23,13 @@ export function getOpenCount() {
|
|||
return process.env.NODE_ENV === 'test' ? openCount : 0;
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/19340
|
||||
// https://github.com/ant-design/ant-design/issues/19332
|
||||
let cacheOverflow = {};
|
||||
|
||||
const getParent = (getContainer: GetContainer) => {
|
||||
if (!supportDom) {
|
||||
return null;
|
||||
}
|
||||
if (getContainer) {
|
||||
if (typeof getContainer === 'string') {
|
||||
return document.querySelectorAll(getContainer)[0];
|
||||
return document.querySelectorAll(getContainer)[0] as HTMLElement;
|
||||
}
|
||||
if (typeof getContainer === 'function') {
|
||||
return getContainer();
|
||||
|
@ -49,31 +44,36 @@ const getParent = (getContainer: GetContainer) => {
|
|||
export type GetContainer = string | HTMLElement | (() => HTMLElement);
|
||||
|
||||
export default defineComponent({
|
||||
compatConfig: { MODE: 3 },
|
||||
name: 'PortalWrapper',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
wrapperClassName: PropTypes.string,
|
||||
forceRender: PropTypes.looseBool,
|
||||
wrapperClassName: String,
|
||||
forceRender: { type: Boolean, default: undefined },
|
||||
getContainer: PropTypes.any,
|
||||
visible: PropTypes.looseBool,
|
||||
visible: { type: Boolean, default: undefined },
|
||||
autoLock: booleanType(),
|
||||
didUpdate: Function,
|
||||
},
|
||||
|
||||
setup(props, { slots }) {
|
||||
const container = ref<HTMLElement>();
|
||||
const componentRef = ref();
|
||||
const rafId = ref<number>();
|
||||
const scrollLocker = new ScrollLocker({
|
||||
container: getParent(props.getContainer) as HTMLElement,
|
||||
});
|
||||
|
||||
const container = shallowRef<HTMLElement>();
|
||||
const componentRef = shallowRef();
|
||||
const rafId = shallowRef<number>();
|
||||
const triggerUpdate = shallowRef(1);
|
||||
const defaultContainer = canUseDom() && document.createElement('div');
|
||||
const removeCurrentContainer = () => {
|
||||
// Portal will remove from `parentNode`.
|
||||
// Let's handle this again to avoid refactor issue.
|
||||
if (container.value === defaultContainer) {
|
||||
container.value?.parentNode?.removeChild(container.value);
|
||||
}
|
||||
container.value = null;
|
||||
};
|
||||
let parent: HTMLElement = null;
|
||||
const attachToParent = (force = false) => {
|
||||
if (force || (container.value && !container.value.parentNode)) {
|
||||
const parent = getParent(props.getContainer);
|
||||
parent = getParent(props.getContainer);
|
||||
if (parent) {
|
||||
parent.appendChild(container.value);
|
||||
return true;
|
||||
|
@ -84,14 +84,12 @@ export default defineComponent({
|
|||
|
||||
return true;
|
||||
};
|
||||
// attachToParent();
|
||||
|
||||
const getContainer = () => {
|
||||
if (!supportDom) {
|
||||
return null;
|
||||
}
|
||||
if (!container.value) {
|
||||
container.value = document.createElement('div');
|
||||
container.value = defaultContainer;
|
||||
attachToParent(true);
|
||||
}
|
||||
setWrapperClassName();
|
||||
|
@ -107,43 +105,33 @@ export default defineComponent({
|
|||
setWrapperClassName();
|
||||
attachToParent();
|
||||
});
|
||||
/**
|
||||
* Enhance ./switchScrollingEffect
|
||||
* 1. Simulate document body scroll bar with
|
||||
* 2. Record body has overflow style and recover when all of PortalWrapper invisible
|
||||
* 3. Disable body scroll when PortalWrapper has open
|
||||
*
|
||||
* @memberof PortalWrapper
|
||||
*/
|
||||
const switchScrolling = () => {
|
||||
if (openCount === 1 && !Object.keys(cacheOverflow).length) {
|
||||
switchScrollingEffect();
|
||||
// Must be set after switchScrollingEffect
|
||||
cacheOverflow = setStyle({
|
||||
overflow: 'hidden',
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'hidden',
|
||||
});
|
||||
} else if (!openCount) {
|
||||
setStyle(cacheOverflow);
|
||||
cacheOverflow = {};
|
||||
switchScrollingEffect(true);
|
||||
}
|
||||
};
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
useScrollLocker(
|
||||
computed(() => {
|
||||
return (
|
||||
props.autoLock &&
|
||||
props.visible &&
|
||||
canUseDom() &&
|
||||
(container.value === document.body || container.value === defaultContainer)
|
||||
);
|
||||
}),
|
||||
);
|
||||
onMounted(() => {
|
||||
let init = false;
|
||||
watch(
|
||||
[() => props.visible, () => props.getContainer],
|
||||
([visible, getContainer], [prevVisible, prevGetContainer]) => {
|
||||
// Update count
|
||||
if (supportDom && getParent(props.getContainer) === document.body) {
|
||||
if (supportDom) {
|
||||
parent = getParent(props.getContainer);
|
||||
if (parent === document.body) {
|
||||
if (visible && !prevVisible) {
|
||||
openCount += 1;
|
||||
} else if (init) {
|
||||
openCount -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (init) {
|
||||
// Clean up container if needed
|
||||
|
@ -156,17 +144,6 @@ export default defineComponent({
|
|||
) {
|
||||
removeCurrentContainer();
|
||||
}
|
||||
// updateScrollLocker
|
||||
if (
|
||||
visible &&
|
||||
visible !== prevVisible &&
|
||||
supportDom &&
|
||||
getParent(getContainer) !== scrollLocker.getContainer()
|
||||
) {
|
||||
scrollLocker.reLock({
|
||||
container: getParent(getContainer) as HTMLElement,
|
||||
});
|
||||
}
|
||||
}
|
||||
init = true;
|
||||
},
|
||||
|
@ -175,38 +152,35 @@ export default defineComponent({
|
|||
|
||||
nextTick(() => {
|
||||
if (!attachToParent()) {
|
||||
rafId.value = wrapperRaf(() => {
|
||||
instance.update();
|
||||
rafId.value = raf(() => {
|
||||
triggerUpdate.value += 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
const { visible, getContainer } = props;
|
||||
if (supportDom && getParent(getContainer) === document.body) {
|
||||
const { visible } = props;
|
||||
if (supportDom && parent === document.body) {
|
||||
// 离开时不会 render, 导到离开时数值不变,改用 func 。。
|
||||
openCount = visible && openCount ? openCount - 1 : openCount;
|
||||
}
|
||||
removeCurrentContainer();
|
||||
wrapperRaf.cancel(rafId.value);
|
||||
raf.cancel(rafId.value);
|
||||
});
|
||||
|
||||
return () => {
|
||||
const { forceRender, visible } = props;
|
||||
let portal = null;
|
||||
const childProps = {
|
||||
getOpenCount: () => openCount,
|
||||
getContainer,
|
||||
switchScrollingEffect: switchScrolling,
|
||||
scrollLocker,
|
||||
};
|
||||
|
||||
if (forceRender || visible || componentRef.value) {
|
||||
if (triggerUpdate.value && (forceRender || visible || componentRef.value)) {
|
||||
portal = (
|
||||
<Portal
|
||||
getContainer={getContainer}
|
||||
ref={componentRef}
|
||||
didUpdate={props.didUpdate}
|
||||
v-slots={{ default: () => slots.default?.(childProps) }}
|
||||
></Portal>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
compatConfig: { MODE: 3 },
|
||||
name: 'Portal',
|
||||
inheritAttrs: false,
|
||||
props: ['getContainer'],
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { defineComponent } from 'vue';
|
||||
import { customRenderSlot } from '../vnode';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RenderSlot',
|
||||
setup(_props, { slots }) {
|
||||
return () => {
|
||||
return customRenderSlot(slots, 'default', {}, () => ['default value']);
|
||||
};
|
||||
},
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
import UnreachableException from '../unreachableException';
|
||||
|
||||
describe('UnreachableException', () => {
|
||||
it('error thrown matches snapshot', () => {
|
||||
const exception = new UnreachableException('some value');
|
||||
expect(exception.error.message).toMatchInlineSnapshot(`"unreachable case: \\"some value\\""`);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,26 @@
|
|||
import RenderSlot from '../__mocks__/RenderSlot';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
describe('render slot content', () => {
|
||||
it('renders slot content', () => {
|
||||
const wrapper = mount(RenderSlot, {
|
||||
slots: {
|
||||
default: () => 'This is slot content',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toContain('This is slot content');
|
||||
});
|
||||
|
||||
it('render default value when slot is fragment', async () => {
|
||||
const wrapper = mount(RenderSlot, {
|
||||
slots: {
|
||||
default: () => <></>,
|
||||
},
|
||||
});
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.html()).toContain('default value');
|
||||
});
|
||||
});
|
|
@ -1,35 +0,0 @@
|
|||
function onCompositionStart(e) {
|
||||
e.target.composing = true;
|
||||
}
|
||||
|
||||
function onCompositionEnd(e) {
|
||||
// prevent triggering an input event for no reason
|
||||
if (!e.target.composing) return;
|
||||
e.target.composing = false;
|
||||
trigger(e.target, 'input');
|
||||
}
|
||||
|
||||
function trigger(el, type) {
|
||||
const e = document.createEvent('HTMLEvents');
|
||||
e.initEvent(type, true, true);
|
||||
el.dispatchEvent(e);
|
||||
}
|
||||
|
||||
export function addEventListener(el, event, handler, options) {
|
||||
el.addEventListener(event, handler, options);
|
||||
}
|
||||
const antInput = {
|
||||
created(el, binding) {
|
||||
if (!binding.modifiers || !binding.modifiers.lazy) {
|
||||
addEventListener(el, 'compositionstart', onCompositionStart);
|
||||
addEventListener(el, 'compositionend', onCompositionEnd);
|
||||
// Safari < 10.2 & UIWebView doesn't fire compositionend when
|
||||
// switching focus before confirming composition choice
|
||||
// this also fixes the issue where some browsers e.g. iOS Chrome
|
||||
// fires "change" instead of "input" on autocomplete.
|
||||
addEventListener(el, 'change', onCompositionEnd);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default antInput;
|
|
@ -0,0 +1,50 @@
|
|||
import { nextTick } from 'vue';
|
||||
import { addClass, removeClass } from '../vc-util/Dom/class';
|
||||
import type { CSSMotionProps } from './transition';
|
||||
|
||||
const collapseMotion = (name = 'ant-motion-collapse', appear = true): CSSMotionProps => {
|
||||
return {
|
||||
name,
|
||||
appear,
|
||||
css: true,
|
||||
onBeforeEnter: (node: HTMLDivElement) => {
|
||||
node.style.height = '0px';
|
||||
node.style.opacity = '0';
|
||||
addClass(node, name);
|
||||
},
|
||||
onEnter: (node: HTMLDivElement) => {
|
||||
nextTick(() => {
|
||||
node.style.height = `${node.scrollHeight}px`;
|
||||
node.style.opacity = '1';
|
||||
});
|
||||
},
|
||||
onAfterEnter: (node: HTMLDivElement) => {
|
||||
if (node) {
|
||||
removeClass(node, name);
|
||||
node.style.height = null;
|
||||
node.style.opacity = null;
|
||||
}
|
||||
},
|
||||
onBeforeLeave: (node: HTMLDivElement) => {
|
||||
addClass(node, name);
|
||||
node.style.height = `${node.offsetHeight}px`;
|
||||
node.style.opacity = null;
|
||||
},
|
||||
onLeave: (node: HTMLDivElement) => {
|
||||
setTimeout(() => {
|
||||
node.style.height = '0px';
|
||||
node.style.opacity = '0';
|
||||
});
|
||||
},
|
||||
onAfterLeave: (node: HTMLDivElement) => {
|
||||
if (node) {
|
||||
removeClass(node, name);
|
||||
if (node.style) {
|
||||
node.style.height = null;
|
||||
node.style.opacity = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
export default collapseMotion;
|
|
@ -1,23 +1,34 @@
|
|||
import type { ElementOf } from './type';
|
||||
import { tuple } from './type';
|
||||
import type { PresetColorKey } from '../theme/interface';
|
||||
import { PresetColors } from '../theme/interface';
|
||||
|
||||
export const PresetStatusColorTypes = tuple('success', 'processing', 'error', 'default', 'warning');
|
||||
type InverseColor = `${PresetColorKey}-inverse`;
|
||||
const inverseColors = PresetColors.map<InverseColor>(color => `${color}-inverse`);
|
||||
|
||||
export const PresetColorTypes = tuple(
|
||||
'pink',
|
||||
'red',
|
||||
'yellow',
|
||||
'orange',
|
||||
'cyan',
|
||||
'green',
|
||||
'blue',
|
||||
'purple',
|
||||
'geekblue',
|
||||
'magenta',
|
||||
'volcano',
|
||||
'gold',
|
||||
'lime',
|
||||
);
|
||||
export const PresetStatusColorTypes = [
|
||||
'success',
|
||||
'processing',
|
||||
'error',
|
||||
'default',
|
||||
'warning',
|
||||
] as const;
|
||||
|
||||
export type PresetColorType = ElementOf<typeof PresetColorTypes>;
|
||||
export type PresetStatusColorType = ElementOf<typeof PresetStatusColorTypes>;
|
||||
export type PresetColorType = PresetColorKey | InverseColor;
|
||||
|
||||
export type PresetStatusColorType = (typeof PresetStatusColorTypes)[number];
|
||||
|
||||
/**
|
||||
* determine if the color keyword belongs to the `Ant Design` {@link PresetColors}.
|
||||
* @param color color to be judged
|
||||
* @param includeInverse whether to include reversed colors
|
||||
*/
|
||||
export function isPresetColor(color?: any, includeInverse = true) {
|
||||
if (includeInverse) {
|
||||
return [...inverseColors, ...PresetColors].includes(color);
|
||||
}
|
||||
|
||||
return PresetColors.includes(color);
|
||||
}
|
||||
|
||||
export function isPresetStatusColor(color?: any): color is PresetStatusColorType {
|
||||
return PresetStatusColorTypes.includes(color);
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/**
|
||||
* Safe chained function
|
||||
*
|
||||
* Will only create a new function if needed,
|
||||
* otherwise will pass back existing functions or null.
|
||||
*
|
||||
* @returns {function|null}
|
||||
*/
|
||||
export default function createChainedFunction() {
|
||||
const args = [].slice.call(arguments, 0);
|
||||
if (args.length === 1) {
|
||||
return args[0];
|
||||
}
|
||||
|
||||
return function chainedFunction() {
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] && args[i].apply) {
|
||||
args[i].apply(this, arguments);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import { inject, provide, reactive, watchEffect } from 'vue';
|
||||
|
||||
function createContext<T extends Record<string, any>>(defaultValue?: T) {
|
||||
const contextKey = Symbol('contextKey');
|
||||
const useProvide = (props: T, newProps?: T) => {
|
||||
const mergedProps = reactive<T>({} as T);
|
||||
provide(contextKey, mergedProps);
|
||||
watchEffect(() => {
|
||||
Object.assign(mergedProps, props, newProps || {});
|
||||
});
|
||||
return mergedProps;
|
||||
};
|
||||
const useInject = () => {
|
||||
return inject(contextKey, defaultValue as T) || ({} as T);
|
||||
};
|
||||
return {
|
||||
useProvide,
|
||||
useInject,
|
||||
};
|
||||
}
|
||||
|
||||
export default createContext;
|
|
@ -1,130 +0,0 @@
|
|||
const START_EVENT_NAME_MAP = {
|
||||
transitionstart: {
|
||||
transition: 'transitionstart',
|
||||
WebkitTransition: 'webkitTransitionStart',
|
||||
MozTransition: 'mozTransitionStart',
|
||||
OTransition: 'oTransitionStart',
|
||||
msTransition: 'MSTransitionStart',
|
||||
},
|
||||
|
||||
animationstart: {
|
||||
animation: 'animationstart',
|
||||
WebkitAnimation: 'webkitAnimationStart',
|
||||
MozAnimation: 'mozAnimationStart',
|
||||
OAnimation: 'oAnimationStart',
|
||||
msAnimation: 'MSAnimationStart',
|
||||
},
|
||||
};
|
||||
|
||||
const END_EVENT_NAME_MAP = {
|
||||
transitionend: {
|
||||
transition: 'transitionend',
|
||||
WebkitTransition: 'webkitTransitionEnd',
|
||||
MozTransition: 'mozTransitionEnd',
|
||||
OTransition: 'oTransitionEnd',
|
||||
msTransition: 'MSTransitionEnd',
|
||||
},
|
||||
|
||||
animationend: {
|
||||
animation: 'animationend',
|
||||
WebkitAnimation: 'webkitAnimationEnd',
|
||||
MozAnimation: 'mozAnimationEnd',
|
||||
OAnimation: 'oAnimationEnd',
|
||||
msAnimation: 'MSAnimationEnd',
|
||||
},
|
||||
};
|
||||
|
||||
const startEvents = [];
|
||||
const endEvents = [];
|
||||
|
||||
function detectEvents() {
|
||||
const testEl = document.createElement('div');
|
||||
const style = testEl.style;
|
||||
|
||||
if (!('AnimationEvent' in window)) {
|
||||
delete START_EVENT_NAME_MAP.animationstart.animation;
|
||||
delete END_EVENT_NAME_MAP.animationend.animation;
|
||||
}
|
||||
|
||||
if (!('TransitionEvent' in window)) {
|
||||
delete START_EVENT_NAME_MAP.transitionstart.transition;
|
||||
delete END_EVENT_NAME_MAP.transitionend.transition;
|
||||
}
|
||||
|
||||
function process(EVENT_NAME_MAP, events) {
|
||||
for (const baseEventName in EVENT_NAME_MAP) {
|
||||
if (EVENT_NAME_MAP.hasOwnProperty(baseEventName)) {
|
||||
const baseEvents = EVENT_NAME_MAP[baseEventName];
|
||||
for (const styleName in baseEvents) {
|
||||
if (styleName in style) {
|
||||
events.push(baseEvents[styleName]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process(START_EVENT_NAME_MAP, startEvents);
|
||||
process(END_EVENT_NAME_MAP, endEvents);
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
||||
detectEvents();
|
||||
}
|
||||
|
||||
function addEventListener(node, eventName, eventListener) {
|
||||
node.addEventListener(eventName, eventListener, false);
|
||||
}
|
||||
|
||||
function removeEventListener(node, eventName, eventListener) {
|
||||
node.removeEventListener(eventName, eventListener, false);
|
||||
}
|
||||
|
||||
const TransitionEvents = {
|
||||
// Start events
|
||||
startEvents,
|
||||
|
||||
addStartEventListener(node, eventListener) {
|
||||
if (startEvents.length === 0) {
|
||||
window.setTimeout(eventListener, 0);
|
||||
return;
|
||||
}
|
||||
startEvents.forEach(startEvent => {
|
||||
addEventListener(node, startEvent, eventListener);
|
||||
});
|
||||
},
|
||||
|
||||
removeStartEventListener(node, eventListener) {
|
||||
if (startEvents.length === 0) {
|
||||
return;
|
||||
}
|
||||
startEvents.forEach(startEvent => {
|
||||
removeEventListener(node, startEvent, eventListener);
|
||||
});
|
||||
},
|
||||
|
||||
// End events
|
||||
endEvents,
|
||||
|
||||
addEndEventListener(node, eventListener) {
|
||||
if (endEvents.length === 0) {
|
||||
window.setTimeout(eventListener, 0);
|
||||
return;
|
||||
}
|
||||
endEvents.forEach(endEvent => {
|
||||
addEventListener(node, endEvent, eventListener);
|
||||
});
|
||||
},
|
||||
|
||||
removeEndEventListener(node, eventListener) {
|
||||
if (endEvents.length === 0) {
|
||||
return;
|
||||
}
|
||||
endEvents.forEach(endEvent => {
|
||||
removeEventListener(node, endEvent, eventListener);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default TransitionEvents;
|
|
@ -1,184 +0,0 @@
|
|||
// https://github.com/yiminghe/css-animation 1.5.0
|
||||
|
||||
import Event from './Event';
|
||||
import classes from '../component-classes';
|
||||
import { requestAnimationTimeout, cancelAnimationTimeout } from '../requestAnimationTimeout';
|
||||
|
||||
const isCssAnimationSupported = Event.endEvents.length !== 0;
|
||||
const capitalPrefixes = [
|
||||
'Webkit',
|
||||
'Moz',
|
||||
'O',
|
||||
// ms is special .... !
|
||||
'ms',
|
||||
];
|
||||
const prefixes = ['-webkit-', '-moz-', '-o-', 'ms-', ''];
|
||||
|
||||
function getStyleProperty(node, name) {
|
||||
// old ff need null, https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
|
||||
const style = window.getComputedStyle(node, null);
|
||||
let ret = '';
|
||||
for (let i = 0; i < prefixes.length; i++) {
|
||||
ret = style.getPropertyValue(prefixes[i] + name);
|
||||
if (ret) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function fixBrowserByTimeout(node) {
|
||||
if (isCssAnimationSupported) {
|
||||
const transitionDelay = parseFloat(getStyleProperty(node, 'transition-delay')) || 0;
|
||||
const transitionDuration = parseFloat(getStyleProperty(node, 'transition-duration')) || 0;
|
||||
const animationDelay = parseFloat(getStyleProperty(node, 'animation-delay')) || 0;
|
||||
const animationDuration = parseFloat(getStyleProperty(node, 'animation-duration')) || 0;
|
||||
const time = Math.max(transitionDuration + transitionDelay, animationDuration + animationDelay);
|
||||
// sometimes, browser bug
|
||||
node.rcEndAnimTimeout = setTimeout(() => {
|
||||
node.rcEndAnimTimeout = null;
|
||||
if (node.rcEndListener) {
|
||||
node.rcEndListener();
|
||||
}
|
||||
}, time * 1000 + 200);
|
||||
}
|
||||
}
|
||||
|
||||
function clearBrowserBugTimeout(node) {
|
||||
if (node.rcEndAnimTimeout) {
|
||||
clearTimeout(node.rcEndAnimTimeout);
|
||||
node.rcEndAnimTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
const cssAnimation = (node, transitionName, endCallback) => {
|
||||
const nameIsObj = typeof transitionName === 'object';
|
||||
const className = nameIsObj ? transitionName.name : transitionName;
|
||||
const activeClassName = nameIsObj ? transitionName.active : `${transitionName}-active`;
|
||||
let end = endCallback;
|
||||
let start;
|
||||
let active;
|
||||
const nodeClasses = classes(node);
|
||||
|
||||
if (endCallback && Object.prototype.toString.call(endCallback) === '[object Object]') {
|
||||
end = endCallback.end;
|
||||
start = endCallback.start;
|
||||
active = endCallback.active;
|
||||
}
|
||||
|
||||
if (node.rcEndListener) {
|
||||
node.rcEndListener();
|
||||
}
|
||||
|
||||
node.rcEndListener = e => {
|
||||
if (e && e.target !== node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.rcAnimTimeout) {
|
||||
cancelAnimationTimeout(node.rcAnimTimeout);
|
||||
node.rcAnimTimeout = null;
|
||||
}
|
||||
|
||||
clearBrowserBugTimeout(node);
|
||||
|
||||
nodeClasses.remove(className);
|
||||
nodeClasses.remove(activeClassName);
|
||||
|
||||
Event.removeEndEventListener(node, node.rcEndListener);
|
||||
node.rcEndListener = null;
|
||||
|
||||
// Usually this optional end is used for informing an owner of
|
||||
// a leave animation and telling it to remove the child.
|
||||
if (end) {
|
||||
end();
|
||||
}
|
||||
};
|
||||
|
||||
Event.addEndEventListener(node, node.rcEndListener);
|
||||
|
||||
if (start) {
|
||||
start();
|
||||
}
|
||||
nodeClasses.add(className);
|
||||
|
||||
node.rcAnimTimeout = requestAnimationTimeout(() => {
|
||||
node.rcAnimTimeout = null;
|
||||
|
||||
nodeClasses.add(className);
|
||||
nodeClasses.add(activeClassName);
|
||||
|
||||
if (active) {
|
||||
requestAnimationTimeout(active, 0);
|
||||
}
|
||||
fixBrowserByTimeout(node);
|
||||
// 30ms for firefox
|
||||
}, 30);
|
||||
|
||||
return {
|
||||
stop() {
|
||||
if (node.rcEndListener) {
|
||||
node.rcEndListener();
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
cssAnimation.style = (node, style, callback) => {
|
||||
if (node.rcEndListener) {
|
||||
node.rcEndListener();
|
||||
}
|
||||
|
||||
node.rcEndListener = e => {
|
||||
if (e && e.target !== node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.rcAnimTimeout) {
|
||||
cancelAnimationTimeout(node.rcAnimTimeout);
|
||||
node.rcAnimTimeout = null;
|
||||
}
|
||||
|
||||
clearBrowserBugTimeout(node);
|
||||
|
||||
Event.removeEndEventListener(node, node.rcEndListener);
|
||||
node.rcEndListener = null;
|
||||
|
||||
// Usually this optional callback is used for informing an owner of
|
||||
// a leave animation and telling it to remove the child.
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
Event.addEndEventListener(node, node.rcEndListener);
|
||||
|
||||
node.rcAnimTimeout = requestAnimationTimeout(() => {
|
||||
for (const s in style) {
|
||||
if (style.hasOwnProperty(s)) {
|
||||
node.style[s] = style[s];
|
||||
}
|
||||
}
|
||||
node.rcAnimTimeout = null;
|
||||
fixBrowserByTimeout(node);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
cssAnimation.setTransition = (node, p, value) => {
|
||||
let property = p;
|
||||
let v = value;
|
||||
if (value === undefined) {
|
||||
v = property;
|
||||
property = '';
|
||||
}
|
||||
property = property || '';
|
||||
capitalPrefixes.forEach(prefix => {
|
||||
node.style[`${prefix}Transition${property}`] = v;
|
||||
});
|
||||
};
|
||||
|
||||
cssAnimation.isCssAnimationSupported = isCssAnimationSupported;
|
||||
|
||||
export { isCssAnimationSupported };
|
||||
|
||||
export default cssAnimation;
|
|
@ -0,0 +1,29 @@
|
|||
export type KeyType = string | number;
|
||||
type ValueType = [number, any]; // [times, realValue]
|
||||
const SPLIT = '%';
|
||||
class Entity {
|
||||
instanceId: string;
|
||||
constructor(instanceId: string) {
|
||||
this.instanceId = instanceId;
|
||||
}
|
||||
/** @private Internal cache map. Do not access this directly */
|
||||
cache = new Map<string, ValueType>();
|
||||
|
||||
get(keys: KeyType[] | string): ValueType | null {
|
||||
return this.cache.get(Array.isArray(keys) ? keys.join(SPLIT) : keys) || null;
|
||||
}
|
||||
|
||||
update(keys: KeyType[] | string, valueFn: (origin: ValueType | null) => ValueType | null) {
|
||||
const path = Array.isArray(keys) ? keys.join(SPLIT) : keys;
|
||||
const prevValue = this.cache.get(path)!;
|
||||
const nextValue = valueFn(prevValue);
|
||||
|
||||
if (nextValue === null) {
|
||||
this.cache.delete(path);
|
||||
} else {
|
||||
this.cache.set(path, nextValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Entity;
|
|
@ -0,0 +1,19 @@
|
|||
import type { CSSInterpolation } from './hooks/useStyleRegister';
|
||||
|
||||
class Keyframe {
|
||||
private name: string;
|
||||
style: CSSInterpolation;
|
||||
|
||||
constructor(name: string, style: CSSInterpolation) {
|
||||
this.name = name;
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
getName(hashId = ''): string {
|
||||
return hashId ? `${hashId}-${this.name}` : this.name;
|
||||
}
|
||||
|
||||
_keyframe = true;
|
||||
}
|
||||
|
||||
export default Keyframe;
|
|
@ -0,0 +1,195 @@
|
|||
import type { ShallowRef, ExtractPropTypes, InjectionKey, Ref } from 'vue';
|
||||
import {
|
||||
provide,
|
||||
defineComponent,
|
||||
unref,
|
||||
inject,
|
||||
watch,
|
||||
shallowRef,
|
||||
getCurrentInstance,
|
||||
} from 'vue';
|
||||
import CacheEntity from './Cache';
|
||||
import type { Linter } from './linters/interface';
|
||||
import type { Transformer } from './transformers/interface';
|
||||
import { arrayType, booleanType, objectType, someType, stringType, withInstall } from '../type';
|
||||
export const ATTR_TOKEN = 'data-token-hash';
|
||||
export const ATTR_MARK = 'data-css-hash';
|
||||
export const ATTR_CACHE_PATH = 'data-cache-path';
|
||||
|
||||
// Mark css-in-js instance in style element
|
||||
export const CSS_IN_JS_INSTANCE = '__cssinjs_instance__';
|
||||
|
||||
export function createCache() {
|
||||
const cssinjsInstanceId = Math.random().toString(12).slice(2);
|
||||
|
||||
// Tricky SSR: Move all inline style to the head.
|
||||
// PS: We do not recommend tricky mode.
|
||||
if (typeof document !== 'undefined' && document.head && document.body) {
|
||||
const styles = document.body.querySelectorAll(`style[${ATTR_MARK}]`) || [];
|
||||
const { firstChild } = document.head;
|
||||
|
||||
Array.from(styles).forEach(style => {
|
||||
(style as any)[CSS_IN_JS_INSTANCE] = (style as any)[CSS_IN_JS_INSTANCE] || cssinjsInstanceId;
|
||||
|
||||
// Not force move if no head
|
||||
// Not force move if no head
|
||||
if ((style as any)[CSS_IN_JS_INSTANCE] === cssinjsInstanceId) {
|
||||
document.head.insertBefore(style, firstChild);
|
||||
}
|
||||
});
|
||||
|
||||
// Deduplicate of moved styles
|
||||
const styleHash: Record<string, boolean> = {};
|
||||
Array.from(document.querySelectorAll(`style[${ATTR_MARK}]`)).forEach(style => {
|
||||
const hash = style.getAttribute(ATTR_MARK)!;
|
||||
if (styleHash[hash]) {
|
||||
if ((style as any)[CSS_IN_JS_INSTANCE] === cssinjsInstanceId) {
|
||||
style.parentNode?.removeChild(style);
|
||||
}
|
||||
} else {
|
||||
styleHash[hash] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return new CacheEntity(cssinjsInstanceId);
|
||||
}
|
||||
|
||||
export type HashPriority = 'low' | 'high';
|
||||
|
||||
export interface StyleContextProps {
|
||||
autoClear?: boolean;
|
||||
/** @private Test only. Not work in production. */
|
||||
mock?: 'server' | 'client';
|
||||
/**
|
||||
* Only set when you need ssr to extract style on you own.
|
||||
* If not provided, it will auto create <style /> on the end of Provider in server side.
|
||||
*/
|
||||
cache: CacheEntity;
|
||||
/** Tell children that this context is default generated context */
|
||||
defaultCache: boolean;
|
||||
/** Use `:where` selector to reduce hashId css selector priority */
|
||||
hashPriority?: HashPriority;
|
||||
/** Tell cssinjs where to inject style in */
|
||||
container?: Element | ShadowRoot;
|
||||
/** Component wil render inline `<style />` for fallback in SSR. Not recommend. */
|
||||
ssrInline?: boolean;
|
||||
/** Transform css before inject in document. Please note that `transformers` do not support dynamic update */
|
||||
transformers?: Transformer[];
|
||||
/**
|
||||
* Linters to lint css before inject in document.
|
||||
* Styles will be linted after transforming.
|
||||
* Please note that `linters` do not support dynamic update.
|
||||
*/
|
||||
linters?: Linter[];
|
||||
}
|
||||
|
||||
const StyleContextKey: InjectionKey<ShallowRef<Partial<StyleContextProps>>> =
|
||||
Symbol('StyleContextKey');
|
||||
|
||||
export type UseStyleProviderProps = Partial<StyleContextProps> | Ref<Partial<StyleContextProps>>;
|
||||
|
||||
// fix: https://github.com/vueComponent/ant-design-vue/issues/7023
|
||||
const getCache = () => {
|
||||
const instance = getCurrentInstance();
|
||||
let cache: CacheEntity;
|
||||
if (instance && instance.appContext) {
|
||||
const globalCache = instance.appContext?.config?.globalProperties?.__ANTDV_CSSINJS_CACHE__;
|
||||
if (globalCache) {
|
||||
cache = globalCache;
|
||||
} else {
|
||||
cache = createCache();
|
||||
if (instance.appContext.config.globalProperties) {
|
||||
instance.appContext.config.globalProperties.__ANTDV_CSSINJS_CACHE__ = cache;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cache = createCache();
|
||||
}
|
||||
return cache;
|
||||
};
|
||||
|
||||
const defaultStyleContext: StyleContextProps = {
|
||||
cache: createCache(),
|
||||
defaultCache: true,
|
||||
hashPriority: 'low',
|
||||
};
|
||||
// fix: https://github.com/vueComponent/ant-design-vue/issues/6912
|
||||
export const useStyleInject = () => {
|
||||
const cache = getCache();
|
||||
return inject(StyleContextKey, shallowRef({ ...defaultStyleContext, cache }));
|
||||
};
|
||||
export const useStyleProvider = (props: UseStyleProviderProps) => {
|
||||
const parentContext = useStyleInject();
|
||||
const context = shallowRef<Partial<StyleContextProps>>({
|
||||
...defaultStyleContext,
|
||||
cache: createCache(),
|
||||
});
|
||||
watch(
|
||||
[() => unref(props), parentContext],
|
||||
() => {
|
||||
const mergedContext: Partial<StyleContextProps> = {
|
||||
...parentContext.value,
|
||||
};
|
||||
const propsValue = unref(props);
|
||||
Object.keys(propsValue).forEach(key => {
|
||||
const value = propsValue[key];
|
||||
if (propsValue[key] !== undefined) {
|
||||
mergedContext[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
const { cache } = propsValue;
|
||||
mergedContext.cache = mergedContext.cache || createCache();
|
||||
mergedContext.defaultCache = !cache && parentContext.value.defaultCache;
|
||||
context.value = mergedContext;
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
provide(StyleContextKey, context);
|
||||
return context;
|
||||
};
|
||||
export const styleProviderProps = () => ({
|
||||
autoClear: booleanType(),
|
||||
/** @private Test only. Not work in production. */
|
||||
mock: stringType<'server' | 'client'>(),
|
||||
/**
|
||||
* Only set when you need ssr to extract style on you own.
|
||||
* If not provided, it will auto create <style /> on the end of Provider in server side.
|
||||
*/
|
||||
cache: objectType<CacheEntity>(),
|
||||
/** Tell children that this context is default generated context */
|
||||
defaultCache: booleanType(),
|
||||
/** Use `:where` selector to reduce hashId css selector priority */
|
||||
hashPriority: stringType<HashPriority>(),
|
||||
/** Tell cssinjs where to inject style in */
|
||||
container: someType<Element | ShadowRoot>(),
|
||||
/** Component wil render inline `<style />` for fallback in SSR. Not recommend. */
|
||||
ssrInline: booleanType(),
|
||||
/** Transform css before inject in document. Please note that `transformers` do not support dynamic update */
|
||||
transformers: arrayType<Transformer[]>(),
|
||||
/**
|
||||
* Linters to lint css before inject in document.
|
||||
* Styles will be linted after transforming.
|
||||
* Please note that `linters` do not support dynamic update.
|
||||
*/
|
||||
linters: arrayType<Linter[]>(),
|
||||
});
|
||||
export type StyleProviderProps = Partial<ExtractPropTypes<ReturnType<typeof styleProviderProps>>>;
|
||||
export const StyleProvider = withInstall(
|
||||
defineComponent({
|
||||
name: 'AStyleProvider',
|
||||
inheritAttrs: false,
|
||||
props: styleProviderProps(),
|
||||
setup(props, { slots }) {
|
||||
useStyleProvider(props);
|
||||
return () => slots.default?.();
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export default {
|
||||
useStyleInject,
|
||||
useStyleProvider,
|
||||
StyleProvider,
|
||||
};
|
|
@ -0,0 +1,165 @@
|
|||
import hash from '@emotion/hash';
|
||||
import { ATTR_TOKEN, CSS_IN_JS_INSTANCE, useStyleInject } from '../StyleContext';
|
||||
import type Theme from '../theme/Theme';
|
||||
import useGlobalCache from './useGlobalCache';
|
||||
import { flattenToken, token2key } from '../util';
|
||||
import type { Ref } from 'vue';
|
||||
import { ref, computed } from 'vue';
|
||||
|
||||
const EMPTY_OVERRIDE = {};
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
// nuxt generate when NODE_ENV is prerender
|
||||
const isPrerender = process.env.NODE_ENV === 'prerender';
|
||||
|
||||
// Generate different prefix to make user selector break in production env.
|
||||
// This helps developer not to do style override directly on the hash id.
|
||||
const hashPrefix = !isProduction && !isPrerender ? 'css-dev-only-do-not-override' : 'css';
|
||||
|
||||
export interface Option<DerivativeToken, DesignToken> {
|
||||
/**
|
||||
* Generate token with salt.
|
||||
* This is used to generate different hashId even same derivative token for different version.
|
||||
*/
|
||||
salt?: string;
|
||||
override?: object;
|
||||
/**
|
||||
* Format token as you need. Such as:
|
||||
*
|
||||
* - rename token
|
||||
* - merge token
|
||||
* - delete token
|
||||
*
|
||||
* This should always be the same since it's one time process.
|
||||
* It's ok to useMemo outside but this has better cache strategy.
|
||||
*/
|
||||
formatToken?: (mergedToken: any) => DerivativeToken;
|
||||
/**
|
||||
* Get final token with origin token, override token and theme.
|
||||
* The parameters do not contain formatToken since it's passed by user.
|
||||
* @param origin The original token.
|
||||
* @param override Extra tokens to override.
|
||||
* @param theme Theme instance. Could get derivative token by `theme.getDerivativeToken`
|
||||
*/
|
||||
getComputedToken?: (
|
||||
origin: DesignToken,
|
||||
override: object,
|
||||
theme: Theme<any, any>,
|
||||
) => DerivativeToken;
|
||||
}
|
||||
|
||||
const tokenKeys = new Map<string, number>();
|
||||
function recordCleanToken(tokenKey: string) {
|
||||
tokenKeys.set(tokenKey, (tokenKeys.get(tokenKey) || 0) + 1);
|
||||
}
|
||||
|
||||
function removeStyleTags(key: string, instanceId: string) {
|
||||
if (typeof document !== 'undefined') {
|
||||
const styles = document.querySelectorAll(`style[${ATTR_TOKEN}="${key}"]`);
|
||||
|
||||
styles.forEach(style => {
|
||||
if ((style as any)[CSS_IN_JS_INSTANCE] === instanceId) {
|
||||
style.parentNode?.removeChild(style);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const TOKEN_THRESHOLD = 0;
|
||||
|
||||
// Remove will check current keys first
|
||||
function cleanTokenStyle(tokenKey: string, instanceId: string) {
|
||||
tokenKeys.set(tokenKey, (tokenKeys.get(tokenKey) || 0) - 1);
|
||||
|
||||
const tokenKeyList = Array.from(tokenKeys.keys());
|
||||
const cleanableKeyList = tokenKeyList.filter(key => {
|
||||
const count = tokenKeys.get(key) || 0;
|
||||
|
||||
return count <= 0;
|
||||
});
|
||||
|
||||
// Should keep tokens under threshold for not to insert style too often
|
||||
if (tokenKeyList.length - cleanableKeyList.length > TOKEN_THRESHOLD) {
|
||||
cleanableKeyList.forEach(key => {
|
||||
removeStyleTags(key, instanceId);
|
||||
tokenKeys.delete(key);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const getComputedToken = <DerivativeToken = object, DesignToken = DerivativeToken>(
|
||||
originToken: DesignToken,
|
||||
overrideToken: object,
|
||||
theme: Theme<any, any>,
|
||||
format?: (token: DesignToken) => DerivativeToken,
|
||||
) => {
|
||||
const derivativeToken = theme.getDerivativeToken(originToken);
|
||||
// Merge with override
|
||||
let mergedDerivativeToken = {
|
||||
...derivativeToken,
|
||||
...overrideToken,
|
||||
};
|
||||
|
||||
// Format if needed
|
||||
if (format) {
|
||||
mergedDerivativeToken = format(mergedDerivativeToken);
|
||||
}
|
||||
|
||||
return mergedDerivativeToken;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache theme derivative token as global shared one
|
||||
* @param theme Theme entity
|
||||
* @param tokens List of tokens, used for cache. Please do not dynamic generate object directly
|
||||
* @param option Additional config
|
||||
* @returns Call Theme.getDerivativeToken(tokenObject) to get token
|
||||
*/
|
||||
export default function useCacheToken<DerivativeToken = object, DesignToken = DerivativeToken>(
|
||||
theme: Ref<Theme<any, any>>,
|
||||
tokens: Ref<Partial<DesignToken>[]>,
|
||||
option: Ref<Option<DerivativeToken, DesignToken>> = ref({}),
|
||||
) {
|
||||
const style = useStyleInject();
|
||||
|
||||
// Basic - We do basic cache here
|
||||
const mergedToken = computed(() => Object.assign({}, ...tokens.value));
|
||||
const tokenStr = computed(() => flattenToken(mergedToken.value));
|
||||
const overrideTokenStr = computed(() => flattenToken(option.value.override || EMPTY_OVERRIDE));
|
||||
|
||||
const cachedToken = useGlobalCache<[DerivativeToken & { _tokenKey: string }, string]>(
|
||||
'token',
|
||||
computed(() => [
|
||||
option.value.salt || '',
|
||||
theme.value.id,
|
||||
tokenStr.value,
|
||||
overrideTokenStr.value,
|
||||
]),
|
||||
() => {
|
||||
const {
|
||||
salt = '',
|
||||
override = EMPTY_OVERRIDE,
|
||||
formatToken,
|
||||
getComputedToken: compute,
|
||||
} = option.value;
|
||||
const mergedDerivativeToken = compute
|
||||
? compute(mergedToken.value, override, theme.value)
|
||||
: getComputedToken(mergedToken.value, override, theme.value, formatToken);
|
||||
|
||||
// Optimize for `useStyleRegister` performance
|
||||
const tokenKey = token2key(mergedDerivativeToken, salt);
|
||||
mergedDerivativeToken._tokenKey = tokenKey;
|
||||
recordCleanToken(tokenKey);
|
||||
|
||||
const hashId = `${hashPrefix}-${hash(tokenKey)}`;
|
||||
mergedDerivativeToken._hashId = hashId; // Not used
|
||||
return [mergedDerivativeToken, hashId];
|
||||
},
|
||||
cache => {
|
||||
// Remove token will remove all related style
|
||||
cleanTokenStyle(cache[0]._tokenKey, style.value?.cache.instanceId);
|
||||
},
|
||||
);
|
||||
|
||||
return cachedToken;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
import { useStyleInject } from '../StyleContext';
|
||||
import type { KeyType } from '../Cache';
|
||||
import useHMR from './useHMR';
|
||||
import type { ShallowRef, Ref } from 'vue';
|
||||
import { onBeforeUnmount, watch, watchEffect, shallowRef } from 'vue';
|
||||
export default function useClientCache<CacheType>(
|
||||
prefix: string,
|
||||
keyPath: Ref<KeyType[]>,
|
||||
cacheFn: () => CacheType,
|
||||
onCacheRemove?: (cache: CacheType, fromHMR: boolean) => void,
|
||||
): ShallowRef<CacheType> {
|
||||
const styleContext = useStyleInject();
|
||||
const fullPathStr = shallowRef('');
|
||||
const res = shallowRef<CacheType>();
|
||||
watchEffect(() => {
|
||||
fullPathStr.value = [prefix, ...keyPath.value].join('%');
|
||||
});
|
||||
const HMRUpdate = useHMR();
|
||||
const clearCache = (pathStr: string) => {
|
||||
styleContext.value.cache.update(pathStr, prevCache => {
|
||||
const [times = 0, cache] = prevCache || [];
|
||||
const nextCount = times - 1;
|
||||
if (nextCount === 0) {
|
||||
onCacheRemove?.(cache, false);
|
||||
return null;
|
||||
}
|
||||
|
||||
return [times - 1, cache];
|
||||
});
|
||||
};
|
||||
|
||||
watch(
|
||||
fullPathStr,
|
||||
(newStr, oldStr) => {
|
||||
if (oldStr) clearCache(oldStr);
|
||||
// Create cache
|
||||
styleContext.value.cache.update(newStr, prevCache => {
|
||||
const [times = 0, cache] = prevCache || [];
|
||||
|
||||
// HMR should always ignore cache since developer may change it
|
||||
let tmpCache = cache;
|
||||
if (process.env.NODE_ENV !== 'production' && cache && HMRUpdate) {
|
||||
onCacheRemove?.(tmpCache, HMRUpdate);
|
||||
tmpCache = null;
|
||||
}
|
||||
const mergedCache = tmpCache || cacheFn();
|
||||
|
||||
return [times + 1, mergedCache];
|
||||
});
|
||||
res.value = styleContext.value.cache.get(fullPathStr.value)![1];
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
onBeforeUnmount(() => {
|
||||
clearCache(fullPathStr.value);
|
||||
});
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
function useProdHMR() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let webpackHMR = false;
|
||||
|
||||
function useDevHMR() {
|
||||
return webpackHMR;
|
||||
}
|
||||
|
||||
export default process.env.NODE_ENV === 'production' ? useProdHMR : useDevHMR;
|
||||
|
||||
// Webpack `module.hot.accept` do not support any deps update trigger
|
||||
// We have to hack handler to force mark as HRM
|
||||
if (
|
||||
process.env.NODE_ENV !== 'production' &&
|
||||
typeof module !== 'undefined' &&
|
||||
module &&
|
||||
(module as any).hot &&
|
||||
typeof window !== 'undefined'
|
||||
) {
|
||||
const win = window as any;
|
||||
if (typeof win.webpackHotUpdate === 'function') {
|
||||
const originWebpackHotUpdate = win.webpackHotUpdate;
|
||||
|
||||
win.webpackHotUpdate = (...args: any[]) => {
|
||||
webpackHMR = true;
|
||||
setTimeout(() => {
|
||||
webpackHMR = false;
|
||||
}, 0);
|
||||
return originWebpackHotUpdate(...args);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
import canUseDom from '../../../../_util/canUseDom';
|
||||
import { ATTR_MARK } from '../../StyleContext';
|
||||
|
||||
export const ATTR_CACHE_MAP = 'data-ant-cssinjs-cache-path';
|
||||
|
||||
/**
|
||||
* This marks style from the css file.
|
||||
* Which means not exist in `<style />` tag.
|
||||
*/
|
||||
export const CSS_FILE_STYLE = '_FILE_STYLE__';
|
||||
|
||||
export function serialize(cachePathMap: Record<string, string>) {
|
||||
return Object.keys(cachePathMap)
|
||||
.map(path => {
|
||||
const hash = cachePathMap[path];
|
||||
return `${path}:${hash}`;
|
||||
})
|
||||
.join(';');
|
||||
}
|
||||
|
||||
let cachePathMap: Record<string, string>;
|
||||
let fromCSSFile = true;
|
||||
|
||||
/**
|
||||
* @private Test usage only. Can save remove if no need.
|
||||
*/
|
||||
export function reset(mockCache?: Record<string, string>, fromFile = true) {
|
||||
cachePathMap = mockCache!;
|
||||
fromCSSFile = fromFile;
|
||||
}
|
||||
|
||||
export function prepare() {
|
||||
if (!cachePathMap) {
|
||||
cachePathMap = {};
|
||||
|
||||
if (canUseDom()) {
|
||||
const div = document.createElement('div');
|
||||
div.className = ATTR_CACHE_MAP;
|
||||
div.style.position = 'fixed';
|
||||
div.style.visibility = 'hidden';
|
||||
div.style.top = '-9999px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
let content = getComputedStyle(div).content || '';
|
||||
content = content.replace(/^"/, '').replace(/"$/, '');
|
||||
|
||||
// Fill data
|
||||
content.split(';').forEach(item => {
|
||||
const [path, hash] = item.split(':');
|
||||
cachePathMap[path] = hash;
|
||||
});
|
||||
|
||||
// Remove inline record style
|
||||
const inlineMapStyle = document.querySelector(`style[${ATTR_CACHE_MAP}]`);
|
||||
if (inlineMapStyle) {
|
||||
fromCSSFile = false;
|
||||
inlineMapStyle.parentNode?.removeChild(inlineMapStyle);
|
||||
}
|
||||
|
||||
document.body.removeChild(div);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function existPath(path: string) {
|
||||
prepare();
|
||||
|
||||
return !!cachePathMap[path];
|
||||
}
|
||||
|
||||
export function getStyleAndHash(path: string): [style: string | null, hash: string] {
|
||||
const hash = cachePathMap[path];
|
||||
let styleStr: string | null = null;
|
||||
|
||||
if (hash && canUseDom()) {
|
||||
if (fromCSSFile) {
|
||||
styleStr = CSS_FILE_STYLE;
|
||||
} else {
|
||||
const style = document.querySelector(`style[${ATTR_MARK}="${cachePathMap[path]}"]`);
|
||||
|
||||
if (style) {
|
||||
styleStr = style.innerHTML;
|
||||
} else {
|
||||
// Clean up since not exist anymore
|
||||
delete cachePathMap[path];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [styleStr, hash];
|
||||
}
|
|
@ -0,0 +1,566 @@
|
|||
import hash from '@emotion/hash';
|
||||
import type * as CSS from 'csstype';
|
||||
// @ts-ignore
|
||||
import unitless from '@emotion/unitless';
|
||||
import { compile, serialize, stringify } from 'stylis';
|
||||
import type { Theme, Transformer } from '../..';
|
||||
import type Cache from '../../Cache';
|
||||
import type Keyframes from '../../Keyframes';
|
||||
import type { Linter } from '../../linters';
|
||||
import { contentQuotesLinter, hashedAnimationLinter } from '../../linters';
|
||||
import type { HashPriority } from '../../StyleContext';
|
||||
import {
|
||||
useStyleInject,
|
||||
ATTR_CACHE_PATH,
|
||||
ATTR_MARK,
|
||||
ATTR_TOKEN,
|
||||
CSS_IN_JS_INSTANCE,
|
||||
} from '../../StyleContext';
|
||||
import { supportLayer } from '../../util';
|
||||
import useGlobalCache from '../useGlobalCache';
|
||||
import { removeCSS, updateCSS } from '../../../../vc-util/Dom/dynamicCSS';
|
||||
import type { Ref } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import type { VueNode } from '../../../type';
|
||||
import canUseDom from '../../../../_util/canUseDom';
|
||||
|
||||
import {
|
||||
ATTR_CACHE_MAP,
|
||||
existPath,
|
||||
getStyleAndHash,
|
||||
serialize as serializeCacheMap,
|
||||
} from './cacheMapUtil';
|
||||
|
||||
const isClientSide = canUseDom();
|
||||
|
||||
const SKIP_CHECK = '_skip_check_';
|
||||
const MULTI_VALUE = '_multi_value_';
|
||||
export type CSSProperties = Omit<CSS.PropertiesFallback<number | string>, 'animationName'> & {
|
||||
animationName?: CSS.PropertiesFallback<number | string>['animationName'] | Keyframes;
|
||||
};
|
||||
|
||||
export type CSSPropertiesWithMultiValues = {
|
||||
[K in keyof CSSProperties]:
|
||||
| CSSProperties[K]
|
||||
| readonly Extract<CSSProperties[K], string>[]
|
||||
| {
|
||||
[SKIP_CHECK]?: boolean;
|
||||
[MULTI_VALUE]?: boolean;
|
||||
value: CSSProperties[K] | CSSProperties[K][];
|
||||
};
|
||||
};
|
||||
|
||||
export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject };
|
||||
|
||||
type ArrayCSSInterpolation = readonly CSSInterpolation[];
|
||||
|
||||
export type InterpolationPrimitive = null | undefined | boolean | number | string | CSSObject;
|
||||
|
||||
export type CSSInterpolation = InterpolationPrimitive | ArrayCSSInterpolation | Keyframes;
|
||||
|
||||
export type CSSOthersObject = Record<string, CSSInterpolation>;
|
||||
|
||||
export interface CSSObject extends CSSPropertiesWithMultiValues, CSSPseudos, CSSOthersObject {}
|
||||
|
||||
// ============================================================================
|
||||
// == Parser ==
|
||||
// ============================================================================
|
||||
// Preprocessor style content to browser support one
|
||||
export function normalizeStyle(styleStr: string): string {
|
||||
const serialized = serialize(compile(styleStr), stringify);
|
||||
return serialized.replace(/\{%%%\:[^;];}/g, ';');
|
||||
}
|
||||
|
||||
function isCompoundCSSProperty(value: CSSObject[string]) {
|
||||
return typeof value === 'object' && value && (SKIP_CHECK in value || MULTI_VALUE in value);
|
||||
}
|
||||
|
||||
// 注入 hash 值
|
||||
function injectSelectorHash(key: string, hashId: string, hashPriority?: HashPriority) {
|
||||
if (!hashId) {
|
||||
return key;
|
||||
}
|
||||
|
||||
const hashClassName = `.${hashId}`;
|
||||
const hashSelector = hashPriority === 'low' ? `:where(${hashClassName})` : hashClassName;
|
||||
|
||||
// 注入 hashId
|
||||
const keys = key.split(',').map(k => {
|
||||
const fullPath = k.trim().split(/\s+/);
|
||||
|
||||
// 如果 Selector 第一个是 HTML Element,那我们就插到它的后面。反之,就插到最前面。
|
||||
let firstPath = fullPath[0] || '';
|
||||
const htmlElement = firstPath.match(/^\w+/)?.[0] || '';
|
||||
|
||||
firstPath = `${htmlElement}${hashSelector}${firstPath.slice(htmlElement.length)}`;
|
||||
|
||||
return [firstPath, ...fullPath.slice(1)].join(' ');
|
||||
});
|
||||
return keys.join(',');
|
||||
}
|
||||
|
||||
export interface ParseConfig {
|
||||
hashId?: string;
|
||||
hashPriority?: HashPriority;
|
||||
layer?: string;
|
||||
path?: string;
|
||||
transformers?: Transformer[];
|
||||
linters?: Linter[];
|
||||
}
|
||||
|
||||
export interface ParseInfo {
|
||||
root?: boolean;
|
||||
injectHash?: boolean;
|
||||
parentSelectors: string[];
|
||||
}
|
||||
|
||||
// Global effect style will mount once and not removed
|
||||
// The effect will not save in SSR cache (e.g. keyframes)
|
||||
const globalEffectStyleKeys = new Set();
|
||||
|
||||
/**
|
||||
* @private Test only. Clear the global effect style keys.
|
||||
*/
|
||||
export const _cf =
|
||||
process.env.NODE_ENV !== 'production' ? () => globalEffectStyleKeys.clear() : undefined;
|
||||
|
||||
// Parse CSSObject to style content
|
||||
export const parseStyle = (
|
||||
interpolation: CSSInterpolation,
|
||||
config: ParseConfig = {},
|
||||
{ root, injectHash, parentSelectors }: ParseInfo = {
|
||||
root: true,
|
||||
parentSelectors: [],
|
||||
},
|
||||
): [
|
||||
parsedStr: string,
|
||||
// Style content which should be unique on all of the style (e.g. Keyframes).
|
||||
// Firefox will flick with same animation name when exist multiple same keyframes.
|
||||
effectStyle: Record<string, string>,
|
||||
] => {
|
||||
const { hashId, layer, path, hashPriority, transformers = [], linters = [] } = config;
|
||||
let styleStr = '';
|
||||
let effectStyle: Record<string, string> = {};
|
||||
|
||||
function parseKeyframes(keyframes: Keyframes) {
|
||||
const animationName = keyframes.getName(hashId);
|
||||
if (!effectStyle[animationName]) {
|
||||
const [parsedStr] = parseStyle(keyframes.style, config, {
|
||||
root: false,
|
||||
parentSelectors,
|
||||
});
|
||||
|
||||
effectStyle[animationName] = `@keyframes ${keyframes.getName(hashId)}${parsedStr}`;
|
||||
}
|
||||
}
|
||||
|
||||
function flattenList(list: ArrayCSSInterpolation, fullList: CSSObject[] = []) {
|
||||
list.forEach(item => {
|
||||
if (Array.isArray(item)) {
|
||||
flattenList(item, fullList);
|
||||
} else if (item) {
|
||||
fullList.push(item as CSSObject);
|
||||
}
|
||||
});
|
||||
|
||||
return fullList;
|
||||
}
|
||||
|
||||
const flattenStyleList = flattenList(
|
||||
Array.isArray(interpolation) ? interpolation : [interpolation],
|
||||
);
|
||||
|
||||
flattenStyleList.forEach(originStyle => {
|
||||
// Only root level can use raw string
|
||||
const style: CSSObject = typeof originStyle === 'string' && !root ? {} : originStyle;
|
||||
|
||||
if (typeof style === 'string') {
|
||||
styleStr += `${style}\n`;
|
||||
} else if ((style as any)._keyframe) {
|
||||
// Keyframe
|
||||
parseKeyframes(style as unknown as Keyframes);
|
||||
} else {
|
||||
const mergedStyle = transformers.reduce((prev, trans) => trans?.visit?.(prev) || prev, style);
|
||||
|
||||
// Normal CSSObject
|
||||
Object.keys(mergedStyle).forEach(key => {
|
||||
const value = mergedStyle[key];
|
||||
|
||||
if (
|
||||
typeof value === 'object' &&
|
||||
value &&
|
||||
(key !== 'animationName' || !(value as Keyframes)._keyframe) &&
|
||||
!isCompoundCSSProperty(value)
|
||||
) {
|
||||
let subInjectHash = false;
|
||||
|
||||
// 当成嵌套对象来处理
|
||||
let mergedKey = key.trim();
|
||||
// Whether treat child as root. In most case it is false.
|
||||
let nextRoot = false;
|
||||
|
||||
// 拆分多个选择器
|
||||
if ((root || injectHash) && hashId) {
|
||||
if (mergedKey.startsWith('@')) {
|
||||
// 略过媒体查询,交给子节点继续插入 hashId
|
||||
subInjectHash = true;
|
||||
} else {
|
||||
// 注入 hashId
|
||||
mergedKey = injectSelectorHash(key, hashId, hashPriority);
|
||||
}
|
||||
} else if (root && !hashId && (mergedKey === '&' || mergedKey === '')) {
|
||||
// In case of `{ '&': { a: { color: 'red' } } }` or `{ '': { a: { color: 'red' } } }` without hashId,
|
||||
// we will get `&{a:{color:red;}}` or `{a:{color:red;}}` string for stylis to compile.
|
||||
// But it does not conform to stylis syntax,
|
||||
// and finally we will get `{color:red;}` as css, which is wrong.
|
||||
// So we need to remove key in root, and treat child `{ a: { color: 'red' } }` as root.
|
||||
mergedKey = '';
|
||||
nextRoot = true;
|
||||
}
|
||||
|
||||
const [parsedStr, childEffectStyle] = parseStyle(value as any, config, {
|
||||
root: nextRoot,
|
||||
injectHash: subInjectHash,
|
||||
parentSelectors: [...parentSelectors, mergedKey],
|
||||
});
|
||||
|
||||
effectStyle = {
|
||||
...effectStyle,
|
||||
...childEffectStyle,
|
||||
};
|
||||
|
||||
styleStr += `${mergedKey}${parsedStr}`;
|
||||
} else {
|
||||
function appendStyle(cssKey: string, cssValue: any) {
|
||||
if (
|
||||
process.env.NODE_ENV !== 'production' &&
|
||||
(typeof value !== 'object' || !(value as any)?.[SKIP_CHECK])
|
||||
) {
|
||||
[contentQuotesLinter, hashedAnimationLinter, ...linters].forEach(linter =>
|
||||
linter(cssKey, cssValue, { path, hashId, parentSelectors }),
|
||||
);
|
||||
}
|
||||
|
||||
// 如果是样式则直接插入
|
||||
const styleName = cssKey.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
|
||||
|
||||
// Auto suffix with px
|
||||
let formatValue = cssValue;
|
||||
if (!unitless[cssKey] && typeof formatValue === 'number' && formatValue !== 0) {
|
||||
formatValue = `${formatValue}px`;
|
||||
}
|
||||
|
||||
// handle animationName & Keyframe value
|
||||
if (cssKey === 'animationName' && (cssValue as Keyframes)?._keyframe) {
|
||||
parseKeyframes(cssValue as Keyframes);
|
||||
formatValue = (cssValue as Keyframes).getName(hashId);
|
||||
}
|
||||
|
||||
styleStr += `${styleName}:${formatValue};`;
|
||||
}
|
||||
const actualValue = (value as any)?.value ?? value;
|
||||
if (
|
||||
typeof value === 'object' &&
|
||||
(value as any)?.[MULTI_VALUE] &&
|
||||
Array.isArray(actualValue)
|
||||
) {
|
||||
actualValue.forEach(item => {
|
||||
appendStyle(key, item);
|
||||
});
|
||||
} else {
|
||||
appendStyle(key, actualValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (!root) {
|
||||
styleStr = `{${styleStr}}`;
|
||||
} else if (layer && supportLayer()) {
|
||||
const layerCells = layer.split(',');
|
||||
const layerName = layerCells[layerCells.length - 1].trim();
|
||||
styleStr = `@layer ${layerName} {${styleStr}}`;
|
||||
|
||||
// Order of layer if needed
|
||||
if (layerCells.length > 1) {
|
||||
// zombieJ: stylis do not support layer order, so we need to handle it manually.
|
||||
styleStr = `@layer ${layer}{%%%:%}${styleStr}`;
|
||||
}
|
||||
}
|
||||
|
||||
return [styleStr, effectStyle];
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// == Register ==
|
||||
// ============================================================================
|
||||
function uniqueHash(path: (string | number)[], styleStr: string) {
|
||||
return hash(`${path.join('%')}${styleStr}`);
|
||||
}
|
||||
|
||||
// function Empty() {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Register a style to the global style sheet.
|
||||
*/
|
||||
export default function useStyleRegister(
|
||||
info: Ref<{
|
||||
theme: Theme<any, any>;
|
||||
token: any;
|
||||
path: string[];
|
||||
hashId?: string;
|
||||
layer?: string;
|
||||
nonce?: string | (() => string);
|
||||
clientOnly?: boolean;
|
||||
/**
|
||||
* Tell cssinjs the insert order of style.
|
||||
* It's useful when you need to insert style
|
||||
* before other style to overwrite for the same selector priority.
|
||||
*/
|
||||
order?: number;
|
||||
}>,
|
||||
styleFn: () => CSSInterpolation,
|
||||
) {
|
||||
const styleContext = useStyleInject();
|
||||
|
||||
const tokenKey = computed(() => info.value.token._tokenKey as string);
|
||||
|
||||
const fullPath = computed(() => [tokenKey.value, ...info.value.path]);
|
||||
|
||||
// Check if need insert style
|
||||
let isMergedClientSide = isClientSide;
|
||||
if (process.env.NODE_ENV !== 'production' && styleContext.value.mock !== undefined) {
|
||||
isMergedClientSide = styleContext.value.mock === 'client';
|
||||
}
|
||||
|
||||
// const [cacheStyle[0], cacheStyle[1], cacheStyle[2]]
|
||||
useGlobalCache<
|
||||
[
|
||||
styleStr: string,
|
||||
tokenKey: string,
|
||||
styleId: string,
|
||||
effectStyle: Record<string, string>,
|
||||
clientOnly: boolean | undefined,
|
||||
order: number,
|
||||
]
|
||||
>(
|
||||
'style',
|
||||
fullPath,
|
||||
// Create cache if needed
|
||||
() => {
|
||||
const { path, hashId, layer, nonce, clientOnly, order = 0 } = info.value;
|
||||
const cachePath = fullPath.value.join('|');
|
||||
// Get style from SSR inline style directly
|
||||
if (existPath(cachePath)) {
|
||||
const [inlineCacheStyleStr, styleHash] = getStyleAndHash(cachePath);
|
||||
if (inlineCacheStyleStr) {
|
||||
return [inlineCacheStyleStr, tokenKey.value, styleHash, {}, clientOnly, order];
|
||||
}
|
||||
}
|
||||
const styleObj = styleFn();
|
||||
const { hashPriority, container, transformers, linters, cache } = styleContext.value;
|
||||
|
||||
const [parsedStyle, effectStyle] = parseStyle(styleObj, {
|
||||
hashId,
|
||||
hashPriority,
|
||||
layer,
|
||||
path: path.join('-'),
|
||||
transformers,
|
||||
linters,
|
||||
});
|
||||
const styleStr = normalizeStyle(parsedStyle);
|
||||
const styleId = uniqueHash(fullPath.value, styleStr);
|
||||
|
||||
if (isMergedClientSide) {
|
||||
const mergedCSSConfig: Parameters<typeof updateCSS>[2] = {
|
||||
mark: ATTR_MARK,
|
||||
prepend: 'queue',
|
||||
attachTo: container,
|
||||
priority: order,
|
||||
};
|
||||
|
||||
const nonceStr = typeof nonce === 'function' ? nonce() : nonce;
|
||||
|
||||
if (nonceStr) {
|
||||
mergedCSSConfig.csp = { nonce: nonceStr };
|
||||
}
|
||||
|
||||
const style = updateCSS(styleStr, styleId, mergedCSSConfig);
|
||||
|
||||
(style as any)[CSS_IN_JS_INSTANCE] = cache.instanceId;
|
||||
|
||||
// Used for `useCacheToken` to remove on batch when token removed
|
||||
style.setAttribute(ATTR_TOKEN, tokenKey.value);
|
||||
|
||||
// Dev usage to find which cache path made this easily
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
style.setAttribute(ATTR_CACHE_PATH, fullPath.value.join('|'));
|
||||
}
|
||||
|
||||
// Inject client side effect style
|
||||
Object.keys(effectStyle).forEach(effectKey => {
|
||||
if (!globalEffectStyleKeys.has(effectKey)) {
|
||||
globalEffectStyleKeys.add(effectKey);
|
||||
|
||||
// Inject
|
||||
updateCSS(normalizeStyle(effectStyle[effectKey]), `_effect-${effectKey}`, {
|
||||
mark: ATTR_MARK,
|
||||
prepend: 'queue',
|
||||
attachTo: container,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return [styleStr, tokenKey.value, styleId, effectStyle, clientOnly, order];
|
||||
},
|
||||
// Remove cache if no need
|
||||
([, , styleId], fromHMR) => {
|
||||
if ((fromHMR || styleContext.value.autoClear) && isClientSide) {
|
||||
removeCSS(styleId, { mark: ATTR_MARK });
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return (node: VueNode) => {
|
||||
return node;
|
||||
// let styleNode: VueNode;
|
||||
// if (!styleContext.ssrInline || isMergedClientSide || !styleContext.defaultCache) {
|
||||
// styleNode = <Empty />;
|
||||
// } else {
|
||||
// styleNode = (
|
||||
// <style
|
||||
// {...{
|
||||
// [ATTR_TOKEN]: cacheStyle.value[1],
|
||||
// [ATTR_MARK]: cacheStyle.value[2],
|
||||
// }}
|
||||
// innerHTML={cacheStyle.value[0]}
|
||||
// />
|
||||
// );
|
||||
// }
|
||||
|
||||
// return (
|
||||
// <>
|
||||
// {styleNode}
|
||||
// {node}
|
||||
// </>
|
||||
// );
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// == SSR ==
|
||||
// ============================================================================
|
||||
export function extractStyle(cache: Cache, plain = false) {
|
||||
const matchPrefix = `style%`;
|
||||
|
||||
// prefix with `style` is used for `useStyleRegister` to cache style context
|
||||
const styleKeys = Array.from(cache.cache.keys()).filter(key => key.startsWith(matchPrefix));
|
||||
|
||||
// Common effect styles like animation
|
||||
const effectStyles: Record<string, boolean> = {};
|
||||
|
||||
// Mapping of cachePath to style hash
|
||||
const cachePathMap: Record<string, string> = {};
|
||||
|
||||
let styleText = '';
|
||||
|
||||
function toStyleStr(
|
||||
style: string,
|
||||
tokenKey?: string,
|
||||
styleId?: string,
|
||||
customizeAttrs: Record<string, string> = {},
|
||||
) {
|
||||
const attrs: Record<string, string | undefined> = {
|
||||
...customizeAttrs,
|
||||
[ATTR_TOKEN]: tokenKey,
|
||||
[ATTR_MARK]: styleId,
|
||||
};
|
||||
|
||||
const attrStr = Object.keys(attrs)
|
||||
.map(attr => {
|
||||
const val = attrs[attr];
|
||||
return val ? `${attr}="${val}"` : null;
|
||||
})
|
||||
.filter(v => v)
|
||||
.join(' ');
|
||||
|
||||
return plain ? style : `<style ${attrStr}>${style}</style>`;
|
||||
}
|
||||
|
||||
// ====================== Fill Style ======================
|
||||
type OrderStyle = [order: number, style: string];
|
||||
|
||||
const orderStyles: OrderStyle[] = styleKeys
|
||||
.map(key => {
|
||||
const cachePath = key.slice(matchPrefix.length).replace(/%/g, '|');
|
||||
|
||||
const [styleStr, tokenKey, styleId, effectStyle, clientOnly, order]: [
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
Record<string, string>,
|
||||
boolean,
|
||||
number,
|
||||
] = cache.cache.get(key)![1];
|
||||
|
||||
// Skip client only style
|
||||
if (clientOnly) {
|
||||
return null! as OrderStyle;
|
||||
}
|
||||
|
||||
// ====================== Style ======================
|
||||
// Used for vc-util
|
||||
const sharedAttrs = {
|
||||
'data-vc-order': 'prependQueue',
|
||||
'data-vc-priority': `${order}`,
|
||||
};
|
||||
|
||||
let keyStyleText = toStyleStr(styleStr, tokenKey, styleId, sharedAttrs);
|
||||
|
||||
// Save cache path with hash mapping
|
||||
cachePathMap[cachePath] = styleId;
|
||||
|
||||
// =============== Create effect style ===============
|
||||
if (effectStyle) {
|
||||
Object.keys(effectStyle).forEach(effectKey => {
|
||||
// Effect style can be reused
|
||||
if (!effectStyles[effectKey]) {
|
||||
effectStyles[effectKey] = true;
|
||||
keyStyleText += toStyleStr(
|
||||
normalizeStyle(effectStyle[effectKey]),
|
||||
tokenKey,
|
||||
`_effect-${effectKey}`,
|
||||
sharedAttrs,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const ret: OrderStyle = [order, keyStyleText];
|
||||
|
||||
return ret;
|
||||
})
|
||||
.filter(o => o);
|
||||
|
||||
orderStyles
|
||||
.sort((o1, o2) => o1[0] - o2[0])
|
||||
.forEach(([, style]) => {
|
||||
styleText += style;
|
||||
});
|
||||
|
||||
// ==================== Fill Cache Path ====================
|
||||
styleText += toStyleStr(
|
||||
`.${ATTR_CACHE_MAP}{content:"${serializeCacheMap(cachePathMap)}";}`,
|
||||
undefined,
|
||||
undefined,
|
||||
{
|
||||
[ATTR_CACHE_MAP]: ATTR_CACHE_MAP,
|
||||
},
|
||||
);
|
||||
|
||||
return styleText;
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
import useCacheToken from './hooks/useCacheToken';
|
||||
import type { CSSInterpolation, CSSObject } from './hooks/useStyleRegister';
|
||||
import useStyleRegister, { extractStyle } from './hooks/useStyleRegister';
|
||||
import Keyframes from './Keyframes';
|
||||
import type { Linter } from './linters';
|
||||
import { legacyNotSelectorLinter, logicalPropertiesLinter, parentSelectorLinter } from './linters';
|
||||
import type { StyleContextProps, StyleProviderProps } from './StyleContext';
|
||||
import { createCache, useStyleInject, useStyleProvider, StyleProvider } from './StyleContext';
|
||||
import type { DerivativeFunc, TokenType } from './theme';
|
||||
import { createTheme, Theme } from './theme';
|
||||
import type { Transformer } from './transformers/interface';
|
||||
import legacyLogicalPropertiesTransformer from './transformers/legacyLogicalProperties';
|
||||
import px2remTransformer from './transformers/px2rem';
|
||||
import { supportLogicProps, supportWhere } from './util';
|
||||
|
||||
const cssinjs = {
|
||||
Theme,
|
||||
createTheme,
|
||||
useStyleRegister,
|
||||
useCacheToken,
|
||||
createCache,
|
||||
useStyleInject,
|
||||
useStyleProvider,
|
||||
Keyframes,
|
||||
extractStyle,
|
||||
|
||||
// Transformer
|
||||
legacyLogicalPropertiesTransformer,
|
||||
px2remTransformer,
|
||||
|
||||
// Linters
|
||||
logicalPropertiesLinter,
|
||||
legacyNotSelectorLinter,
|
||||
parentSelectorLinter,
|
||||
|
||||
// cssinjs
|
||||
StyleProvider,
|
||||
};
|
||||
export {
|
||||
Theme,
|
||||
createTheme,
|
||||
useStyleRegister,
|
||||
useCacheToken,
|
||||
createCache,
|
||||
useStyleInject,
|
||||
useStyleProvider,
|
||||
Keyframes,
|
||||
extractStyle,
|
||||
|
||||
// Transformer
|
||||
legacyLogicalPropertiesTransformer,
|
||||
px2remTransformer,
|
||||
|
||||
// Linters
|
||||
logicalPropertiesLinter,
|
||||
legacyNotSelectorLinter,
|
||||
parentSelectorLinter,
|
||||
|
||||
// cssinjs
|
||||
StyleProvider,
|
||||
};
|
||||
export type {
|
||||
TokenType,
|
||||
CSSObject,
|
||||
CSSInterpolation,
|
||||
DerivativeFunc,
|
||||
Transformer,
|
||||
Linter,
|
||||
StyleContextProps,
|
||||
StyleProviderProps,
|
||||
};
|
||||
|
||||
export const _experimental = {
|
||||
supportModernCSS: () => supportWhere() && supportLogicProps(),
|
||||
};
|
||||
|
||||
export default cssinjs;
|
|
@ -0,0 +1,25 @@
|
|||
import type { Linter } from './interface';
|
||||
import { lintWarning } from './utils';
|
||||
|
||||
const linter: Linter = (key, value, info) => {
|
||||
if (key === 'content') {
|
||||
// From emotion: https://github.com/emotion-js/emotion/blob/main/packages/serialize/src/index.js#L63
|
||||
const contentValuePattern =
|
||||
/(attr|counters?|url|(((repeating-)?(linear|radial))|conic)-gradient)\(|(no-)?(open|close)-quote/;
|
||||
const contentValues = ['normal', 'none', 'initial', 'inherit', 'unset'];
|
||||
if (
|
||||
typeof value !== 'string' ||
|
||||
(contentValues.indexOf(value) === -1 &&
|
||||
!contentValuePattern.test(value) &&
|
||||
(value.charAt(0) !== value.charAt(value.length - 1) ||
|
||||
(value.charAt(0) !== '"' && value.charAt(0) !== "'")))
|
||||
) {
|
||||
lintWarning(
|
||||
`You seem to be using a value for 'content' without quotes, try replacing it with \`content: '"${value}"'\`.`,
|
||||
info,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default linter;
|
|
@ -0,0 +1,15 @@
|
|||
import type { Linter } from './interface';
|
||||
import { lintWarning } from './utils';
|
||||
|
||||
const linter: Linter = (key, value, info) => {
|
||||
if (key === 'animation') {
|
||||
if (info.hashId && value !== 'none') {
|
||||
lintWarning(
|
||||
`You seem to be using hashed animation '${value}', in which case 'animationName' with Keyframe as value is recommended.`,
|
||||
info,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default linter;
|
|
@ -0,0 +1,6 @@
|
|||
export { default as contentQuotesLinter } from './contentQuotesLinter';
|
||||
export { default as hashedAnimationLinter } from './hashedAnimationLinter';
|
||||
export type { Linter } from './interface';
|
||||
export { default as legacyNotSelectorLinter } from './legacyNotSelectorLinter';
|
||||
export { default as logicalPropertiesLinter } from './logicalPropertiesLinter';
|
||||
export { default as parentSelectorLinter } from './parentSelectorLinter';
|
|
@ -0,0 +1,9 @@
|
|||
export interface LinterInfo {
|
||||
path?: string;
|
||||
hashId?: string;
|
||||
parentSelectors: string[];
|
||||
}
|
||||
|
||||
export interface Linter {
|
||||
(key: string, value: string | number, info: LinterInfo): void;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
import type { Linter, LinterInfo } from './interface';
|
||||
import { lintWarning } from './utils';
|
||||
|
||||
function isConcatSelector(selector: string) {
|
||||
const notContent = selector.match(/:not\(([^)]*)\)/)?.[1] || '';
|
||||
|
||||
// split selector. e.g.
|
||||
// `h1#a.b` => ['h1', #a', '.b']
|
||||
const splitCells = notContent.split(/(\[[^[]*])|(?=[.#])/).filter(str => str);
|
||||
|
||||
return splitCells.length > 1;
|
||||
}
|
||||
|
||||
function parsePath(info: LinterInfo) {
|
||||
return info.parentSelectors.reduce((prev, cur) => {
|
||||
if (!prev) {
|
||||
return cur;
|
||||
}
|
||||
|
||||
return cur.includes('&') ? cur.replace(/&/g, prev) : `${prev} ${cur}`;
|
||||
}, '');
|
||||
}
|
||||
|
||||
const linter: Linter = (_key, _value, info) => {
|
||||
const parentSelectorPath = parsePath(info);
|
||||
const notList = parentSelectorPath.match(/:not\([^)]*\)/g) || [];
|
||||
|
||||
if (notList.length > 0 && notList.some(isConcatSelector)) {
|
||||
lintWarning(`Concat ':not' selector not support in legacy browsers.`, info);
|
||||
}
|
||||
};
|
||||
|
||||
export default linter;
|
|
@ -0,0 +1,88 @@
|
|||
import type { Linter } from './interface';
|
||||
import { lintWarning } from './utils';
|
||||
|
||||
const linter: Linter = (key, value, info) => {
|
||||
switch (key) {
|
||||
case 'marginLeft':
|
||||
case 'marginRight':
|
||||
case 'paddingLeft':
|
||||
case 'paddingRight':
|
||||
case 'left':
|
||||
case 'right':
|
||||
case 'borderLeft':
|
||||
case 'borderLeftWidth':
|
||||
case 'borderLeftStyle':
|
||||
case 'borderLeftColor':
|
||||
case 'borderRight':
|
||||
case 'borderRightWidth':
|
||||
case 'borderRightStyle':
|
||||
case 'borderRightColor':
|
||||
case 'borderTopLeftRadius':
|
||||
case 'borderTopRightRadius':
|
||||
case 'borderBottomLeftRadius':
|
||||
case 'borderBottomRightRadius':
|
||||
lintWarning(
|
||||
`You seem to be using non-logical property '${key}' which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`,
|
||||
info,
|
||||
);
|
||||
return;
|
||||
case 'margin':
|
||||
case 'padding':
|
||||
case 'borderWidth':
|
||||
case 'borderStyle':
|
||||
// case 'borderColor':
|
||||
if (typeof value === 'string') {
|
||||
const valueArr = value.split(' ').map(item => item.trim());
|
||||
if (valueArr.length === 4 && valueArr[1] !== valueArr[3]) {
|
||||
lintWarning(
|
||||
`You seem to be using '${key}' property with different left ${key} and right ${key}, which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`,
|
||||
info,
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 'clear':
|
||||
case 'textAlign':
|
||||
if (value === 'left' || value === 'right') {
|
||||
lintWarning(
|
||||
`You seem to be using non-logical value '${value}' of ${key}, which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`,
|
||||
info,
|
||||
);
|
||||
}
|
||||
return;
|
||||
case 'borderRadius':
|
||||
if (typeof value === 'string') {
|
||||
const radiusGroups = value.split('/').map(item => item.trim());
|
||||
const invalid = radiusGroups.reduce((result, group) => {
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
const radiusArr = group.split(' ').map(item => item.trim());
|
||||
// borderRadius: '2px 4px'
|
||||
if (radiusArr.length >= 2 && radiusArr[0] !== radiusArr[1]) {
|
||||
return true;
|
||||
}
|
||||
// borderRadius: '4px 4px 2px'
|
||||
if (radiusArr.length === 3 && radiusArr[1] !== radiusArr[2]) {
|
||||
return true;
|
||||
}
|
||||
// borderRadius: '4px 4px 2px 4px'
|
||||
if (radiusArr.length === 4 && radiusArr[2] !== radiusArr[3]) {
|
||||
return true;
|
||||
}
|
||||
return result;
|
||||
}, false);
|
||||
|
||||
if (invalid) {
|
||||
lintWarning(
|
||||
`You seem to be using non-logical value '${value}' of ${key}, which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`,
|
||||
info,
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
export default linter;
|
|
@ -0,0 +1,15 @@
|
|||
import type { Linter } from '..';
|
||||
import { lintWarning } from './utils';
|
||||
|
||||
const linter: Linter = (_key, _value, info) => {
|
||||
if (
|
||||
info.parentSelectors.some(selector => {
|
||||
const selectors = selector.split(',');
|
||||
return selectors.some(item => item.split('&').length > 2);
|
||||
})
|
||||
) {
|
||||
lintWarning('Should not use more than one `&` in a selector.', info);
|
||||
}
|
||||
};
|
||||
|
||||
export default linter;
|
|
@ -0,0 +1,13 @@
|
|||
import devWarning from '../../../vc-util/warning';
|
||||
import type { LinterInfo } from './interface';
|
||||
|
||||
export function lintWarning(message: string, info: LinterInfo) {
|
||||
const { path, parentSelectors } = info;
|
||||
|
||||
devWarning(
|
||||
false,
|
||||
`[Ant Design Vue CSS-in-JS] ${path ? `Error in '${path}': ` : ''}${message}${
|
||||
parentSelectors.length ? ` Selector info: ${parentSelectors.join(' -> ')}` : ''
|
||||
}`,
|
||||
);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import warning from '../../warning';
|
||||
import type { DerivativeFunc, TokenType } from './interface';
|
||||
|
||||
let uuid = 0;
|
||||
|
||||
/**
|
||||
* Theme with algorithms to derive tokens from design tokens.
|
||||
* Use `createTheme` first which will help to manage the theme instance cache.
|
||||
*/
|
||||
export default class Theme<DesignToken extends TokenType, DerivativeToken extends TokenType> {
|
||||
private derivatives: DerivativeFunc<DesignToken, DerivativeToken>[];
|
||||
public readonly id: number;
|
||||
|
||||
constructor(
|
||||
derivatives:
|
||||
| DerivativeFunc<DesignToken, DerivativeToken>
|
||||
| DerivativeFunc<DesignToken, DerivativeToken>[],
|
||||
) {
|
||||
this.derivatives = Array.isArray(derivatives) ? derivatives : [derivatives];
|
||||
this.id = uuid;
|
||||
|
||||
if (derivatives.length === 0) {
|
||||
warning(
|
||||
derivatives.length > 0,
|
||||
'[Ant Design Vue CSS-in-JS] Theme should have at least one derivative function.',
|
||||
);
|
||||
}
|
||||
|
||||
uuid += 1;
|
||||
}
|
||||
|
||||
getDerivativeToken(token: DesignToken): DerivativeToken {
|
||||
return this.derivatives.reduce<DerivativeToken>(
|
||||
(result, derivative) => derivative(token, result),
|
||||
undefined as any,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
import type Theme from './Theme';
|
||||
import type { DerivativeFunc } from './interface';
|
||||
|
||||
// ================================== Cache ==================================
|
||||
type ThemeCacheMap = Map<
|
||||
DerivativeFunc<any, any>,
|
||||
{
|
||||
map?: ThemeCacheMap;
|
||||
value?: [Theme<any, any>, number];
|
||||
}
|
||||
>;
|
||||
|
||||
type DerivativeOptions = DerivativeFunc<any, any>[];
|
||||
|
||||
export function sameDerivativeOption(left: DerivativeOptions, right: DerivativeOptions) {
|
||||
if (left.length !== right.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < left.length; i++) {
|
||||
if (left[i] !== right[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export default class ThemeCache {
|
||||
public static MAX_CACHE_SIZE = 20;
|
||||
public static MAX_CACHE_OFFSET = 5;
|
||||
|
||||
private readonly cache: ThemeCacheMap;
|
||||
private keys: DerivativeOptions[];
|
||||
private cacheCallTimes: number;
|
||||
|
||||
constructor() {
|
||||
this.cache = new Map();
|
||||
this.keys = [];
|
||||
this.cacheCallTimes = 0;
|
||||
}
|
||||
|
||||
public size(): number {
|
||||
return this.keys.length;
|
||||
}
|
||||
|
||||
private internalGet(
|
||||
derivativeOption: DerivativeOptions,
|
||||
updateCallTimes = false,
|
||||
): [Theme<any, any>, number] | undefined {
|
||||
let cache: ReturnType<ThemeCacheMap['get']> = { map: this.cache };
|
||||
derivativeOption.forEach(derivative => {
|
||||
if (!cache) {
|
||||
cache = undefined;
|
||||
} else {
|
||||
cache = cache?.map?.get(derivative);
|
||||
}
|
||||
});
|
||||
if (cache?.value && updateCallTimes) {
|
||||
cache.value[1] = this.cacheCallTimes++;
|
||||
}
|
||||
return cache?.value;
|
||||
}
|
||||
|
||||
public get(derivativeOption: DerivativeOptions): Theme<any, any> | undefined {
|
||||
return this.internalGet(derivativeOption, true)?.[0];
|
||||
}
|
||||
|
||||
public has(derivativeOption: DerivativeOptions): boolean {
|
||||
return !!this.internalGet(derivativeOption);
|
||||
}
|
||||
|
||||
public set(derivativeOption: DerivativeOptions, value: Theme<any, any>): void {
|
||||
// New cache
|
||||
if (!this.has(derivativeOption)) {
|
||||
if (this.size() + 1 > ThemeCache.MAX_CACHE_SIZE + ThemeCache.MAX_CACHE_OFFSET) {
|
||||
const [targetKey] = this.keys.reduce<[DerivativeOptions, number]>(
|
||||
(result, key) => {
|
||||
const [, callTimes] = result;
|
||||
if (this.internalGet(key)![1] < callTimes) {
|
||||
return [key, this.internalGet(key)![1]];
|
||||
}
|
||||
return result;
|
||||
},
|
||||
[this.keys[0], this.cacheCallTimes],
|
||||
);
|
||||
this.delete(targetKey);
|
||||
}
|
||||
|
||||
this.keys.push(derivativeOption);
|
||||
}
|
||||
|
||||
let cache = this.cache;
|
||||
derivativeOption.forEach((derivative, index) => {
|
||||
if (index === derivativeOption.length - 1) {
|
||||
cache.set(derivative, { value: [value, this.cacheCallTimes++] });
|
||||
} else {
|
||||
const cacheValue = cache.get(derivative);
|
||||
if (!cacheValue) {
|
||||
cache.set(derivative, { map: new Map() });
|
||||
} else if (!cacheValue.map) {
|
||||
cacheValue.map = new Map();
|
||||
}
|
||||
cache = cache.get(derivative)!.map!;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private deleteByPath(
|
||||
currentCache: ThemeCacheMap,
|
||||
derivatives: DerivativeFunc<any, any>[],
|
||||
): Theme<any, any> | undefined {
|
||||
const cache = currentCache.get(derivatives[0])!;
|
||||
if (derivatives.length === 1) {
|
||||
if (!cache.map) {
|
||||
currentCache.delete(derivatives[0]);
|
||||
} else {
|
||||
currentCache.set(derivatives[0], { map: cache.map });
|
||||
}
|
||||
return cache.value?.[0];
|
||||
}
|
||||
const result = this.deleteByPath(cache.map!, derivatives.slice(1));
|
||||
if ((!cache.map || cache.map.size === 0) && !cache.value) {
|
||||
currentCache.delete(derivatives[0]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public delete(derivativeOption: DerivativeOptions): Theme<any, any> | undefined {
|
||||
// If cache exists
|
||||
if (this.has(derivativeOption)) {
|
||||
this.keys = this.keys.filter(item => !sameDerivativeOption(item, derivativeOption));
|
||||
return this.deleteByPath(this.cache, derivativeOption);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
import ThemeCache from './ThemeCache';
|
||||
import Theme from './Theme';
|
||||
import type { DerivativeFunc, TokenType } from './interface';
|
||||
|
||||
const cacheThemes = new ThemeCache();
|
||||
|
||||
/**
|
||||
* Same as new Theme, but will always return same one if `derivative` not changed.
|
||||
*/
|
||||
export default function createTheme<
|
||||
DesignToken extends TokenType,
|
||||
DerivativeToken extends TokenType,
|
||||
>(
|
||||
derivatives:
|
||||
| DerivativeFunc<DesignToken, DerivativeToken>[]
|
||||
| DerivativeFunc<DesignToken, DerivativeToken>,
|
||||
) {
|
||||
const derivativeArr = Array.isArray(derivatives) ? derivatives : [derivatives];
|
||||
// Create new theme if not exist
|
||||
if (!cacheThemes.has(derivativeArr)) {
|
||||
cacheThemes.set(derivativeArr, new Theme(derivativeArr));
|
||||
}
|
||||
|
||||
// Get theme from cache and return
|
||||
return cacheThemes.get(derivativeArr)!;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export { default as createTheme } from './createTheme';
|
||||
export { default as Theme } from './Theme';
|
||||
export { default as ThemeCache } from './ThemeCache';
|
||||
export type { TokenType, DerivativeFunc } from './interface';
|
|
@ -0,0 +1,5 @@
|
|||
export type TokenType = object;
|
||||
export type DerivativeFunc<DesignToken extends TokenType, DerivativeToken extends TokenType> = (
|
||||
designToken: DesignToken,
|
||||
derivativeToken?: DerivativeToken,
|
||||
) => DerivativeToken;
|
|
@ -0,0 +1,5 @@
|
|||
import type { CSSObject } from '..';
|
||||
|
||||
export interface Transformer {
|
||||
visit?: (cssObj: CSSObject) => CSSObject;
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
import type { CSSObject } from '..';
|
||||
import type { Transformer } from './interface';
|
||||
|
||||
function splitValues(value: string | number) {
|
||||
if (typeof value === 'number') {
|
||||
return [value];
|
||||
}
|
||||
|
||||
const splitStyle = String(value).split(/\s+/);
|
||||
|
||||
// Combine styles split in brackets, like `calc(1px + 2px)`
|
||||
let temp = '';
|
||||
let brackets = 0;
|
||||
return splitStyle.reduce<string[]>((list, item) => {
|
||||
if (item.includes('(')) {
|
||||
temp += item;
|
||||
brackets += item.split('(').length - 1;
|
||||
} else if (item.includes(')')) {
|
||||
temp += ` ${item}`;
|
||||
brackets -= item.split(')').length - 1;
|
||||
if (brackets === 0) {
|
||||
list.push(temp);
|
||||
temp = '';
|
||||
}
|
||||
} else if (brackets > 0) {
|
||||
temp += ` ${item}`;
|
||||
} else {
|
||||
list.push(item);
|
||||
}
|
||||
return list;
|
||||
}, []);
|
||||
}
|
||||
|
||||
type MatchValue = string[] & {
|
||||
notSplit?: boolean;
|
||||
};
|
||||
|
||||
function noSplit(list: MatchValue): MatchValue {
|
||||
list.notSplit = true;
|
||||
return list;
|
||||
}
|
||||
|
||||
const keyMap: Record<string, MatchValue> = {
|
||||
// Inset
|
||||
inset: ['top', 'right', 'bottom', 'left'],
|
||||
insetBlock: ['top', 'bottom'],
|
||||
insetBlockStart: ['top'],
|
||||
insetBlockEnd: ['bottom'],
|
||||
insetInline: ['left', 'right'],
|
||||
insetInlineStart: ['left'],
|
||||
insetInlineEnd: ['right'],
|
||||
|
||||
// Margin
|
||||
marginBlock: ['marginTop', 'marginBottom'],
|
||||
marginBlockStart: ['marginTop'],
|
||||
marginBlockEnd: ['marginBottom'],
|
||||
marginInline: ['marginLeft', 'marginRight'],
|
||||
marginInlineStart: ['marginLeft'],
|
||||
marginInlineEnd: ['marginRight'],
|
||||
|
||||
// Padding
|
||||
paddingBlock: ['paddingTop', 'paddingBottom'],
|
||||
paddingBlockStart: ['paddingTop'],
|
||||
paddingBlockEnd: ['paddingBottom'],
|
||||
paddingInline: ['paddingLeft', 'paddingRight'],
|
||||
paddingInlineStart: ['paddingLeft'],
|
||||
paddingInlineEnd: ['paddingRight'],
|
||||
|
||||
// Border
|
||||
borderBlock: noSplit(['borderTop', 'borderBottom']),
|
||||
borderBlockStart: noSplit(['borderTop']),
|
||||
borderBlockEnd: noSplit(['borderBottom']),
|
||||
borderInline: noSplit(['borderLeft', 'borderRight']),
|
||||
borderInlineStart: noSplit(['borderLeft']),
|
||||
borderInlineEnd: noSplit(['borderRight']),
|
||||
|
||||
// Border width
|
||||
borderBlockWidth: ['borderTopWidth', 'borderBottomWidth'],
|
||||
borderBlockStartWidth: ['borderTopWidth'],
|
||||
borderBlockEndWidth: ['borderBottomWidth'],
|
||||
borderInlineWidth: ['borderLeftWidth', 'borderRightWidth'],
|
||||
borderInlineStartWidth: ['borderLeftWidth'],
|
||||
borderInlineEndWidth: ['borderRightWidth'],
|
||||
|
||||
// Border style
|
||||
borderBlockStyle: ['borderTopStyle', 'borderBottomStyle'],
|
||||
borderBlockStartStyle: ['borderTopStyle'],
|
||||
borderBlockEndStyle: ['borderBottomStyle'],
|
||||
borderInlineStyle: ['borderLeftStyle', 'borderRightStyle'],
|
||||
borderInlineStartStyle: ['borderLeftStyle'],
|
||||
borderInlineEndStyle: ['borderRightStyle'],
|
||||
|
||||
// Border color
|
||||
borderBlockColor: ['borderTopColor', 'borderBottomColor'],
|
||||
borderBlockStartColor: ['borderTopColor'],
|
||||
borderBlockEndColor: ['borderBottomColor'],
|
||||
borderInlineColor: ['borderLeftColor', 'borderRightColor'],
|
||||
borderInlineStartColor: ['borderLeftColor'],
|
||||
borderInlineEndColor: ['borderRightColor'],
|
||||
|
||||
// Border radius
|
||||
borderStartStartRadius: ['borderTopLeftRadius'],
|
||||
borderStartEndRadius: ['borderTopRightRadius'],
|
||||
borderEndStartRadius: ['borderBottomLeftRadius'],
|
||||
borderEndEndRadius: ['borderBottomRightRadius'],
|
||||
};
|
||||
|
||||
function skipCheck(value: string | number) {
|
||||
return { _skip_check_: true, value };
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert css logical properties to legacy properties.
|
||||
* Such as: `margin-block-start` to `margin-top`.
|
||||
* Transform list:
|
||||
* - inset
|
||||
* - margin
|
||||
* - padding
|
||||
* - border
|
||||
*/
|
||||
const transform: Transformer = {
|
||||
visit: cssObj => {
|
||||
const clone: CSSObject = {};
|
||||
|
||||
Object.keys(cssObj).forEach(key => {
|
||||
const value = cssObj[key];
|
||||
const matchValue = keyMap[key];
|
||||
|
||||
if (matchValue && (typeof value === 'number' || typeof value === 'string')) {
|
||||
const values = splitValues(value);
|
||||
|
||||
if (matchValue.length && matchValue.notSplit) {
|
||||
// not split means always give same value like border
|
||||
matchValue.forEach(matchKey => {
|
||||
clone[matchKey] = skipCheck(value);
|
||||
});
|
||||
} else if (matchValue.length === 1) {
|
||||
// Handle like `marginBlockStart` => `marginTop`
|
||||
clone[matchValue[0]] = skipCheck(value);
|
||||
} else if (matchValue.length === 2) {
|
||||
// Handle like `marginBlock` => `marginTop` & `marginBottom`
|
||||
matchValue.forEach((matchKey, index) => {
|
||||
clone[matchKey] = skipCheck(values[index] ?? values[0]);
|
||||
});
|
||||
} else if (matchValue.length === 4) {
|
||||
// Handle like `inset` => `top` & `right` & `bottom` & `left`
|
||||
matchValue.forEach((matchKey, index) => {
|
||||
clone[matchKey] = skipCheck(values[index] ?? values[index - 2] ?? values[0]);
|
||||
});
|
||||
} else {
|
||||
clone[key] = value;
|
||||
}
|
||||
} else {
|
||||
clone[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
return clone;
|
||||
},
|
||||
};
|
||||
|
||||
export default transform;
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* respect https://github.com/cuth/postcss-pxtorem
|
||||
*/
|
||||
import unitless from '@emotion/unitless';
|
||||
import type { CSSObject } from '..';
|
||||
import type { Transformer } from './interface';
|
||||
|
||||
export interface Options {
|
||||
/**
|
||||
* The root font size.
|
||||
* @default 16
|
||||
*/
|
||||
rootValue?: number;
|
||||
/**
|
||||
* The decimal numbers to allow the REM units to grow to.
|
||||
* @default 5
|
||||
*/
|
||||
precision?: number;
|
||||
/**
|
||||
* Whether to allow px to be converted in media queries.
|
||||
* @default false
|
||||
*/
|
||||
mediaQuery?: boolean;
|
||||
}
|
||||
|
||||
const pxRegex = /url\([^)]+\)|var\([^)]+\)|(\d*\.?\d+)px/g;
|
||||
|
||||
function toFixed(number: number, precision: number) {
|
||||
const multiplier = Math.pow(10, precision + 1),
|
||||
wholeNumber = Math.floor(number * multiplier);
|
||||
return (Math.round(wholeNumber / 10) * 10) / multiplier;
|
||||
}
|
||||
|
||||
const transform = (options: Options = {}): Transformer => {
|
||||
const { rootValue = 16, precision = 5, mediaQuery = false } = options;
|
||||
|
||||
const pxReplace = (m: string, $1: any) => {
|
||||
if (!$1) return m;
|
||||
const pixels = parseFloat($1);
|
||||
// covenant: pixels <= 1, not transform to rem @zombieJ
|
||||
if (pixels <= 1) return m;
|
||||
const fixedVal = toFixed(pixels / rootValue, precision);
|
||||
return `${fixedVal}rem`;
|
||||
};
|
||||
|
||||
const visit = (cssObj: CSSObject): CSSObject => {
|
||||
const clone: CSSObject = { ...cssObj };
|
||||
|
||||
Object.entries(cssObj).forEach(([key, value]) => {
|
||||
if (typeof value === 'string' && value.includes('px')) {
|
||||
const newValue = value.replace(pxRegex, pxReplace);
|
||||
clone[key] = newValue;
|
||||
}
|
||||
|
||||
// no unit
|
||||
if (!unitless[key] && typeof value === 'number' && value !== 0) {
|
||||
clone[key] = `${value}px`.replace(pxRegex, pxReplace);
|
||||
}
|
||||
|
||||
// Media queries
|
||||
const mergedKey = key.trim();
|
||||
if (mergedKey.startsWith('@') && mergedKey.includes('px') && mediaQuery) {
|
||||
const newKey = key.replace(pxRegex, pxReplace);
|
||||
|
||||
clone[newKey] = clone[key];
|
||||
delete clone[key];
|
||||
}
|
||||
});
|
||||
|
||||
return clone;
|
||||
};
|
||||
|
||||
return { visit };
|
||||
};
|
||||
|
||||
export default transform;
|
|
@ -0,0 +1,118 @@
|
|||
import hash from '@emotion/hash';
|
||||
import { removeCSS, updateCSS } from '../../vc-util/Dom/dynamicCSS';
|
||||
import canUseDom from '../canUseDom';
|
||||
|
||||
import { Theme } from './theme';
|
||||
|
||||
// Create a cache here to avoid always loop generate
|
||||
const flattenTokenCache = new WeakMap<any, string>();
|
||||
|
||||
export function flattenToken(token: any) {
|
||||
let str = flattenTokenCache.get(token) || '';
|
||||
|
||||
if (!str) {
|
||||
Object.keys(token).forEach(key => {
|
||||
const value = token[key];
|
||||
str += key;
|
||||
if (value instanceof Theme) {
|
||||
str += value.id;
|
||||
} else if (value && typeof value === 'object') {
|
||||
str += flattenToken(value);
|
||||
} else {
|
||||
str += value;
|
||||
}
|
||||
});
|
||||
|
||||
// Put in cache
|
||||
flattenTokenCache.set(token, str);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert derivative token to key string
|
||||
*/
|
||||
export function token2key(token: any, salt: string): string {
|
||||
return hash(`${salt}_${flattenToken(token)}`);
|
||||
}
|
||||
|
||||
const randomSelectorKey = `random-${Date.now()}-${Math.random()}`.replace(/\./g, '');
|
||||
|
||||
// Magic `content` for detect selector support
|
||||
const checkContent = '_bAmBoO_';
|
||||
|
||||
function supportSelector(
|
||||
styleStr: string,
|
||||
handleElement: (ele: HTMLElement) => void,
|
||||
supportCheck?: (ele: HTMLElement) => boolean,
|
||||
): boolean {
|
||||
if (canUseDom()) {
|
||||
updateCSS(styleStr, randomSelectorKey);
|
||||
|
||||
const ele = document.createElement('div');
|
||||
ele.style.position = 'fixed';
|
||||
ele.style.left = '0';
|
||||
ele.style.top = '0';
|
||||
handleElement?.(ele);
|
||||
document.body.appendChild(ele);
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
ele.innerHTML = 'Test';
|
||||
ele.style.zIndex = '9999999';
|
||||
}
|
||||
|
||||
const support = supportCheck
|
||||
? supportCheck(ele)
|
||||
: getComputedStyle(ele).content?.includes(checkContent);
|
||||
|
||||
ele.parentNode?.removeChild(ele);
|
||||
removeCSS(randomSelectorKey);
|
||||
|
||||
return support;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
let canLayer: boolean | undefined = undefined;
|
||||
export function supportLayer(): boolean {
|
||||
if (canLayer === undefined) {
|
||||
canLayer = supportSelector(
|
||||
`@layer ${randomSelectorKey} { .${randomSelectorKey} { content: "${checkContent}"!important; } }`,
|
||||
ele => {
|
||||
ele.className = randomSelectorKey;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return canLayer!;
|
||||
}
|
||||
|
||||
let canWhere: boolean | undefined = undefined;
|
||||
export function supportWhere(): boolean {
|
||||
if (canWhere === undefined) {
|
||||
canWhere = supportSelector(
|
||||
`:where(.${randomSelectorKey}) { content: "${checkContent}"!important; }`,
|
||||
ele => {
|
||||
ele.className = randomSelectorKey;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return canWhere!;
|
||||
}
|
||||
|
||||
let canLogic: boolean | undefined = undefined;
|
||||
export function supportLogicProps(): boolean {
|
||||
if (canLogic === undefined) {
|
||||
canLogic = supportSelector(
|
||||
`.${randomSelectorKey} { inset-block: 93px !important; }`,
|
||||
ele => {
|
||||
ele.className = randomSelectorKey;
|
||||
},
|
||||
ele => getComputedStyle(ele).bottom === '93px',
|
||||
);
|
||||
}
|
||||
|
||||
return canLogic!;
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* source by `dom-closest`
|
||||
* https://github.com/necolas/dom-closest.git
|
||||
*/
|
||||
|
||||
import matches from './dom-matches';
|
||||
|
||||
/**
|
||||
* @param element {Element}
|
||||
* @param selector {String}
|
||||
* @param context {Element=}
|
||||
* @return {Element}
|
||||
*/
|
||||
export default function (element, selector, context) {
|
||||
context = context || document;
|
||||
// guard against orphans
|
||||
element = { parentNode: element };
|
||||
|
||||
while ((element = element.parentNode) && element !== context) {
|
||||
if (matches(element, selector)) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/**
|
||||
* source by `dom-matches`
|
||||
* https://github.com/necolas/dom-matches.git
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determine if a DOM element matches a CSS selector
|
||||
*
|
||||
* @param {Element} elem
|
||||
* @param {String} selector
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
export default function matches(elem, selector) {
|
||||
// Vendor-specific implementations of `Element.prototype.matches()`.
|
||||
const proto = window.Element.prototype;
|
||||
const nativeMatches =
|
||||
proto.matches ||
|
||||
proto.mozMatchesSelector ||
|
||||
proto.msMatchesSelector ||
|
||||
proto.oMatchesSelector ||
|
||||
proto.webkitMatchesSelector;
|
||||
|
||||
if (!elem || elem.nodeType !== 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const parentElem = elem.parentNode;
|
||||
|
||||
// use native 'matches'
|
||||
if (nativeMatches) {
|
||||
return nativeMatches.call(elem, selector);
|
||||
}
|
||||
|
||||
// native support for `matches` is missing and a fallback is required
|
||||
const nodes = parentElem.querySelectorAll(selector);
|
||||
const len = nodes.length;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (nodes[i] === elem) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { watchEffect, shallowRef } from 'vue';
|
||||
import type { ComputedRef } from 'vue';
|
||||
export declare type ComputedGetter<T> = (...args: any[]) => T;
|
||||
export default function eagerComputed<T>(fn: ComputedGetter<T>) {
|
||||
const result = shallowRef<T>();
|
||||
watchEffect(
|
||||
() => {
|
||||
result.value = fn();
|
||||
},
|
||||
{
|
||||
flush: 'sync', // needed so updates are immediate.
|
||||
},
|
||||
);
|
||||
|
||||
return result as any as ComputedRef<T>;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
type RecordType = Record<string, any>;
|
||||
|
||||
function extendsObject<T extends RecordType>(...list: T[]) {
|
||||
const result: RecordType = { ...list[0] };
|
||||
|
||||
for (let i = 1; i < list.length; i++) {
|
||||
const obj = list[i];
|
||||
if (obj) {
|
||||
Object.keys(obj).forEach(key => {
|
||||
const val = obj[key];
|
||||
if (val !== undefined) {
|
||||
result[key] = val;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export default extendsObject;
|
|
@ -0,0 +1,13 @@
|
|||
import type { SizeType } from '../config-provider/SizeContext';
|
||||
|
||||
export function isPresetSize(size?: SizeType | string | number): size is SizeType {
|
||||
return ['small', 'middle', 'large'].includes(size as string);
|
||||
}
|
||||
|
||||
export function isValidGapNumber(size?: SizeType | string | number): size is number {
|
||||
if (!size) {
|
||||
// The case of size = 0 is deliberately excluded here, because the default value of the gap attribute in CSS is 0, so if the user passes 0 in, we can directly ignore it.
|
||||
return false;
|
||||
}
|
||||
return typeof size === 'number' && !Number.isNaN(size);
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
export function getComponentLocale(props, context, componentName, getDefaultLocale) {
|
||||
let locale = {};
|
||||
if (context && context.antLocale && context.antLocale[componentName]) {
|
||||
locale = context.antLocale[componentName];
|
||||
} else {
|
||||
const defaultLocale = getDefaultLocale();
|
||||
// TODO: make default lang of antd be English
|
||||
// https://github.com/ant-design/ant-design/issues/6334
|
||||
locale = defaultLocale.default || defaultLocale;
|
||||
}
|
||||
|
||||
const result = {
|
||||
...locale,
|
||||
...props.locale,
|
||||
};
|
||||
result.lang = {
|
||||
...locale.lang,
|
||||
...props.locale.lang,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getLocaleCode(context) {
|
||||
const localeCode = context.antLocale && context.antLocale.locale;
|
||||
// Had use LocaleProvide but didn't set locale
|
||||
if (context.antLocale && context.antLocale.exist && !localeCode) {
|
||||
return 'zh-cn';
|
||||
}
|
||||
return localeCode;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue