mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-21 08:29:18 +08:00
commit
d29e6675a5
8
.github/main.workflow
vendored
Normal file
8
.github/main.workflow
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
workflow "New workflow" {
|
||||
on = "push"
|
||||
resolves = ["Auto Assign"]
|
||||
}
|
||||
|
||||
action "Auto Assign" {
|
||||
uses = "kentaro-m/auto-assign@v1.0.0"
|
||||
}
|
124
AUTHORS.txt
124
AUTHORS.txt
@ -1,10 +1,11 @@
|
||||
+v <ljw@live.jp>
|
||||
17073025 <17073025@cnsuning.com>
|
||||
282159468 <282159468@qq.com>
|
||||
778758944 <778758944@qq.com>
|
||||
Aaron Planell López <aaronplanell@gmail.com>
|
||||
Aashutosh Rathi <aashutoshrathi@gmail.com>
|
||||
Aditya Padhi <aditya.padhi@outlook.com>
|
||||
Adrian Dimitrov <dimitrov.adrian@gmail.com>
|
||||
Ahmed AlSammany <ahmed.alsammany@incorta.com>
|
||||
Alan Braithwaite <asbraithwaite@gmail.com>
|
||||
Albert Zheng <lisong.zheng@gmail.com>
|
||||
Albert 理斯特 <shuaizhexu@gmail.com>
|
||||
@ -14,21 +15,27 @@ Alexander Anpleenko <vaeum@yandex.com>
|
||||
Alexander Suevalov <suevalov.work@gmail.com>
|
||||
Alexandre Kirszenberg <a.kirszenberg@gmail.com>
|
||||
Alexey Yakovlev <yallie@yandex.ru>
|
||||
Alfred Qiu <sc941203@gmail.com>
|
||||
Ali Zhdanov <makedonec88@gmail.com>
|
||||
Alireza <alireza.mh@gmail.com>
|
||||
Alvin Abia <alvin.abia@icloud.com>
|
||||
Amorites <751809522@qq.com>
|
||||
Amumu <yoyo837@hotmail.com>
|
||||
Anas Tawfeek <anas.tawfeek@outlook.com>
|
||||
Andre Perunicic <andre@intoli.com>
|
||||
Andrew Murray <radarhere@gmail.com>
|
||||
Andrew Shearer <andrew@ashearer.com>
|
||||
Andrey G <plandem@gmail.com>
|
||||
Andrzej Dybionka <andrzej@arabel.la>
|
||||
André <mazoni.andre@gmail.com>
|
||||
Ardo Kusuma <ardo@uber.com>
|
||||
Arnab Sen <arnabsen@gmail.com>
|
||||
Arthur Denner Oliveira Santos <arthurdenner7@gmail.com>
|
||||
Arvin Xu <arvinx@foxmail.com>
|
||||
Ash Kumar <kumar.ashwin@outlook.com>
|
||||
BK Heleth <bon.hoo@hotmail.com>
|
||||
Babajide Fowotade <jide.b.tade@gmail.com>
|
||||
Barry <barry.yansh@gmail.com>
|
||||
Bartek <bartek.kozera@gmail.com>
|
||||
Benedikt Franke <benedikt@franke.tech>
|
||||
Benjamin Kniffler <bkniffler@me.com>
|
||||
@ -38,6 +45,8 @@ Bernie <bernie.wangbj@gmail.com>
|
||||
Bilal Sirazitdinov <bilalsir@yandex.ru>
|
||||
Bill Sheikh <bilawals22@gmail.com>
|
||||
Bo Chen <bochen2014@yahoo.com>
|
||||
Bolun Zhang <rzhangbolun@gmail.com>
|
||||
Bora Ikizoglu <boraikizoglu@gmail.com>
|
||||
Bozhao <yubz86@gmail.com>
|
||||
Bradley Xu <xgheaven@gmail.com>
|
||||
Brett Lamy <bel423@me.com>
|
||||
@ -47,6 +56,7 @@ Bruno Maia <bruno.mm.maia@gmail.com>
|
||||
Bryan Berger <bb@ga.co>
|
||||
C <4019980@qq.com>
|
||||
C.J. Winslow <whoaa512@gmail.com>
|
||||
CORP\lianyufeng <15275222711@163.com>
|
||||
Cam Song <neosoyn@gmail.com>
|
||||
Camol <kwwnjujlc@sina.com>
|
||||
Cang Ta <hoksilato176@gmail.com>
|
||||
@ -58,6 +68,7 @@ Chandler Moisen <chandlermoisen@gmail.com>
|
||||
Chang Wang <cheapsteak@gmail.com>
|
||||
Charles Covey-Brandt <chazcb@gmail.com>
|
||||
Chelsea Huang <chelsea.huang@sap.com>
|
||||
Cheng Liu <liucheng.tech@outlook.com>
|
||||
Chenjia <ariesjia00@hotmail.com>
|
||||
Chikara Chan <chenhongtu@51xianqu.net>
|
||||
Chris Kelly <cjke.7777@gmail.com>
|
||||
@ -119,11 +130,16 @@ Eward Song <eward.song@gmail.com>
|
||||
Federico Marcos <marcosfede@gmail.com>
|
||||
Fergus Leung <fergusleung96@gmail.com>
|
||||
Fernando Giarritiello <fgiarritiello@gmail.com>
|
||||
Florian Orpelière <florian.orpeliere@gmail.com>
|
||||
Flynn <li.fulin@foxmail.com>
|
||||
For177 <mengqiang.q@gmail.com>
|
||||
Gabe Medrash <gabeme@alleninstitute.org>
|
||||
Gabriel Nunes <gabriel@multiverso.me>
|
||||
Gao Jiangmiao <tolbkni@gmail.com>
|
||||
Gautier <rollingautier2@gmail.com>
|
||||
Geoff Holden <geoff@brightloudnoise.com>
|
||||
George Gray <george@ummodesign.com>
|
||||
Go7hic <gtfx0209@qq.com>
|
||||
Graeme Yeates <gyeates@clearpath.ai>
|
||||
Graeme Yeates <yeatesgraeme@gmail.com>
|
||||
Grant Klinsing <gklinsing@gmail.com>
|
||||
@ -133,17 +149,22 @@ Guan Yu Pan (Jacky) <jackypan1989@gmail.com>
|
||||
HJin.me <hjin.me@gmail.com>
|
||||
Hai Phan Nguyen <pnghai@gmail.com>
|
||||
Haibin Yu <haibin.yu@oceanwing.com>
|
||||
Hal-pan <hms181231@gmail.com>
|
||||
Hanai <ihanai1991@gmail.com>
|
||||
Hanz Luo <lhz0516@gmail.com>
|
||||
Harlan <luoxwen@gmail.com>
|
||||
HarlanLuo <luoxwen@gmail.com>
|
||||
Haroen Viaene <fingebimus@me.com>
|
||||
Harshit Mehrotra <harshitmehrotra@hotmail.com>
|
||||
Heaven <ne_smalltown@163.com>
|
||||
Henri Normak <henri.normak@gmail.com>
|
||||
HeskeyBaozi <hezhiyu233@foxmail.com>
|
||||
Hieu Ho <hieu.ho.le@lazada.com>
|
||||
Higor Araújo dos Anjos <higor.araujo.anjos@gmail.com>
|
||||
Hubert Argasinski <argasinski.hubert@gmail.com>
|
||||
Hughen <446370503@163.com>
|
||||
Hugo LEHMANN <shogi31@gmail.com>
|
||||
Igor <nemytyshew@yandex.ru>
|
||||
Igor G <i.gaidai4uk@gmail.com>
|
||||
Ilan <hasanovtk@gmail.com>
|
||||
Ilan Hasanov <hasanovtk@gmail.com>
|
||||
@ -154,6 +175,7 @@ Ivan Kravets <me@ikravets.com>
|
||||
Ivan Trofimov <ivan@trofimov.link>
|
||||
Ivo Stratev <ivo.stratev.tues@gmail.com>
|
||||
Jack Hsieh <jack@egenware.com>
|
||||
Jack Lo <jack-lo@foxmail.com>
|
||||
Jack Works <zjwpeter@gmail.com>
|
||||
Jackie.Ls <418292038@qq.com>
|
||||
Jacques Kvam <jwkvam@gmail.com>
|
||||
@ -162,6 +184,7 @@ Jake Richards <jake.richards@genesys.com>
|
||||
James <james@schoolshape.com>
|
||||
JamesYin <elantion@gmail.com>
|
||||
Jaroslav Bereza <github.com@bereza.cz>
|
||||
Jason Chen <ceocjy@vip.qq.com>
|
||||
Jean-Luc Sorak <jlsorak@icloud.com>
|
||||
Jeffrey Carl Faden <jeffreyatw@gmail.com>
|
||||
JeromeLin <jerome.lin@zhongan.com>
|
||||
@ -173,6 +196,7 @@ Jieraaa <842533841@qq.com>
|
||||
Jin ZHANG <jz.zhangjin@gmail.com>
|
||||
Jing Ma <mjingm87@qq.com>
|
||||
Jinxuan Zhu <zhujinxuan@gmail.com>
|
||||
Joao Rabelo <jrabelo@tech6.com.br>
|
||||
Joe <qiaolibo@126.com>
|
||||
Joe Hsu <jhsu.x1@gmail.com>
|
||||
Johannes Loewe <johannes@loewe.pm>
|
||||
@ -181,11 +205,15 @@ John Nguyen <jtnguyen236@gmail.com>
|
||||
Jonatas Walker <jonataswalker@gmail.com>
|
||||
Jonny Buchanan <jonathan.buchanan@gmail.com>
|
||||
Jordan Hornblow <jordan@jch254.com>
|
||||
Josue Peralta <jperal77@gmail.com>
|
||||
Josué <ujosuegt@outlook.com>
|
||||
JribiBelhassen <belha9inzaghi@gmail.com>
|
||||
Juan Rodrigo Venegas Boesch <jrvboesch@gmail.com>
|
||||
Julia Passynkova <ipassynk@hotmail.com>
|
||||
Junyu Zhan <irrigator@yeah.net>
|
||||
Justin Reich <reich.justin@gmail.com>
|
||||
Kaien Liao <liaokaien@gmail.com>
|
||||
Kasra Bigdeli <kasra85@gmail.com>
|
||||
Kenaniah Cerny <kenaniah@gmail.com>
|
||||
Kenneth Luján Rosas <elgenio.03@gmail.com>
|
||||
Kenneth Truong <kenneth.e.truong@gmail.com>
|
||||
@ -200,6 +228,7 @@ Kimmo Saari <kimmo.saari@revolt.fi>
|
||||
Kirill Alexander Khalitov <voronar@gmail.com>
|
||||
Kirill Stiopin <kirill.stiopin@hotmail.com>
|
||||
Knacktus <knacktus@gmail.com>
|
||||
Konrad Machlowski <konrad.machlowski@gmail.com>
|
||||
Kyle Kelley <rgbkrk@gmail.com>
|
||||
Kyle Rosenberg <kyle.rosenberg@gmail.com>
|
||||
LLinFan- <catfoursi@qq.com>
|
||||
@ -218,9 +247,12 @@ Ludwig Bäcklund <ludli839@student.liu.se>
|
||||
Lyndon001 <lld207@126.com>
|
||||
MG12 <wuzhao.mail@gmail.com>
|
||||
Ma Tianxiao <matx2215@outlook.com>
|
||||
Maciej Czekaj <natanielcz@gmail.com>
|
||||
Madis Väin <madisvain@gmail.com>
|
||||
Maksym Mosyura <wmornotwm@gmail.com>
|
||||
Manjit Kumar <manjit1727@gmail.com>
|
||||
Manweill <mic.liangwenwei@foxmail.com>
|
||||
MaoYiWei <137308365@qq.com>
|
||||
Marcela Bomfim <mbomfim@live.com>
|
||||
Marco Afonso <mafonso333@gmail.com>
|
||||
Marcus Bransbury <marcus.bransbury@gmail.com>
|
||||
@ -231,26 +263,34 @@ Martin Litvaj <kamahl19@gmail.com>
|
||||
Martin Novák <martinnovak@outlook.com>
|
||||
Mathew <khayaanimations@gmail.com>
|
||||
Matt Lein <matt.lein@code42.com>
|
||||
Max <maksym.mosyura@kruschecompany.com>
|
||||
Maximilian Meyer <Maximilian.Meyer@br.de>
|
||||
Meck <yesmeck@gmail.com>
|
||||
MeiLin <postget.me@gmail.com>
|
||||
Meow-z <372086270@qq.com>
|
||||
Miaow <i@zfeng.net>
|
||||
Michael Krog <michael.krog@previsto.com>
|
||||
Michael Krog <mic@apaq.dk>
|
||||
Michael Salaverry <barakplasma@gmail.com>
|
||||
Michael Wang <ylzcylx@gmail.com>
|
||||
Michalis Macheras <diodosier@gmail.com>
|
||||
Michelle Zhang <michelle.chsy@gmail.com>
|
||||
Mikasa33 <mikasa33@qq.com>
|
||||
Min <dicklwm@163.com>
|
||||
MinJeong Kim <min7859@gmail.com>
|
||||
Ming Hann <eldy8888@gmail.com>
|
||||
Minqi Pan <pmq2001@gmail.com>
|
||||
Minsung Ryu <ryums0227@gmail.com>
|
||||
Mitchell Demler <mitchell.demler@harcourts.net>
|
||||
Mohamed Seada <mohamed.seada.1994@gmail.com>
|
||||
Mohammad Faisal <faisalhmohd@gmail.com>
|
||||
Mohan Ban <banmohan@outlook.com>
|
||||
Mounish Sai <pvsmounish@gmail.com>
|
||||
Mr.Tone <vector@malubei.com>
|
||||
MuYu <mr.muzea@gmail.com>
|
||||
Mário Gonçalves <mario.mc.goncalves@gmail.com>
|
||||
Nathan Broadbent <git@ndbroadbent.com>
|
||||
Nathan Griffin <nathan@gatherhere.com>
|
||||
Nathan Schneider <n.l.schneider@gmail.com>
|
||||
Nathan Tavares Nascimento <nathan.tnascimento@gmail.com>
|
||||
Nathan Wells <nwwells@gmail.com>
|
||||
Neekey <ni184775761@gmail.com>
|
||||
@ -258,8 +298,10 @@ Nekron <nekron.hyt@gmail.com>
|
||||
Neverland <chenjiahan@buaa.edu.cn>
|
||||
Nico <nicolas@freddelacompta.com>
|
||||
Nidhi Agarwal <nidhi.agarwal@zomato.com>
|
||||
Niko Autio <niko.autio@fenten.fi>
|
||||
Nikolay <veseliy07@gmail.com>
|
||||
Nikolay Solovyov <i@mr-ozio.ru>
|
||||
Nima Dehnashi <nima@getaround.com>
|
||||
Nimo <nimo.jser@gmail.com>
|
||||
Nishant Arora <na.nishantarora@gmail.com>
|
||||
Nokecy <Nokecy@163.com>
|
||||
@ -268,6 +310,8 @@ Oleg Kuzava <olegkuzava@gmail.com>
|
||||
Oleksandr Kovalchuk <me.olexandr.kovalchuk@gmail.com>
|
||||
Ooi Yee Wei <ywooi@yahoo.com>
|
||||
Open Next <opennext@126.com>
|
||||
Oren Kosto <oren@panda-os.com>
|
||||
Oren Kosto <orenkosto86@gmail.com>
|
||||
OuYancey <ou.yancey@gmail.com>
|
||||
Panjie Setiawan Wicaksono <panjie@panjiesw.com>
|
||||
Patrick Gidich <patrick.gidich@simnova.com>
|
||||
@ -275,6 +319,7 @@ Patryk <longer44@gmail.com>
|
||||
Peter <usstpeter@gmail.com>
|
||||
Peter Berg <atticusberg@gmail.com>
|
||||
Phanupong Janthapoon <panupong.jtp@gmail.com>
|
||||
Philip Oliver <philipodev@gmail.com>
|
||||
Pierre <pierre@bazoge.com>
|
||||
Pierre Neter <pierreneter@gmail.com>
|
||||
Piper Chester <piperchester@gmail.com>
|
||||
@ -282,12 +327,14 @@ Pixy Yuan <pixy.bupt@gmail.com>
|
||||
Pooya Parsa <pyapar@gmail.com>
|
||||
Pyiner <lijiuyang1992@gmail.com>
|
||||
Pyroboomka <qwaarty@mail.ru>
|
||||
QC-L <github@liqichang.com>
|
||||
Qiaosen Huang <joesonw@gmail.com>
|
||||
Qingrong Ke <keqingrong1992@gmail.com>
|
||||
Rafael Cosman <rafaelcosman@alumni.stanford.edu>
|
||||
Rahul Gurung <gurungrahul2@gmail.com>
|
||||
Rallets <rallet@rallets.com>
|
||||
Ramsés Moreno <ramses@cuatromedios.com>
|
||||
Ran Byron <ranbena@gmail.com>
|
||||
Randy <randypriv@gmail.com>
|
||||
RaoHai <surgesoft@gmail.com>
|
||||
Raphael Chauveau <raph.chauveau@gmail.com>
|
||||
@ -300,10 +347,12 @@ Robert Wilkinson <wilkinson.robert.a@gmail.com>
|
||||
Rohan Malhotra <rohan.root@gmail.com>
|
||||
Rongjian Zhang <pd4d10@gmail.com>
|
||||
Rrrandom <emanonhere@gmail.com>
|
||||
RunningCoderLee <sprint_l@aliyun.com>
|
||||
RyanHui <ryanhui1996@gmail.com>
|
||||
SHEN Lin <shenlin192@gmail.com>
|
||||
Sakol Assawasagool <koobitor@gmail.com>
|
||||
Sam Chen <chenxsan@gmail.com>
|
||||
Sam Lanning <sam@samlanning.com>
|
||||
Sam Maxwell <sam@paybase.io>
|
||||
Samuel Gaus <sam@gaus.co.uk>
|
||||
Sangle <whb97@163.com>
|
||||
@ -315,23 +364,31 @@ Sean Sun <pinggodstudio@gmail.com>
|
||||
Sebastian Blade <blade254353074@hotmail.com>
|
||||
Sebastian Busch <mail@sebastian-bus.ch>
|
||||
Sebastian Busch <s.busch@qbus-enet.de>
|
||||
Sergey Volynkin <sergey.volynkin@akvelon.com>
|
||||
Sergio Crisostomo <sergiosbox@gmail.com>
|
||||
Shawn Sit <xueqingxiao@gmail.com>
|
||||
ShiTengFei <shitengfei@goyoo.com>
|
||||
Shuai Chen <wasd2144@hotmail.com>
|
||||
Shubham Kanodia <shubhamsizzles@gmail.com>
|
||||
Shun <polytechnics.shun@gmail.com>
|
||||
Shuvalov Anton <anton@shuvalov.info>
|
||||
SimaQ <sima.zhang1990@gmail.com>
|
||||
Simo Aleksandrov <simo3003@me.com>
|
||||
Spencer <spjy@hawaii.edu>
|
||||
Stephen Esser <Stephen.Esser@gmail.com>
|
||||
Subroto <shub1493biswas@gmail.com>
|
||||
Sven Efftinge <sven.efftinge@typefox.io>
|
||||
Tao <magicdawn@qq.com>
|
||||
Tao Zhang <windse7en@gmail.com>
|
||||
Taylor Sabell <taylorsabell@gmail.com>
|
||||
Teng YANG <morenyang88@gmail.com>
|
||||
Teng YANG <yangteng@me.com>
|
||||
Tengjiao Cai <caitengjiao1987@gmail.com>
|
||||
Terence <trence320@163.com>
|
||||
The Rock <zhoguoxin@126.com>
|
||||
Thibault Derousseaux <tde@activeviam.com>
|
||||
Thiebaud Thomas <thiebaud.tom@gmail.com>
|
||||
Thomas <tom@axisj.com>
|
||||
Tino D <ginodeis@gmail.com>
|
||||
Tom Gao <tom@zoomsoft.cc>
|
||||
Tom Xu <tom.xu@antcosa.com>
|
||||
@ -345,16 +402,19 @@ Tyler <chaotyler@gmail.com>
|
||||
Ubaldo Quintana <blkdr@hotmail.com>
|
||||
Vadim Macagon <vadim.macagon@gmail.com>
|
||||
Valentin Vichnal <valentin@vichnal.com>
|
||||
Van Nguyen <vnguyen94@gmail.com>
|
||||
Vemund Santi <vemund@santi.no>
|
||||
Vic <709147950@qq.com>
|
||||
Vincent Zhang <vxzhong@qq.com>
|
||||
Vitaliy Mazurenko <vitaliymazurenko@gmail.com>
|
||||
ViviaRui <zr1450995198@163.com>
|
||||
Vu Hoang Minh <vuhminh@gmail.com>
|
||||
Walter Barbagallo <brb.walter@gmail.com>
|
||||
Walter Barbagallo <turbometalskater@gmail.com>
|
||||
Wang Jun <amos.callmexyz@gmail.com>
|
||||
Wang Riwu <riwu0730@gmail.com>
|
||||
Wang Zhengchen <wang909208@163.com>
|
||||
Wang yb <wangyibu123@gmail.com>
|
||||
Warren Seymour <warren@fountainhead.tech>
|
||||
Wei Zhu <yesmeck@gmail.com>
|
||||
Wenchao Hu <zjuhwc@gmail.com>
|
||||
@ -369,6 +429,7 @@ Xiping.wang <527409987@qq.com>
|
||||
XuMM_12 <owiatsq@sina.cn>
|
||||
Yang <504021398@qq.com>
|
||||
Yang Bin <yangkghjh@gmail.com>
|
||||
Yangzhedi <uiryzd@163.com>
|
||||
Yasin Uslu <nepjua@gmail.com>
|
||||
Yevhen Hryhorevskyi <evgeniygrigorevskiy@gmail.com>
|
||||
Yiming <ymjrcc@qq.com>
|
||||
@ -390,10 +451,13 @@ Zheeeng <hi@zheeeng.me>
|
||||
Zhiqiang Gong <elory0513@hotmail.com>
|
||||
Ziluo <gyfzzu@gmail.com>
|
||||
Zohaib Ijaz <mzohaib.qc@gmail.com>
|
||||
aashutoshrathi <aashutoshrathi@gmail.com>
|
||||
afc163 <afc163@gmail.com>
|
||||
agent-z <1607291079@qq.com>
|
||||
ahalimkara <ahalimkara@gmail.com>
|
||||
alex <379118572@qq.com>
|
||||
alexchen <alexchen@easyops.cn>
|
||||
amedora <americandragsterracing@gmail.com>
|
||||
arifemrecelik <ce.arifemre@gmail.com>
|
||||
ascoders <576625322@qq.com>
|
||||
ashishg-qburst <ashishg@qburst.com>
|
||||
@ -402,16 +466,19 @@ bang <sqibang@gmail.com>
|
||||
bang88 <sqibang@gmail.com>
|
||||
baozefeng <727751065@qq.com>
|
||||
blankzust <450811238@qq.com>
|
||||
bukas <yhz1219@gmail.com>
|
||||
byuanama <byuan@ama.com.au>
|
||||
byzyk <bohdan.kh@gmail.com>
|
||||
bzone <yarnbcoder@gmail.com>
|
||||
caoyi <caoyi0905@mail.hfut.edu.cn>
|
||||
carrie-tanminyi <12mytan@gmail.com>
|
||||
cathayandy <wzm_andy@126.com>
|
||||
cc189 <cc189dev@gmail.com>
|
||||
chaofeis <408067385@qq.com>
|
||||
chchen <cc272309126@gmail.com>
|
||||
chencheng (云谦) <sorrycc@gmail.com>
|
||||
chencheng <sorrycc@gmail.com>
|
||||
chunlea <ichunlea@me.com>
|
||||
cjahv <cjahv@qq.com>
|
||||
clinyong <clinyong@gmail.com>
|
||||
codesign <zuishiguang@126.com>
|
||||
@ -430,6 +497,7 @@ djorkaeff <djorkae55@gmail.com>
|
||||
duzliang <duzliang@gmail.com>
|
||||
ecofe <150641329@qq.com>
|
||||
edgji <j.edgji@gmail.com>
|
||||
eidonjoe <806488716@qq.com>
|
||||
elios <elios264@hotmail.com>
|
||||
elrrrrrrr <elrrrrrrr@gmail.com>
|
||||
ezpub <ez.foro@gmail.com>
|
||||
@ -440,6 +508,7 @@ frezc <504021398@qq.com>
|
||||
genie <genie88@163.com>
|
||||
gregahren <grega.hren@gmail.com>
|
||||
guifu <picodoth@gmail.com>
|
||||
gyh9457 <gyh9457@163.com>
|
||||
handycode <lihandi@gmail.com>
|
||||
hank <stonehank310@gmail.com>
|
||||
hanpei <75189218@qq.com>
|
||||
@ -453,15 +522,21 @@ henryv0 <henryvo94@gmail.com>
|
||||
hi-caicai <hi@cai-cai.me>
|
||||
hongxuWei <hongxu.wei@outlook.com>
|
||||
huangyan.py <huangyan.py@bytedance.com>
|
||||
huishiyi <zhou1maple@gmail.com>
|
||||
huzzbuzz <huzzbuzz@outlook.com>
|
||||
iamcastelli <sowed@cyberdude.com>
|
||||
ilanus <hasanovtk@gmail.com>
|
||||
imhele <work@imhele.com>
|
||||
imosapatryk <imosa.patryk@gmail.com>
|
||||
infeng <fzhihao@outlook.com>
|
||||
int2d <int2d@qq.com>
|
||||
iojichervo <ioji@chervonagura.com.ar>
|
||||
ioldfish <fish.wangl@gmail.com>
|
||||
iugo <iugogogo@gmail.com>
|
||||
j3l11234 <297259024@qq.com>
|
||||
jasonslyvia <jasonslyvia@gmail.com>
|
||||
jasonxia23 <xia.jason23@gmail.com>
|
||||
jiajiangxu <minesaner@163.com>
|
||||
jiang <155259966@qq.com>
|
||||
jim <wasd2144@hotmail.com>
|
||||
jinouwuque <ee2win@gmail.com>
|
||||
@ -476,10 +551,12 @@ kayw <kayw@outlook.com>
|
||||
kdenz <ksnz93@gmail.com>
|
||||
kdepp <kdepp.cd@gmail.com>
|
||||
keng <keng@renderinghouse.com>
|
||||
kenve <zwei.xie@gmail.com>
|
||||
keqingrong <keqingrong1992@gmail.com>
|
||||
ko <git@yaksok.net>
|
||||
konakona <lovekonakona@gmail.com>
|
||||
kossel <lis.yichao@gmail.com>
|
||||
kristof0425 <dombi.kristof@gmail.com>
|
||||
kuang <p2227@hotmail.com>
|
||||
kuitos <kuitos.lau@gmail.com>
|
||||
kun sam <kunsam624@icloud.com>
|
||||
@ -492,6 +569,7 @@ lgmcolin <lgmcolin@gmail.com>
|
||||
liangfei <njliangfei@gmail.com>
|
||||
liekkas <zjq0717@163.com>
|
||||
lihqi <455711093@qq.com>
|
||||
lilun <lilun_cd@keruyun.com>
|
||||
littleLane <857183384@qq.com>
|
||||
lixiaochou077 <qi.liqi07@gmail.com>
|
||||
lixiaoyang <lixiaoyang2345@gmail.com>
|
||||
@ -501,7 +579,9 @@ lizhen <lizhen@youzan.com>
|
||||
loganpowell <loganp@tepper.cmu.edu>
|
||||
luyiming <luyimingchn@gmail.com>
|
||||
lvren <luren6049@qq.com>
|
||||
lyhper <lyhper@gmail.com>
|
||||
mArker <252133226@qq.com>
|
||||
maks <pine3ree@gmail.com>
|
||||
memoryza <jincai.wang@foxmail.com>
|
||||
mgrdevport <mgrdevport@gmail.com>
|
||||
mitchell.demler <mitchell.demler@harcourts.net>
|
||||
@ -509,15 +589,19 @@ mkermani144 <mkermani144@gmail.com>
|
||||
mmmveggies <jakeselig@gmail.com>
|
||||
mofelee <mofe@me.com>
|
||||
monkindey <monkindey@163.com>
|
||||
mraiguo <810158465@qq.com>
|
||||
mraiguo <mraiguo@gmail.com>
|
||||
mushan0x0 <mushan0x0@gmail.com>
|
||||
muzea <mr.muzea@gmail.com>
|
||||
muzuiget <muzuiget@gmail.com>
|
||||
natergj <nater_nater@me.com>
|
||||
neekey <ni184775761@gmail.com>
|
||||
nick-ChenZe <chenze2168@gmail.com>
|
||||
niko <644506165@qq.com>
|
||||
nikogu <644506165@qq.com>
|
||||
nuintun <nuintun@qq.com>
|
||||
ohhoney1 <1269075501@qq.com>
|
||||
orzorzorzorz <zy410419243@gmail.com>
|
||||
paranoidjk <hust2012jiangkai@gmail.com>
|
||||
parlop <parlop@gmail.com>
|
||||
pbrink231 <pbrink231@gmail.com>
|
||||
@ -534,11 +618,16 @@ qixian.cs@outlook.com <wasd2144@hotmail.com>
|
||||
qliu <1403927509@qq.com>
|
||||
qubaoming <qubaoming@didichuxing.com>
|
||||
ravirambles <ravirambles@gmail.com>
|
||||
richardison <richard.ison@carleton.ca>
|
||||
ryangun <ryangun@foxmail.com>
|
||||
ryanhoho <hswacoal@gmail.com>
|
||||
ryannz <c5e1856@gmail.com>
|
||||
sadmark <zhoubin@laidian360.com>
|
||||
sallen450 <jqh101@sina.com>
|
||||
sdli <1669375803@qq.com>
|
||||
sfturing <sfturing@gmail.com>
|
||||
shangyuan.ning <shangyuan.ning@manaowan.com>
|
||||
shawtung <shawtung@qq.com>
|
||||
shelwin <wxfans@gmail.com>
|
||||
shenlin192@gmail.com <shenlin192@gmail.com>
|
||||
shlice <licesh@gmail.com>
|
||||
@ -553,32 +642,45 @@ sojournerc <cmeyer@zvelo.com>
|
||||
sorrycc <sorrycc@gmail.com>
|
||||
sosohime <theziming@126.com>
|
||||
spideeee <spideeee@github.com>
|
||||
stevenyuysy <stevenyuysy@gmail.com>
|
||||
stickmy <stickmyc@gmail.com>
|
||||
swindme <swindme@163.com>
|
||||
sylvanasGone <397009765@qq.com>
|
||||
syssam <s.y.s.sam.sys@gmail.com>
|
||||
tangjinzhou <415800467@qq.com>
|
||||
tangjinzhou <tangjinzhou@yidian-inc.com>
|
||||
taoweicn <twchn@live.com>
|
||||
thegatheringstorm <tgs@tgs.blue>
|
||||
thilo-behnke <jan-thilo.behnke@gmx.de>
|
||||
tianli.zhao <275287902@qq.com>
|
||||
tom <caolvchong@gmail.com>
|
||||
twobin <twobin@live.com>
|
||||
u3u <qwq@qwq.cat>
|
||||
undefined <undefined>
|
||||
ustccjw <317713370@qq.com>
|
||||
valleykid <valleykiddy@gmail.com>
|
||||
vgeyi <vgeyiz@126.com>
|
||||
wangshantao <605682551@qq.com>
|
||||
wangshuai <wangshuai@momenta.ai>
|
||||
wangtao0101 <yuecjn@gmail.com>
|
||||
wangxiaolei <fatelei@gmail.com>
|
||||
wangxingkang <156148958@qq.com>
|
||||
wangxingkang <wangxingkang@sensoro.com>
|
||||
wangxueliang <wangxueliang@yidian-inc.com>
|
||||
wanli <wanli@qunhemail.com>
|
||||
warmhug <hualei5280@gmail.com>
|
||||
whtang906 <whtang906@gmail.com>
|
||||
wizawu <wizawu@gmail.com>
|
||||
wonyun <wy393767068@163.com>
|
||||
wwwxy80s <xiaowangziwxy@gmail.com>
|
||||
wx1322 <289758716@qq.com>
|
||||
xiaofan2406 <xiaofan2406@gmail.com>
|
||||
y-take <y.takey@gmail.com>
|
||||
yangwukang <yangwukang@boco.com.cn>
|
||||
yangxiaolin <yangxiao2810279802@gmail.com>
|
||||
ycjcl868 <45808948@qq.com>
|
||||
yeliex <yeliex@yeliex.com>
|
||||
yibu.wang <yibu.wang@orion.co.com>
|
||||
yiminanci <yiminanci@gmail.com>
|
||||
yiminghe <yiminghe@gmail.com>
|
||||
yociduo <yociduo@vip.qq.com>
|
||||
@ -589,22 +691,28 @@ z <haig8@msn.com>
|
||||
zack <zxyah@126.com>
|
||||
zelongc <nickcong123@gmail.com>
|
||||
zerob4wl <zerob4wl@gmail.com>
|
||||
zhangguanyu02 <zhangguanyu02@meituan.com>
|
||||
zhangpc <zhangpc@tenxcloud.com>
|
||||
zhangyangxue <383632607@qq.com>
|
||||
zhaocai <lzc09008@gmail.com>
|
||||
zhaopeidong <lwindscar@gmail.com>
|
||||
zhujun24 <zhujun87654321@gmail.com>
|
||||
zhuyue <fuping.dfp@antfin.com>
|
||||
zilong <jzlxiaohei@163.com>
|
||||
zinkey <yaya@uloveit.com.cn>
|
||||
zlljqn <zlljqn@gmail.com>
|
||||
zollero <corona7@163.com>
|
||||
zombieJ <smith3816@gmail.com>
|
||||
zombiej <smith3816@gmail.com>
|
||||
zongzi531 <zongzi.xy@gmail.com>
|
||||
ztplz <mysticzt@gmail.com>
|
||||
zuiidea <zuiiidea@gmail.com>
|
||||
zy410419243 <zy410419243@gmail.com>
|
||||
°))))彡 <fisherspy@live.com>
|
||||
邦 <sqibang@gmail.com>
|
||||
爱but的苍蝇 <354788473@qq.com>
|
||||
高力 <3071730@qq.com>
|
||||
郑旭 <332171564@qq.com>
|
||||
拷钉 <41830859@qq.com>
|
||||
苏秦 <646382806@qq.com>
|
||||
竹尔 <Juelchiang@gmail.com>
|
||||
@ -615,6 +723,8 @@ zuiidea <zuiiidea@gmail.com>
|
||||
诸岳 <dengfuping_develop@163.com>
|
||||
逸达 <dqaria@gmail.com>
|
||||
诸岳 <fuping.dfp@antfin.com>
|
||||
二哲 <kodo@forchange.cn>
|
||||
廖星 <liaoxing.lx@bytedance.com>
|
||||
刘红 <liuhong1.happy@163.com>
|
||||
宝码 <noyobo@gmail.com>
|
||||
陈帅 <qixian.cs@outlook.com>
|
||||
@ -623,12 +733,15 @@ zuiidea <zuiiidea@gmail.com>
|
||||
愚道 <tingzhao.ytz@antfin.com>
|
||||
陈帅 <wasd2144@hotmail.com>
|
||||
松子 <window.pibarr@gmail.com>
|
||||
何乐 <work@imhele.com>
|
||||
付引 <xxxquotes@gmail.com>
|
||||
可乐 <zaxlct@foxmail.com>
|
||||
山客 <zeakhold@gmail.com>
|
||||
曾凯 <zengkai2009@foxmail.com>
|
||||
低位 <zhujun87654321@gmail.com>
|
||||
信鑫-King <45808948@qq.com>
|
||||
广彬-梁 <326741518@qq.com>
|
||||
小哈husky <951565664@qq.com>
|
||||
何志勇 <15988134176@163.com>
|
||||
徐坤龙 <272992168@qq.com>
|
||||
黄子毅 <576625322@qq.com>
|
||||
@ -637,18 +750,25 @@ zuiidea <zuiiidea@gmail.com>
|
||||
黄文鉴 <concefly@foxmail.com>
|
||||
董天成 <dongtiangche@outlook.com>
|
||||
方剑成 <fjc0kb@gmail.com>
|
||||
陈广亮 <geraldchen890806@gmail.com>
|
||||
包子熊 <hezhiyu233@foxmail.com>
|
||||
闲耘™ <hotoo.cn@gmail.com>
|
||||
一喵呜 <hyb628@gmail.com>
|
||||
黄俊亮 <jayhuang@easyops.cn>
|
||||
吕立青 <jimmy.jinglv@gmail.com>
|
||||
隋鑫磊 <joshuasui@gmail.com>
|
||||
米老朱 <laozhu.me@gmail.com>
|
||||
乔奕轩 <qiao_yixuan@163.com>
|
||||
马斯特 <sd4399340@126.com>
|
||||
王集鹄 <wjhu111@21cn.com>
|
||||
徐新航 <xuxinhang@bytedance.com>
|
||||
杨哲迪 <yangzhedi@yidian-inc.com>
|
||||
柚子男 <yozman@sina.com>
|
||||
愚指导 <yutingzhao1991@sina.com>
|
||||
郭延豪(708674) <gyh9457@163.com>
|
||||
愚指导-TZ <yutingzhao1991@sina.com>
|
||||
杨小事er <Uiryzd@163.com>
|
||||
杨小事er <uiryzd@163.com>
|
||||
超能刚哥 <margox@foxmail.com>
|
||||
马金花儿 <o.o@mug.dog>
|
||||
रोहन मल्होत्रा <rohan.malhotra@adwyze.com>
|
||||
|
@ -15,6 +15,38 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 3.13.6
|
||||
|
||||
`2019-02-23`
|
||||
|
||||
- Form
|
||||
- 🐞 Use new method to repair align issue of Form.Item with validate message. [#14946](https://github.com/ant-design/ant-design/issues/14946)
|
||||
- 🐞 Improved warning message logic of generating Form.Item `help` and `validateStatus`. [#14911](https://github.com/ant-design/ant-design/issues/14911)
|
||||
- 🐞 Fixed extra space at the bottom of Table header in chrome. [#14926](https://github.com/ant-design/ant-design/issues/14926)
|
||||
- 🐞 Fixed that Select check icon is not aligned center. [#15016](https://github.com/ant-design/ant-design/issues/15016)
|
||||
- 🐞 Fixed Input.Search `addonBefore` or `addonAfter` style issue. [#14959](https://github.com/ant-design/ant-design/issues/14959)
|
||||
- 🐞 Fixed growing space of Tree nodes. [#14958](https://github.com/ant-design/ant-design/issues/14958) [@Yangzhedi](https://github.com/Yangzhedi)
|
||||
- 🐞 Improved accessibility of Icon when `type` is falsy. [#14970](https://github.com/ant-design/ant-design/issues/14970)
|
||||
- 🐞 Fixed Dropdown subMenu disabled cursor style. [#14952](https://github.com/ant-design/ant-design/issues/14952)
|
||||
- 🇮🇩 Updated locale to be more natural for Indonesian. [#15013](https://github.com/ant-design/ant-design/issues/15013) [@kamalmahmudi](https://github.com/kamalmahmudi)
|
||||
|
||||
## 3.13.5
|
||||
|
||||
`2019-02-19`
|
||||
|
||||
- 🐞 Revert FormItem with additional place holder. [#14937](https://github.com/ant-design/ant-design/pull/14937)
|
||||
- 🐞 Adjust Input style to support `text-align: inherit`. [#14912](https://github.com/ant-design/ant-design/pull/14912)
|
||||
- 🐞 Fix incorrect collapse icon position when Sider in the right. [#14446](https://github.com/ant-design/ant-design/pull/14446)
|
||||
- 🐞 Fix Table miss top border in some case. [#14922](https://github.com/ant-design/ant-design/pull/14922)
|
||||
- 🐞 Fix some TypeScript definitions. [#14857](https://github.com/ant-design/ant-design/pull/14857) [#14903](https://github.com/ant-design/ant-design/pull/14903)
|
||||
|
||||
## 3.13.4
|
||||
|
||||
`2019-02-18`
|
||||
|
||||
- 🐞 Fix Table ajax load display no data. [#14898](https://github.com/ant-design/ant-design/pull/14898)
|
||||
- 🐞 Fix FormItem margin style not correct. [#14886](https://github.com/ant-design/ant-design/pull/14886)
|
||||
|
||||
## 3.13.3
|
||||
|
||||
`2019-02-16`
|
||||
|
@ -15,6 +15,38 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 3.13.6
|
||||
|
||||
`2019-02-23`
|
||||
|
||||
- Form
|
||||
- 🐞 使用新的方式修复 Form.Item 在有错误提示时的布局对齐问题。[#14946](https://github.com/ant-design/ant-design/issues/14946)
|
||||
- 🐞 优化 Form.Item 自动生成 `help` 和 `validateStatus` 的警告信息。[#14911](https://github.com/ant-design/ant-design/issues/14911)
|
||||
- 🐞 修复 chrome 下 Table 列头有一点额外空白的样式问题。[#14926](https://github.com/ant-design/ant-design/issues/14926)
|
||||
- 🐞 修复 Select 选中图标位置偏下的问题。[#15016](https://github.com/ant-design/ant-design/issues/15016)
|
||||
- 🐞 修复 Input.Search 增加 `addonBefore` 或 `addonAfter` 时的样式问题。[#14959](https://github.com/ant-design/ant-design/issues/14959)
|
||||
- 🐞 修复 Tree 节点内底部边距叠加的问题。[#14958](https://github.com/ant-design/ant-design/issues/14958) [@Yangzhedi](https://github.com/Yangzhedi)
|
||||
- 🐞 优化 Icon 的 `type` 为空时的可访问性问题。[#14970](https://github.com/ant-design/ant-design/issues/14970)
|
||||
- 🐞 修复 Dropdown 的菜单失效样式。[#14952](https://github.com/ant-design/ant-design/issues/14952)
|
||||
- 🇮🇩 优化印度尼西亚国际化文案。[#15013](https://github.com/ant-design/ant-design/issues/15013) [@kamalmahmudi](https://github.com/kamalmahmudi)
|
||||
|
||||
## 3.13.5
|
||||
|
||||
`2019-02-19`
|
||||
|
||||
- 🐞 回滚 FormItem 占位符以修复额外高度的问题。[#14937](https://github.com/ant-design/ant-design/pull/14937)
|
||||
- 🐞 调整 Input 样式以支持 `text-align: inherit`。[#14912](https://github.com/ant-design/ant-design/pull/14912)
|
||||
- 🐞 修复 Sider 在右侧收缩时,图标位置不正确的问题。[#14446](https://github.com/ant-design/ant-design/pull/14446)
|
||||
- 🐞 修复 Table 在某些情况下丢失顶部边框的问题。[#14922](https://github.com/ant-design/ant-design/pull/14922)
|
||||
- 🐞 修复 TypeScript 类型定义。[#14857](https://github.com/ant-design/ant-design/pull/14857) [#14903](https://github.com/ant-design/ant-design/pull/14903)
|
||||
|
||||
## 3.13.4
|
||||
|
||||
`2019-02-18`
|
||||
|
||||
- 🐞 修复 Table 异步加载没有数据的问题。[#14898](https://github.com/ant-design/ant-design/pull/14898)
|
||||
- 🐞 修复 FormItem margin 不正确的问题。[#14886](https://github.com/ant-design/ant-design/pull/14886)
|
||||
|
||||
## 3.13.3
|
||||
|
||||
`2019-02-16`
|
||||
|
@ -123,6 +123,6 @@ Read our [contributing guide](https://ant.design/docs/react/contributing) and le
|
||||
|
||||
We welcome all contributions. Please read our [CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) first. You can submit any ideas as [pull requests](https://github.com/ant-design/ant-design/pulls) or as [GitHub issues](https://github.com/ant-design/ant-design/issues). If you'd like to improve code, check out the [Development Instructions](https://github.com/ant-design/ant-design/wiki/Development) and have a good time! :)
|
||||
|
||||
If you are collaborator. Please follow our [Pull Request principle](https://github.com/ant-design/ant-design/wiki/PR-principle) to create Pull Request by [collaborator template](https://github.com/ant-design/ant-design/compare?expand=1&template=collaborator.md).
|
||||
If you are a collaborator, please follow our [Pull Request principle](https://github.com/ant-design/ant-design/wiki/PR-principle) to create a Pull Request by [collaborator template](https://github.com/ant-design/ant-design/compare?expand=1&template=collaborator.md).
|
||||
|
||||
[![Let's fund issues in this repository](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884)
|
||||
|
@ -1,9 +1,9 @@
|
||||
import warning from 'warning';
|
||||
|
||||
const warned: Record<string, boolean> = {};
|
||||
export default (valid: boolean, message: string): void => {
|
||||
export default (valid: boolean, component: string, message: string): void => {
|
||||
if (!valid && !warned[message]) {
|
||||
warning(false, message);
|
||||
warning(false, `[antd: ${component}] ${message}`);
|
||||
warned[message] = true;
|
||||
}
|
||||
};
|
||||
|
@ -64,6 +64,7 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
const props = this.props;
|
||||
warning(
|
||||
!('linkRender' in props || 'nameRender' in props),
|
||||
'Breadcrumb',
|
||||
'`linkRender` and `nameRender` are removed, please use `itemRender` instead, ' +
|
||||
'see: https://u.ant.design/item-render.',
|
||||
);
|
||||
@ -106,7 +107,8 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
}
|
||||
warning(
|
||||
element.type && element.type.__ANT_BREADCRUMB_ITEM,
|
||||
"Breadcrumb only accepts Breadcrumb.Item as it's children",
|
||||
'Breadcrumb',
|
||||
"Only accepts Breadcrumb.Item as it's children",
|
||||
);
|
||||
return cloneElement(element, {
|
||||
separator,
|
||||
|
@ -23,7 +23,7 @@ describe('Breadcrumb', () => {
|
||||
);
|
||||
expect(errorSpy.mock.calls).toHaveLength(1);
|
||||
expect(errorSpy.mock.calls[0][0]).toMatch(
|
||||
"Breadcrumb only accepts Breadcrumb.Item as it's children",
|
||||
"Warning: [antd: Breadcrumb] Only accepts Breadcrumb.Item as it's children",
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -147,4 +147,18 @@ describe('Calendar', () => {
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
MockDate.reset();
|
||||
});
|
||||
|
||||
it('should trigger onPanelChange when click last month of date', () => {
|
||||
const onPanelChange = jest.fn();
|
||||
const date = new Moment('1990-09-03');
|
||||
const wrapper = mount(<Calendar onPanelChange={onPanelChange} value={date} />);
|
||||
|
||||
wrapper
|
||||
.find('.ant-fullcalendar-cell')
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
|
||||
expect(onPanelChange).toBeCalled();
|
||||
expect(onPanelChange.mock.calls[0][0].month()).toEqual(date.month() - 1);
|
||||
});
|
||||
});
|
||||
|
@ -128,15 +128,21 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
};
|
||||
|
||||
setValue = (value: moment.Moment, way: 'select' | 'changePanel') => {
|
||||
const prevValue = this.props.value || this.state.value;
|
||||
const { mode } = this.state;
|
||||
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ value });
|
||||
}
|
||||
if (way === 'select') {
|
||||
if (prevValue && prevValue.month() !== value.month()) {
|
||||
this.onPanelChange(value, mode);
|
||||
}
|
||||
if (this.props.onSelect) {
|
||||
this.props.onSelect(value);
|
||||
}
|
||||
} else if (way === 'changePanel') {
|
||||
this.onPanelChange(value, this.state.mode);
|
||||
this.onPanelChange(value, mode);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,7 @@ export interface CardGridProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default (props: CardGridProps) => (
|
||||
const Grid: React.SFC<CardGridProps> = props => (
|
||||
<ConfigConsumer>
|
||||
{({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, className, ...others } = props;
|
||||
@ -18,3 +18,5 @@ export default (props: CardGridProps) => (
|
||||
}}
|
||||
</ConfigConsumer>
|
||||
);
|
||||
|
||||
export default Grid;
|
||||
|
@ -11,7 +11,7 @@ export interface CardMetaProps {
|
||||
description?: React.ReactNode;
|
||||
}
|
||||
|
||||
export default (props: CardMetaProps) => (
|
||||
const Meta: React.SFC<CardMetaProps> = props => (
|
||||
<ConfigConsumer>
|
||||
{({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const {
|
||||
@ -45,3 +45,5 @@ export default (props: CardMetaProps) => (
|
||||
}}
|
||||
</ConfigConsumer>
|
||||
);
|
||||
|
||||
export default Meta;
|
||||
|
@ -71,11 +71,13 @@ export default class Card extends React.Component<CardProps, CardState> {
|
||||
if ('noHovering' in this.props) {
|
||||
warning(
|
||||
!this.props.noHovering,
|
||||
'`noHovering` of Card is deprecated, you can remove it safely or use `hoverable` instead.',
|
||||
'Card',
|
||||
'`noHovering` is deprecated, you can remove it safely or use `hoverable` instead.',
|
||||
);
|
||||
warning(
|
||||
!!this.props.noHovering,
|
||||
'`noHovering={false}` of Card is deprecated, use `hoverable` instead.',
|
||||
'Card',
|
||||
'`noHovering={false}` is deprecated, use `hoverable` instead.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -425,7 +425,7 @@ describe('Cascader', () => {
|
||||
wrapper.find('input').simulate('change', { target: { value: 'a' } });
|
||||
expect(wrapper.find('.ant-cascader-menu-item').length).toBe(2);
|
||||
expect(errorSpy).toBeCalledWith(
|
||||
"Warning: 'limit' of showSearch in Cascader should be positive number or false.",
|
||||
"Warning: [antd: Cascader] 'limit' of showSearch should be positive number or false.",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -366,7 +366,8 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
} else {
|
||||
warning(
|
||||
typeof limit !== 'number',
|
||||
"'limit' of showSearch in Cascader should be positive number or false.",
|
||||
'Cascader',
|
||||
"'limit' of showSearch should be positive number or false.",
|
||||
);
|
||||
filtered = flattenOptions.filter(path => filter(this.state.inputValue, path, names));
|
||||
}
|
||||
|
@ -164,9 +164,6 @@ exports[`renders ./components/comment/demo/editor.md correctly 1`] = `
|
||||
rows="4"
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -191,9 +188,6 @@ exports[`renders ./components/comment/demo/editor.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7043,13 +7043,9 @@ exports[`ConfigProvider components Form configProvider 1`] = `
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="config-form-explain-holder"
|
||||
class="config-form-explain"
|
||||
>
|
||||
<span
|
||||
class="config-form-explain"
|
||||
>
|
||||
Bamboo is Light
|
||||
</span>
|
||||
Bamboo is Light
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7080,13 +7076,9 @@ exports[`ConfigProvider components Form normal 1`] = `
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
class="ant-form-explain"
|
||||
>
|
||||
<span
|
||||
class="ant-form-explain"
|
||||
>
|
||||
Bamboo is Light
|
||||
</span>
|
||||
Bamboo is Light
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7117,13 +7109,9 @@ exports[`ConfigProvider components Form prefixCls 1`] = `
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="prefix-Form-explain-holder"
|
||||
class="prefix-Form-explain"
|
||||
>
|
||||
<span
|
||||
class="prefix-Form-explain"
|
||||
>
|
||||
Bamboo is Light
|
||||
</span>
|
||||
Bamboo is Light
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -291,7 +291,11 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
||||
fixLocale(value, localeCode);
|
||||
fixLocale(showDate, localeCode);
|
||||
|
||||
warning(!('onOK' in props), 'It should be `RangePicker[onOk]`, instead of `onOK`!');
|
||||
warning(
|
||||
!('onOK' in props),
|
||||
'RangePicker',
|
||||
'It should be `RangePicker[onOk]`, instead of `onOK`!',
|
||||
);
|
||||
|
||||
const calendarClassName = classNames({
|
||||
[`${prefixCls}-time`]: showTime,
|
||||
|
@ -17,6 +17,11 @@ describe('DatePicker', () => {
|
||||
MockDate.reset();
|
||||
});
|
||||
|
||||
it('support name prop', () => {
|
||||
const wrapper = mount(<DatePicker name="bamboo" />);
|
||||
expect(wrapper.find('input').props().name).toBe('bamboo');
|
||||
});
|
||||
|
||||
it('prop locale should works', () => {
|
||||
const locale = {
|
||||
lang: {
|
||||
|
@ -172,6 +172,7 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
||||
|
||||
warning(
|
||||
!('onOK' in props),
|
||||
'DatePicker',
|
||||
'It should be `DatePicker[onOk]` or `MonthPicker[onOk]`, instead of `onOK`!',
|
||||
);
|
||||
const calendar = (
|
||||
@ -230,6 +231,7 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
||||
placeholder={placeholder}
|
||||
className={props.pickerInputClass}
|
||||
tabIndex={props.tabIndex}
|
||||
name={props.name}
|
||||
{...dataOrAriaProps}
|
||||
/>
|
||||
{clearIcon}
|
||||
|
@ -22,7 +22,7 @@ subtitle: 日期选择框
|
||||
|
||||
### 国际化配置
|
||||
|
||||
默认配置为 en-US,如果你需要设置其他语言,推荐在入口处使用我们提供的国际化组件,详见:[LocaleProvider国际化](http://ant.design/components/locale-provider-cn/)。
|
||||
默认配置为 en-US,如果你需要设置其他语言,推荐在入口处使用我们提供的国际化组件,详见:[LocaleProvider国际化](http://ant.design/components/locale-provider-cn/)。
|
||||
|
||||
如有特殊需求(仅修改单一组件的语言),请使用 locale 参数,参考:[默认配置](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json)。
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
import * as React from 'react';
|
||||
import * as moment from 'moment';
|
||||
import { TimePickerProps } from '../time-picker';
|
||||
import { tuple } from '../_util/type';
|
||||
|
||||
export interface PickerProps {
|
||||
id?: number | string;
|
||||
name?: string;
|
||||
prefixCls?: string;
|
||||
inputPrefixCls?: string;
|
||||
format?: string | string[];
|
||||
@ -31,6 +33,9 @@ export interface SinglePickerProps {
|
||||
onChange?: (date: moment.Moment, dateString: string) => void;
|
||||
}
|
||||
|
||||
const DatePickerModes = tuple('time', 'date', 'month', 'year');
|
||||
export type DatePickerMode = (typeof DatePickerModes)[number];
|
||||
|
||||
export interface DatePickerProps extends PickerProps, SinglePickerProps {
|
||||
className?: string;
|
||||
showTime?: TimePickerProps | boolean;
|
||||
@ -44,9 +49,10 @@ export interface DatePickerProps extends PickerProps, SinglePickerProps {
|
||||
disabledSeconds?: () => number[];
|
||||
};
|
||||
onOpenChange?: (status: boolean) => void;
|
||||
onPanelChange?: (value: moment.Moment | undefined, mode: DatePickerMode) => void;
|
||||
onOk?: (selectedTime: moment.Moment) => void;
|
||||
placeholder?: string;
|
||||
mode?: 'time' | 'date' | 'month' | 'year';
|
||||
mode?: DatePickerMode;
|
||||
}
|
||||
|
||||
export interface MonthPickerProps extends PickerProps, SinglePickerProps {
|
||||
|
@ -37,6 +37,7 @@ export interface DrawerProps {
|
||||
placement?: placementType;
|
||||
onClose?: (e: EventType) => void;
|
||||
className?: string;
|
||||
handler?: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface IDrawerState {
|
||||
@ -234,6 +235,7 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
|
||||
} = this.props;
|
||||
warning(
|
||||
wrapClassName === undefined,
|
||||
'Drawer',
|
||||
'wrapClassName is deprecated, please use className instead.',
|
||||
);
|
||||
const haveMask = rest.mask ? '' : 'no-mask';
|
||||
|
@ -19,13 +19,26 @@ type Placement = (typeof Placements)[number];
|
||||
|
||||
type OverlayFunc = () => React.ReactNode;
|
||||
|
||||
type Align = {
|
||||
points?: [string, string];
|
||||
offset?: [number, number];
|
||||
targetOffset?: [number, number];
|
||||
overflow?: {
|
||||
adjustX?: boolean;
|
||||
adjustY?: boolean;
|
||||
};
|
||||
useCssRight?: boolean;
|
||||
useCssBottom?: boolean;
|
||||
useCssTransform?: boolean;
|
||||
};
|
||||
|
||||
export interface DropDownProps {
|
||||
trigger?: ('click' | 'hover' | 'contextMenu')[];
|
||||
overlay: React.ReactNode | OverlayFunc;
|
||||
onVisibleChange?: (visible: boolean) => void;
|
||||
visible?: boolean;
|
||||
disabled?: boolean;
|
||||
align?: Object;
|
||||
align?: Align;
|
||||
getPopupContainer?: (triggerNode: Element) => HTMLElement;
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
@ -76,6 +89,7 @@ export default class Dropdown extends React.Component<DropDownProps, any> {
|
||||
// Warning if use other mode
|
||||
warning(
|
||||
!overlayProps.mode || overlayProps.mode === 'vertical',
|
||||
'Dropdown',
|
||||
`mode="${overlayProps.mode}" is not supported for Dropdown\'s Menu.`,
|
||||
);
|
||||
|
||||
|
@ -162,6 +162,8 @@
|
||||
&,
|
||||
.@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
|
||||
color: @disabled-color;
|
||||
background-color: @component-background;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ export default class Form extends React.Component<FormProps, any> {
|
||||
constructor(props: FormProps) {
|
||||
super(props);
|
||||
|
||||
warning(!props.form, 'It is unnecessary to pass `form` to `Form` after antd@1.7.0.');
|
||||
warning(!props.form, 'Form', 'It is unnecessary to pass `form` to `Form` after antd@1.7.0.');
|
||||
}
|
||||
|
||||
renderForm = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
|
@ -57,9 +57,12 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
helpShow = false;
|
||||
|
||||
componentDidMount() {
|
||||
const { children, help, validateStatus } = this.props;
|
||||
warning(
|
||||
this.getControls(this.props.children, true).length <= 1,
|
||||
'`Form.Item` cannot generate `validateStatus` and `help` automatically, ' +
|
||||
this.getControls(children, true).length <= 1 ||
|
||||
(help !== undefined || validateStatus !== undefined),
|
||||
'Form.Item',
|
||||
'Cannot generate `validateStatus` and `help` automatically, ' +
|
||||
'while there are more than one `getFieldDecorator` in it.',
|
||||
);
|
||||
}
|
||||
@ -148,26 +151,23 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
renderHelp(prefixCls: string) {
|
||||
const help = this.getHelpMessage();
|
||||
const children = help ? (
|
||||
<span className={`${prefixCls}-explain`} key="help">
|
||||
<div className={`${prefixCls}-explain`} key="help">
|
||||
{help}
|
||||
</span>
|
||||
</div>
|
||||
) : null;
|
||||
if (children) {
|
||||
this.helpShow = !!children;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${prefixCls}-explain-holder`}>
|
||||
<Animate
|
||||
transitionName="show-help"
|
||||
component=""
|
||||
transitionAppear
|
||||
key="help"
|
||||
onEnd={this.onHelpAnimEnd}
|
||||
>
|
||||
{children}
|
||||
</Animate>
|
||||
</div>
|
||||
<Animate
|
||||
transitionName="show-help"
|
||||
component=""
|
||||
transitionAppear
|
||||
key="help"
|
||||
onEnd={this.onHelpAnimEnd}
|
||||
>
|
||||
{children}
|
||||
</Animate>
|
||||
);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,21 +35,17 @@ exports[`Form should display custom message 1`] = `
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
class="ant-form-explain show-help-enter"
|
||||
>
|
||||
<span
|
||||
class="ant-form-explain show-help-enter"
|
||||
>
|
||||
<span>
|
||||
Account does not exist,
|
||||
<a
|
||||
href="https://www.alipay.com/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Forgot account?
|
||||
</a>
|
||||
</span>
|
||||
<span>
|
||||
Account does not exist,
|
||||
<a
|
||||
href="https://www.alipay.com/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Forgot account?
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -93,13 +89,9 @@ exports[`Form should display two message 1`] = `
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
class="ant-form-explain show-help-enter"
|
||||
>
|
||||
<span
|
||||
class="ant-form-explain show-help-enter"
|
||||
>
|
||||
Error message 1 Error message 2
|
||||
</span>
|
||||
Error message 1 Error message 2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -142,19 +134,15 @@ exports[`Form support error message with reactNode 1`] = `
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
class="ant-form-explain show-help-enter"
|
||||
>
|
||||
<span
|
||||
class="ant-form-explain show-help-enter"
|
||||
>
|
||||
<div>
|
||||
Error 1
|
||||
</div>
|
||||
|
||||
<div>
|
||||
Error 2
|
||||
</div>
|
||||
</span>
|
||||
<div>
|
||||
Error 1
|
||||
</div>
|
||||
|
||||
<div>
|
||||
Error 2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@ import Form from '..';
|
||||
describe('Form', () => {
|
||||
// Mock of `querySelector`
|
||||
const originQuerySelector = HTMLElement.prototype.querySelector;
|
||||
HTMLElement.prototype.querySelector = function(str) {
|
||||
HTMLElement.prototype.querySelector = function querySelector(str) {
|
||||
const match = str.match(/^\[id=('|")(.*)('|")]$/);
|
||||
const id = match && match[2];
|
||||
|
||||
|
@ -87,4 +87,43 @@ describe('Form', () => {
|
||||
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should print warning for not generating help and validateStatus automatically', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const Form1 = Form.create()(({ form }) => {
|
||||
return (
|
||||
<Form>
|
||||
<Form.Item label="Account">
|
||||
{form.getFieldDecorator('account')(<input />)}
|
||||
{form.getFieldDecorator('account')(<input />)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
});
|
||||
|
||||
mount(<Form1 />);
|
||||
expect(errorSpy).toBeCalledWith(
|
||||
'Warning: [antd: Form.Item] Cannot generate `validateStatus` and `help` automatically, while there are more than one `getFieldDecorator` in it.',
|
||||
);
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/14911
|
||||
it('should not print warning for not generating help and validateStatus automatically when help or validateStatus is specified', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const Form1 = Form.create()(({ form }) => {
|
||||
return (
|
||||
<Form>
|
||||
<Form.Item label="Account" help="custom help information">
|
||||
{form.getFieldDecorator('account')(<input />)}
|
||||
{form.getFieldDecorator('account')(<input />)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
});
|
||||
|
||||
mount(<Form1 />);
|
||||
expect(errorSpy).not.toHaveBeenCalled();
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -10,14 +10,18 @@ title:
|
||||
自定义或第三方的表单控件,也可以与 Form 组件一起使用。只要该组件遵循以下的约定:
|
||||
> * 提供受控属性 `value` 或其它与 [`valuePropName`](http://ant.design/components/form/#getFieldDecorator-参数) 的值同名的属性。
|
||||
> * 提供 `onChange` 事件或 [`trigger`](http://ant.design/components/form/#getFieldDecorator-参数) 的值同名的事件。
|
||||
> * 不能是函数式组件。
|
||||
> * 支持 ref:
|
||||
> * React@16.8.0 之前只有 Class 组件支持。
|
||||
> * React@16.8.0 及之后可以通过 [useImperativeHandle](https://reactjs.org/docs/hooks-reference.html#useimperativehandle) 添加 ref 支持。([示例](https://codesandbox.io/s/31mv8004rp))
|
||||
|
||||
## en-US
|
||||
|
||||
Customized or third-party form controls can be used in Form, too. Controls must follow these conventions:
|
||||
> * It has a controlled property `value` or other name which is equal to the value of [`valuePropName`](http://ant.design/components/form/?locale=en-US#getFieldDecorator's-parameters).
|
||||
> * It has event `onChange` or an event which name is equal to the value of [`trigger`](http://ant.design/components/form/?locale=en-US#getFieldDecorator's-parameters).
|
||||
> * It must be a class component.
|
||||
> * Support ref:
|
||||
> * Can only use class component before React@16.8.0.
|
||||
> * Can use [useImperativeHandle](https://reactjs.org/docs/hooks-reference.html#useimperativehandle) to add ref support after React@16.8.0. ([Sample](https://codesandbox.io/s/31mv8004rp))
|
||||
|
||||
````jsx
|
||||
import {
|
||||
|
162
components/form/demo/style-check-debug.md
Normal file
162
components/form/demo/style-check-debug.md
Normal file
@ -0,0 +1,162 @@
|
||||
---
|
||||
order: 99
|
||||
title:
|
||||
zh-CN: 提交修改前看看这个对不对
|
||||
en-US: Please check this before commit
|
||||
debug: true
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
提交修改前看看这个对不对。
|
||||
|
||||
## en-US
|
||||
|
||||
Please check this before commit.
|
||||
|
||||
````jsx
|
||||
import {
|
||||
Button, Modal, Form, Row, Col, Input, Select, InputNumber, Radio, DatePicker,
|
||||
} from 'antd';
|
||||
|
||||
const RadioGroup = Radio.Group;
|
||||
const ColSpan = {lg:12,md:24};
|
||||
|
||||
class App extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
visible: false,
|
||||
};
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.setState({
|
||||
visible: true,
|
||||
});
|
||||
};
|
||||
|
||||
handleCancel = () => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
});
|
||||
};
|
||||
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
const { form } = this.props;
|
||||
form.validateFields((error, values) => {
|
||||
console.log(error, values);
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
form: { getFieldDecorator },
|
||||
} = this.props;
|
||||
const { Item } = Form;
|
||||
const itemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
const span = 12;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* Case 1: Form in modal */}
|
||||
<Button onClick={this.handleClick}>打开</Button>
|
||||
<Modal
|
||||
onOk={this.handleSubmit}
|
||||
onCancel={this.handleCancel}
|
||||
title="弹出层"
|
||||
visible={this.state.visible}
|
||||
>
|
||||
<Form layout="horizontal" onSubmit={this.handleSubmit}>
|
||||
<Row>
|
||||
<Col span={span}>
|
||||
<Item {...itemLayout} label="测试字段">
|
||||
{getFieldDecorator("item1", {
|
||||
rules: [{ required: true, message: "请必须填写此字段" }],
|
||||
})(<Input />)}
|
||||
</Item>
|
||||
</Col>
|
||||
<Col span={span}>
|
||||
<Item {...itemLayout} label="测试字段">
|
||||
{getFieldDecorator("item2", {
|
||||
rules: [{ required: true, message: "请必须填写此字段" }],
|
||||
})(<Input />)}
|
||||
</Item>
|
||||
</Col>
|
||||
<Col span={span}>
|
||||
<Item {...itemLayout} label="测试字段">
|
||||
{getFieldDecorator("item3")(<Input />)}
|
||||
</Item>
|
||||
</Col>
|
||||
<Col span={span}>
|
||||
<Item {...itemLayout} label="测试字段">
|
||||
{getFieldDecorator("item4", {
|
||||
rules: [{ required: true, message: "请必须填写此字段" }],
|
||||
})(<Input />)}
|
||||
</Item>
|
||||
</Col>
|
||||
<Col span={span}>
|
||||
<Item {...itemLayout} label="测试字段">
|
||||
{getFieldDecorator("item5", {
|
||||
rules: [{ required: true, message: "请必须填写此字段" }],
|
||||
})(<Input />)}
|
||||
</Item>
|
||||
</Col>
|
||||
<Col span={span}>
|
||||
<Item {...itemLayout} label="测试字段">
|
||||
{getFieldDecorator("item6", {
|
||||
rules: [{ required: true, message: "请必须填写此字段" }],
|
||||
})(<Input />)}
|
||||
</Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
{/* case 2: Form different item */}
|
||||
<Form>
|
||||
<Row gutter={16}>
|
||||
<Col {...ColSpan}>
|
||||
<Item label="input:64.5px">
|
||||
<Input />
|
||||
</Item>
|
||||
</Col>
|
||||
<Col {...ColSpan}>
|
||||
<Item label="select:64px">
|
||||
<Select />
|
||||
</Item>
|
||||
</Col>
|
||||
<Col {...ColSpan}>
|
||||
<Item label="InputNumber:64px">
|
||||
<InputNumber />
|
||||
</Item>
|
||||
</Col>
|
||||
<Col {...ColSpan}>
|
||||
<Item label="DatePicker: 64.5px">
|
||||
<DatePicker />
|
||||
</Item>
|
||||
</Col>
|
||||
<Col {...ColSpan}>
|
||||
<Item label="RadioGroup: 64px">
|
||||
<RadioGroup>
|
||||
<Radio value={0}>男</Radio>
|
||||
<Radio value={1}>女</Radio>
|
||||
</RadioGroup>
|
||||
</Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const WrapApp = Form.create()(App);
|
||||
|
||||
ReactDOM.render(<WrapApp />, mountNode);
|
||||
````
|
||||
|
@ -10,6 +10,11 @@
|
||||
@form-component-max-height: @input-height-lg;
|
||||
@form-feedback-icon-size: @font-size-base;
|
||||
@form-help-margin-top: (@form-component-height - @form-component-max-height) / 2 + 2px;
|
||||
// Extends additional 1px to fix precision issue.
|
||||
// https://github.com/ant-design/ant-design/issues/12803
|
||||
// https://github.com/ant-design/ant-design/issues/8220
|
||||
@form-explain-precision: 1px;
|
||||
@form-explain-height: floor(@font-size-base * @line-height-base);
|
||||
|
||||
.@{form-prefix-cls} {
|
||||
.reset-component;
|
||||
@ -71,13 +76,12 @@ input[type='checkbox'] {
|
||||
}
|
||||
|
||||
.reset-component;
|
||||
margin-bottom: @form-item-margin-bottom - @font-size-base * @line-height-base -
|
||||
@form-help-margin-top;
|
||||
margin-bottom: @form-item-margin-bottom;
|
||||
vertical-align: top;
|
||||
|
||||
&-control {
|
||||
position: relative;
|
||||
line-height: @form-component-max-height - 0.0001px; // https://github.com/ant-design/ant-design/issues/8220
|
||||
line-height: @form-component-max-height;
|
||||
.clearfix;
|
||||
}
|
||||
|
||||
@ -85,6 +89,10 @@ input[type='checkbox'] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&-with-help {
|
||||
margin-bottom: @form-item-margin-bottom - @form-explain-height - @form-help-margin-top;
|
||||
}
|
||||
|
||||
&-label {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
@ -119,29 +127,20 @@ input[type='checkbox'] {
|
||||
}
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-explain-holder {
|
||||
line-height: @line-height-base;
|
||||
|
||||
&::before {
|
||||
content: '\00A0'; // Use non-space character to keep the same height
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-explain {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-explain,
|
||||
.@{form-prefix-cls}-extra {
|
||||
clear: both;
|
||||
min-height: @form-explain-height + @form-explain-precision;
|
||||
margin-top: @form-help-margin-top;
|
||||
color: @text-color-secondary;
|
||||
line-height: @line-height-base;
|
||||
transition: color 0.3s @ease-out; // sync input color transition
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-explain {
|
||||
margin-bottom: -@form-explain-precision;
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-extra {
|
||||
padding-top: 4px;
|
||||
}
|
||||
@ -343,7 +342,10 @@ form {
|
||||
.@{form-prefix-cls}-item-control {
|
||||
line-height: @line-height-base;
|
||||
}
|
||||
.@{form-prefix-cls}-explain,
|
||||
.@{form-prefix-cls}-explain {
|
||||
margin-top: 2px;
|
||||
margin-bottom: -4px - @form-explain-precision;
|
||||
}
|
||||
.@{form-prefix-cls}-extra {
|
||||
margin-top: 2px;
|
||||
margin-bottom: -4px;
|
||||
@ -389,11 +391,7 @@ form {
|
||||
margin-bottom: 0;
|
||||
|
||||
&-with-help {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
margin-bottom: @form-item-margin-bottom;
|
||||
}
|
||||
|
||||
> .@{form-prefix-cls}-item-control-wrapper,
|
||||
@ -599,6 +597,16 @@ form {
|
||||
}
|
||||
}
|
||||
|
||||
.@{ant-prefix}-advanced-search-form {
|
||||
.@{form-prefix-cls}-item {
|
||||
margin-bottom: @form-item-margin-bottom;
|
||||
|
||||
&-with-help {
|
||||
margin-bottom: @form-item-margin-bottom - @form-explain-height - @form-help-margin-top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.show-help-motion(@className, @keyframeName, @duration: @animation-duration-slow) {
|
||||
.make-motion(@className, @keyframeName, @duration);
|
||||
.@{className}-enter,
|
||||
|
@ -100,10 +100,10 @@ export default class Col extends React.Component<ColProps, {}> {
|
||||
<RowContext.Consumer>
|
||||
{({ gutter }) => {
|
||||
let style = others.style;
|
||||
if ((gutter as number) > 0) {
|
||||
if (gutter! > 0) {
|
||||
style = {
|
||||
paddingLeft: (gutter as number) / 2,
|
||||
paddingRight: (gutter as number) / 2,
|
||||
paddingLeft: gutter! / 2,
|
||||
paddingRight: gutter! / 2,
|
||||
...style,
|
||||
};
|
||||
}
|
||||
|
@ -138,10 +138,10 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
className,
|
||||
);
|
||||
const rowStyle =
|
||||
(gutter as number) > 0
|
||||
gutter! > 0
|
||||
? {
|
||||
marginLeft: (gutter as number) / -2,
|
||||
marginRight: (gutter as number) / -2,
|
||||
marginLeft: gutter! / -2,
|
||||
marginRight: gutter! / -2,
|
||||
...style,
|
||||
}
|
||||
: style;
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
exports[`Icon \`component\` prop can access to svg defs if has children 1`] = `
|
||||
<i
|
||||
aria-label="icon: undefined"
|
||||
class="anticon my-home-icon"
|
||||
>
|
||||
<svg
|
||||
@ -25,7 +24,6 @@ exports[`Icon \`component\` prop can access to svg defs if has children 1`] = `
|
||||
|
||||
exports[`Icon should give warning and render <i>{null}</i> 1`] = `
|
||||
<i
|
||||
aria-label="icon: undefined"
|
||||
class="anticon"
|
||||
/>
|
||||
`;
|
||||
@ -258,7 +256,6 @@ exports[`Icon should support older usage 1`] = `
|
||||
|
||||
exports[`Icon should support pass svg paths as children 1`] = `
|
||||
<i
|
||||
aria-label="icon: undefined"
|
||||
class="anticon"
|
||||
>
|
||||
<svg
|
||||
@ -282,7 +279,6 @@ exports[`Icon should support pass svg paths as children 1`] = `
|
||||
|
||||
exports[`Icon should support svg react component 1`] = `
|
||||
<i
|
||||
aria-label="icon: undefined"
|
||||
class="anticon my-home-icon"
|
||||
>
|
||||
<svg
|
||||
@ -335,7 +331,6 @@ exports[`Icon should support two-tone icon 1`] = `
|
||||
|
||||
exports[`Icon support render svg as component 1`] = `
|
||||
<i
|
||||
aria-label="icon: undefined"
|
||||
class="anticon"
|
||||
>
|
||||
<svg
|
||||
@ -352,7 +347,6 @@ exports[`Icon.createFromIconfontCN() should support iconfont.cn 1`] = `
|
||||
class="icons-list"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: undefined"
|
||||
class="anticon"
|
||||
>
|
||||
<svg
|
||||
@ -369,7 +363,6 @@ exports[`Icon.createFromIconfontCN() should support iconfont.cn 1`] = `
|
||||
</svg>
|
||||
</i>
|
||||
<i
|
||||
aria-label="icon: undefined"
|
||||
class="anticon"
|
||||
>
|
||||
<svg
|
||||
@ -386,7 +379,6 @@ exports[`Icon.createFromIconfontCN() should support iconfont.cn 1`] = `
|
||||
</svg>
|
||||
</i>
|
||||
<i
|
||||
aria-label="icon: undefined"
|
||||
class="anticon"
|
||||
>
|
||||
<svg
|
||||
|
@ -121,7 +121,7 @@ describe('Icon', () => {
|
||||
it('warns', () => {
|
||||
mount(<Icon type="clock-circle-o" theme="filled" />);
|
||||
expect(errorSpy).toBeCalledWith(
|
||||
"Warning: The icon name 'clock-circle-o' already specify a theme 'outlined', the 'theme' prop 'filled' will be ignored.",
|
||||
"Warning: [antd: Icon] The icon name 'clock-circle-o' already specify a theme 'outlined', the 'theme' prop 'filled' will be ignored.",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -91,7 +91,8 @@ const Icon: IconComponent<IconProps> = props => {
|
||||
|
||||
warning(
|
||||
Boolean(type || Component || children),
|
||||
'Icon should have `type` prop or `component` prop or `children`.',
|
||||
'Icon',
|
||||
'Should have `type` prop or `component` prop or `children`.',
|
||||
);
|
||||
|
||||
const classString = classNames(
|
||||
@ -137,6 +138,7 @@ const Icon: IconComponent<IconProps> = props => {
|
||||
(React.Children.count(children) === 1 &&
|
||||
React.isValidElement(children) &&
|
||||
React.Children.only(children).type === 'use'),
|
||||
'Icon',
|
||||
'Make sure that you provide correct `viewBox`' +
|
||||
' prop (default `0 0 1024 1024`) to the icon.',
|
||||
);
|
||||
@ -153,6 +155,7 @@ const Icon: IconComponent<IconProps> = props => {
|
||||
const themeInName = getThemeFromTypeName(type);
|
||||
warning(
|
||||
!themeInName || theme === themeInName,
|
||||
'Icon',
|
||||
`The icon name '${type}' already specify a theme '${themeInName}',` +
|
||||
` the 'theme' prop '${theme}' will be ignored.`,
|
||||
);
|
||||
@ -180,7 +183,7 @@ const Icon: IconComponent<IconProps> = props => {
|
||||
<LocaleReceiver componentName="Icon">
|
||||
{(locale: TransferLocale) => (
|
||||
<i
|
||||
aria-label={`${locale.icon}: ${type}`}
|
||||
aria-label={type && `${locale.icon}: ${type}`}
|
||||
{...restProps}
|
||||
tabIndex={iconTabIndex}
|
||||
onClick={onClick}
|
||||
@ -196,6 +199,7 @@ const Icon: IconComponent<IconProps> = props => {
|
||||
function unstable_ChangeThemeOfIconsDangerously(theme?: ThemeType) {
|
||||
warning(
|
||||
false,
|
||||
'Icon',
|
||||
`You are using the unstable method 'Icon.unstable_ChangeThemeOfAllIconsDangerously', ` +
|
||||
`make sure that all the icons with theme '${theme}' display correctly.`,
|
||||
);
|
||||
@ -205,6 +209,7 @@ function unstable_ChangeThemeOfIconsDangerously(theme?: ThemeType) {
|
||||
function unstable_ChangeDefaultThemeOfIcons(theme: ThemeType) {
|
||||
warning(
|
||||
false,
|
||||
'Icon',
|
||||
`You are using the unstable method 'Icon.unstable_ChangeDefaultThemeOfIcons', ` +
|
||||
`make sure that all the icons with theme '${theme}' display correctly.`,
|
||||
);
|
||||
|
@ -43,7 +43,7 @@ export function withThemeSuffix(type: string, theme: ThemeType) {
|
||||
} else if (theme === 'twoTone') {
|
||||
result += '-twotone';
|
||||
} else {
|
||||
warning(false, `This icon '${type}' has unknown theme '${theme}'`);
|
||||
warning(false, 'Icon', `This icon '${type}' has unknown theme '${theme}'`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import Password from './Password';
|
||||
import Icon from '../icon';
|
||||
import { Omit, tuple } from '../_util/type';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
function fixControlledValue<T>(value: T) {
|
||||
if (typeof value === 'undefined' || value === null) {
|
||||
@ -18,6 +19,10 @@ function fixControlledValue<T>(value: T) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function hasPrefixSuffix(props: InputProps) {
|
||||
return 'prefix' in props || props.suffix || props.allowClear;
|
||||
}
|
||||
|
||||
const InputSizes = tuple('small', 'default', 'large');
|
||||
|
||||
export interface InputProps
|
||||
@ -84,6 +89,21 @@ class Input extends React.Component<InputProps, any> {
|
||||
};
|
||||
}
|
||||
|
||||
getSnapshotBeforeUpdate(prevProps: InputProps) {
|
||||
if (hasPrefixSuffix(prevProps) !== hasPrefixSuffix(this.props)) {
|
||||
warning(
|
||||
this.input !== document.activeElement,
|
||||
'Input',
|
||||
`When Input is focused, dynamic add or remove prefix / suffix will make it lose focus caused by dom structure change. Read more: https://ant.design/components/input/#FAQ`,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Since polyfill `getSnapshotBeforeUpdate` need work with `componentDidUpdate`.
|
||||
// We keep an empty function here.
|
||||
componentDidUpdate() {}
|
||||
|
||||
handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
const { onPressEnter, onKeyDown } = this.props;
|
||||
if (e.keyCode === 13 && onPressEnter) {
|
||||
@ -224,7 +244,7 @@ class Input extends React.Component<InputProps, any> {
|
||||
const { props } = this;
|
||||
const suffix = this.renderSuffix(prefixCls);
|
||||
|
||||
if (!('prefix' in props) && !suffix) {
|
||||
if (!hasPrefixSuffix(props)) {
|
||||
return children;
|
||||
}
|
||||
|
||||
|
@ -245,22 +245,29 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
class="ant-input-group ant-input-group-lg"
|
||||
>
|
||||
<div
|
||||
class="ant-col-5"
|
||||
class="ant-row"
|
||||
style="margin-left:-4px;margin-right:-4px"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value="0571"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-8"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value="26888888"
|
||||
/>
|
||||
<div
|
||||
class="ant-col-5"
|
||||
style="padding-left:4px;padding-right:4px"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value="0571"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-8"
|
||||
style="padding-left:4px;padding-right:4px"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value="26888888"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<br />
|
||||
|
@ -19,7 +19,7 @@ Note: You don't need `Col` to control the width in the `compact` mode.
|
||||
|
||||
````jsx
|
||||
import {
|
||||
Input, Col, Select, InputNumber, DatePicker, AutoComplete, Cascader,
|
||||
Input, Col, Row, Select, InputNumber, DatePicker, AutoComplete, Cascader,
|
||||
} from 'antd';
|
||||
|
||||
const InputGroup = Input.Group;
|
||||
@ -68,12 +68,14 @@ class CompactDemo extends React.Component {
|
||||
return (
|
||||
<div>
|
||||
<InputGroup size="large">
|
||||
<Col span={5}>
|
||||
<Input defaultValue="0571" />
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Input defaultValue="26888888" />
|
||||
</Col>
|
||||
<Row gutter={8}>
|
||||
<Col span={5}>
|
||||
<Input defaultValue="0571" />
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Input defaultValue="26888888" />
|
||||
</Col>
|
||||
</Row>
|
||||
</InputGroup>
|
||||
<br />
|
||||
<InputGroup compact>
|
||||
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 前缀和后缀
|
||||
en-US: prefix and suffix
|
||||
zh-CN: 前缀和后缀
|
||||
en-US: prefix and suffix
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
@ -45,7 +45,7 @@ class NumericInput extends React.Component {
|
||||
onBlur = () => {
|
||||
const { value, onBlur, onChange } = this.props;
|
||||
if (value.charAt(value.length - 1) === '.' || value === '-') {
|
||||
onChange({ value: value.slice(0, -1) });
|
||||
onChange(value.slice(0, -1));
|
||||
}
|
||||
if (onBlur) {
|
||||
onBlur();
|
||||
|
@ -56,7 +56,7 @@ The rest of the props of `Input.TextArea` are the same as the original [textarea
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| enterButton | to show an enter button after input | boolean\|ReactNode | false |
|
||||
| enterButton | to show an enter button after input. This prop is conflict with addon. | boolean\|ReactNode | false |
|
||||
| onSearch | The callback function that is triggered when you click on the search-icon or press Enter key. | function(value, event) | |
|
||||
|
||||
Supports all props of `Input`.
|
||||
@ -80,3 +80,16 @@ Supports all props of `Input`.
|
||||
| Property | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| visibilityToggle | Whether show toggle button | boolean | true |
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why Input lose focus when change `prefix/suffix`
|
||||
|
||||
When Input dynamic add or remove `prefix/suffix` will make React recreate the dom structure and new input will be not focused.
|
||||
You can set an empty `<span />` element to keep the dom structure:
|
||||
|
||||
```jsx
|
||||
const suffix = condition ? <Icon type="smile" /> : <span />;
|
||||
|
||||
<Input suffix={suffix} />
|
||||
```
|
||||
|
@ -53,7 +53,7 @@ Input 的其他属性和 React 自带的 [input](https://facebook.github.io/reac
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| enterButton | 是否有确认按钮,可设为按钮文字 | boolean\|ReactNode | false |
|
||||
| enterButton | 是否有确认按钮,可设为按钮文字。该属性会与 addon 冲突。 | boolean\|ReactNode | false |
|
||||
| onSearch | 点击搜索或按下回车键时的回调 | function(value, event) | |
|
||||
|
||||
其余属性和 Input 一致。
|
||||
@ -77,3 +77,16 @@ Input 的其他属性和 React 自带的 [input](https://facebook.github.io/reac
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| visibilityToggle | 是否显示切换按钮 | boolean | true |
|
||||
|
||||
## FAQ
|
||||
|
||||
### 为什么我动态改变 `prefix/suffix` 时,Input 会失去焦点?
|
||||
|
||||
当 Input 动态添加或者删除 `prefix/suffix` 时,React 会重新创建 DOM 结构而新的 input 是没有焦点的。
|
||||
你可以预设一个空的 `<span />` 来保持 DOM 结构不变:
|
||||
|
||||
```jsx
|
||||
const suffix = condition ? <Icon type="smile" /> : <span />;
|
||||
|
||||
<Input suffix={suffix} />
|
||||
```
|
||||
|
@ -15,6 +15,7 @@
|
||||
&-wrapper {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: start;
|
||||
vertical-align: top; // https://github.com/ant-design/ant-design/issues/6403
|
||||
}
|
||||
}
|
||||
|
@ -135,6 +135,7 @@
|
||||
float: left;
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
text-align: inherit;
|
||||
&:focus {
|
||||
z-index: 1; // Fix https://gw.alipayobjects.com/zos/rmsportal/DHNpoqfMXSfrSnlZvhsJ.png
|
||||
border-right-width: 1px;
|
||||
@ -346,6 +347,7 @@
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: start;
|
||||
|
||||
&:hover .@{inputClass}:not(.@{inputClass}-disabled) {
|
||||
.hover();
|
||||
@ -353,6 +355,7 @@
|
||||
|
||||
.@{inputClass} {
|
||||
position: relative;
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
.@{inputClass}-prefix,
|
||||
|
@ -15,14 +15,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
.@{ant-prefix}-input-group-addon {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
&-enter-button {
|
||||
input {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.@{search-prefix}-button {
|
||||
width: 100%;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
input + .@{ant-prefix}-input-group-addon {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
|
||||
.@{search-prefix}-button {
|
||||
width: 100%;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +213,12 @@ class Sider extends React.Component<SiderProps, SiderState> {
|
||||
// special trigger when collapsedWidth == 0
|
||||
const zeroWidthTrigger =
|
||||
parseFloat(String(collapsedWidth || 0)) === 0 ? (
|
||||
<span onClick={this.toggle} className={`${prefixCls}-zero-width-trigger`}>
|
||||
<span
|
||||
onClick={this.toggle}
|
||||
className={`${prefixCls}-zero-width-trigger ${prefixCls}-zero-width-trigger-${
|
||||
reverseArrow ? 'right' : 'left'
|
||||
}`}
|
||||
>
|
||||
<Icon type="bars" />
|
||||
</span>
|
||||
) : null;
|
||||
|
@ -110,6 +110,10 @@
|
||||
&:hover {
|
||||
background: tint(@layout-sider-background, 10%);
|
||||
}
|
||||
|
||||
&-right {
|
||||
left: -@layout-zero-trigger-width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,16 +97,16 @@ export default class List extends React.Component<ListProps> {
|
||||
};
|
||||
}
|
||||
|
||||
renderItem = (item: React.ReactElement<any>, index: number) => {
|
||||
const { dataSource, renderItem, rowKey } = this.props;
|
||||
renderItem = (item: any, index: number) => {
|
||||
const { renderItem, rowKey } = this.props;
|
||||
let key;
|
||||
|
||||
if (typeof rowKey === 'function') {
|
||||
key = rowKey(dataSource[index]);
|
||||
key = rowKey(item);
|
||||
} else if (typeof rowKey === 'string') {
|
||||
key = dataSource[rowKey];
|
||||
key = item[rowKey];
|
||||
} else {
|
||||
key = dataSource.key;
|
||||
key = item.key;
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
|
@ -97265,7 +97265,7 @@ exports[`Locale Provider should display the text as id 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Membatalkan
|
||||
Batal
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
@ -97273,7 +97273,7 @@ exports[`Locale Provider should display the text as id 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
baik
|
||||
OK
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -97312,7 +97312,7 @@ exports[`Locale Provider should display the text as id 1`] = `
|
||||
class="ant-transfer-list-header-selected"
|
||||
>
|
||||
<span>
|
||||
0 barang
|
||||
0 item
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
@ -97328,7 +97328,7 @@ exports[`Locale Provider should display the text as id 1`] = `
|
||||
<div>
|
||||
<input
|
||||
class="ant-input ant-transfer-list-search"
|
||||
placeholder="Cari di sini"
|
||||
placeholder="Cari"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
@ -97457,7 +97457,7 @@ exports[`Locale Provider should display the text as id 1`] = `
|
||||
class="ant-transfer-list-header-selected"
|
||||
>
|
||||
<span>
|
||||
0 barang
|
||||
0 item
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
@ -97473,7 +97473,7 @@ exports[`Locale Provider should display the text as id 1`] = `
|
||||
<div>
|
||||
<input
|
||||
class="ant-input ant-transfer-list-search"
|
||||
placeholder="Cari di sini"
|
||||
placeholder="Cari"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
@ -98603,7 +98603,7 @@ exports[`Locale Provider should display the text as id 1`] = `
|
||||
aria-label="icon: filter"
|
||||
class="anticon anticon-filter ant-dropdown-trigger"
|
||||
tabindex="-1"
|
||||
title="Menu filter"
|
||||
title="Saring"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
@ -98737,7 +98737,7 @@ exports[`Locale Provider should display the text as id 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Membatalkan
|
||||
Batal
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
@ -98745,7 +98745,7 @@ exports[`Locale Provider should display the text as id 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
baik
|
||||
OK
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -10,26 +10,26 @@ export default {
|
||||
TimePicker,
|
||||
Calendar,
|
||||
Table: {
|
||||
filterTitle: 'Menu filter',
|
||||
filterConfirm: 'baik',
|
||||
filterReset: 'Setel ulang',
|
||||
selectAll: 'Pilih halaman saat ini',
|
||||
selectInvert: 'Balikkan halaman saat ini',
|
||||
sortTitle: 'Menyortir',
|
||||
filterTitle: 'Saring',
|
||||
filterConfirm: 'OK',
|
||||
filterReset: 'Hapus',
|
||||
selectAll: 'Pilih semua di halaman ini',
|
||||
selectInvert: 'Balikkan pilihan di halaman ini',
|
||||
sortTitle: 'Urutkan',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'baik',
|
||||
cancelText: 'Membatalkan',
|
||||
justOkText: 'baik',
|
||||
okText: 'OK',
|
||||
cancelText: 'Batal',
|
||||
justOkText: 'OK',
|
||||
},
|
||||
Popconfirm: {
|
||||
okText: 'baik',
|
||||
cancelText: 'Membatalkan',
|
||||
okText: 'OK',
|
||||
cancelText: 'Batal',
|
||||
},
|
||||
Transfer: {
|
||||
titles: ['', ''],
|
||||
searchPlaceholder: 'Cari di sini',
|
||||
itemUnit: 'barang',
|
||||
searchPlaceholder: 'Cari',
|
||||
itemUnit: 'item',
|
||||
itemsUnit: 'item',
|
||||
},
|
||||
Upload: {
|
||||
|
@ -336,9 +336,6 @@ exports[`renders ./components/mention/demo/controlled.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -372,9 +369,6 @@ exports[`renders ./components/mention/demo/controlled.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -88,13 +88,15 @@ export default class Menu extends React.Component<MenuProps, MenuState> {
|
||||
|
||||
warning(
|
||||
!('onOpen' in props || 'onClose' in props),
|
||||
'Menu',
|
||||
'`onOpen` and `onClose` are removed, please use `onOpenChange` instead, ' +
|
||||
'see: https://u.ant.design/menu-on-open-change.',
|
||||
);
|
||||
|
||||
warning(
|
||||
!('inlineCollapsed' in props && props.mode !== 'inline'),
|
||||
"`inlineCollapsed` should only be used when Menu's `mode` is inline.",
|
||||
'Menu',
|
||||
'`inlineCollapsed` should only be used when `mode` is inline.',
|
||||
);
|
||||
|
||||
let openKeys;
|
||||
|
@ -122,9 +122,11 @@
|
||||
&-vertical&-sub,
|
||||
&-vertical-left&-sub,
|
||||
&-vertical-right&-sub {
|
||||
min-width: 160px;
|
||||
padding: 0;
|
||||
border-right: 0;
|
||||
transform-origin: 0 0;
|
||||
|
||||
.@{menu-prefix-cls}-item {
|
||||
left: 0;
|
||||
margin-left: 0;
|
||||
@ -139,11 +141,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-horizontal&-sub,
|
||||
&-vertical&-sub,
|
||||
&-vertical-left&-sub,
|
||||
&-vertical-right&-sub {
|
||||
min-width: 160px;
|
||||
&-horizontal&-sub {
|
||||
min-width: 114px; // in case of submenu width is too big: https://codesandbox.io/s/qvpwm6mk66
|
||||
}
|
||||
|
||||
&-item,
|
||||
|
@ -24,15 +24,18 @@ export default class ActionButton extends React.Component<ActionButtonProps, Act
|
||||
loading: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.autoFocus) {
|
||||
const $this = ReactDOM.findDOMNode(this) as HTMLInputElement;
|
||||
this.timeoutId = setTimeout(() => $this.focus());
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timeoutId);
|
||||
}
|
||||
|
||||
onClick = () => {
|
||||
const { actionFn, closeModal } = this.props;
|
||||
if (actionFn) {
|
||||
|
@ -33,6 +33,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
} = props;
|
||||
warning(
|
||||
!('iconType' in props),
|
||||
'Modal',
|
||||
`The property 'iconType' is deprecated. Use the property 'icon' instead.`,
|
||||
);
|
||||
const icon = props.icon ? props.icon : iconType;
|
||||
|
@ -28,7 +28,8 @@ export default class Popover extends React.Component<PopoverProps, {}> {
|
||||
const { title, content } = this.props;
|
||||
warning(
|
||||
!('overlay' in this.props),
|
||||
'Popover[overlay] is removed, please use Popover[content] instead, ' +
|
||||
'Popover',
|
||||
'`overlay` is removed, please use `content` instead, ' +
|
||||
'see: https://u.ant.design/popover-content',
|
||||
);
|
||||
return (
|
||||
|
@ -123,6 +123,15 @@ describe('Radio', () => {
|
||||
expect(onChange.mock.calls.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should only trigger once when in group with options', () => {
|
||||
const onChange = jest.fn();
|
||||
const options = [{ label: 'Bamboo', value: 'Bamboo' }];
|
||||
const wrapper = mount(<RadioGroup options={options} onChange={onChange} />);
|
||||
|
||||
wrapper.find('input').simulate('change');
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("won't fire change events when value not changes", () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
|
@ -124,7 +124,6 @@ class RadioGroup extends React.Component<RadioGroupProps, RadioGroupState> {
|
||||
prefixCls={prefixCls}
|
||||
disabled={this.props.disabled}
|
||||
value={option}
|
||||
onChange={this.onRadioChange}
|
||||
checked={this.state.value === option}
|
||||
>
|
||||
{option}
|
||||
@ -138,7 +137,6 @@ class RadioGroup extends React.Component<RadioGroupProps, RadioGroupState> {
|
||||
prefixCls={prefixCls}
|
||||
disabled={option.disabled || this.props.disabled}
|
||||
value={option.value}
|
||||
onChange={this.onRadioChange}
|
||||
checked={this.state.value === option.value}
|
||||
>
|
||||
{option.label}
|
||||
|
@ -131,7 +131,8 @@ export default class Select<T = SelectValue> extends React.Component<SelectProps
|
||||
|
||||
warning(
|
||||
props.mode !== 'combobox',
|
||||
'The combobox mode of Select is deprecated, ' +
|
||||
'Select',
|
||||
'The combobox mode is deprecated, ' +
|
||||
'it will be removed in next major version, ' +
|
||||
'please use AutoComplete instead',
|
||||
);
|
||||
|
@ -553,10 +553,10 @@
|
||||
right: @control-padding-horizontal;
|
||||
color: transparent;
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
text-shadow: 0 0.1px 0, 0.1px 0 0, 0 -0.1px 0, -0.1px 0;
|
||||
transform: translateY(-50%);
|
||||
transition: all 0.2s ease;
|
||||
.iconfont-size-under-12px(10px);
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
&:hover .@{select-prefix-cls}-selected-icon {
|
||||
|
@ -24,6 +24,8 @@
|
||||
position: relative;
|
||||
> div > .@{spin-prefix-cls} {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 4;
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
@ -5,22 +5,24 @@ import Icon from '../icon';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
export interface StepsProps {
|
||||
prefixCls?: string;
|
||||
iconPrefix?: string;
|
||||
className?: string;
|
||||
current?: number;
|
||||
direction?: 'horizontal' | 'vertical';
|
||||
iconPrefix?: string;
|
||||
initial?: number;
|
||||
labelPlacement?: 'horizontal' | 'vertical';
|
||||
status?: 'wait' | 'process' | 'finish' | 'error';
|
||||
size?: 'default' | 'small';
|
||||
direction?: 'horizontal' | 'vertical';
|
||||
prefixCls?: string;
|
||||
progressDot?: boolean | Function;
|
||||
size?: 'default' | 'small';
|
||||
status?: 'wait' | 'process' | 'finish' | 'error';
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export interface StepProps {
|
||||
className?: string;
|
||||
description?: React.ReactNode;
|
||||
icon?: React.ReactNode;
|
||||
onClick?: React.MouseEventHandler<any>;
|
||||
status?: 'wait' | 'process' | 'finish' | 'error';
|
||||
title?: React.ReactNode;
|
||||
}
|
||||
|
@ -114,12 +114,14 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
|
||||
warning(
|
||||
!('columnsPageRange' in props || 'columnsPageSize' in props),
|
||||
'Table',
|
||||
'`columnsPageRange` and `columnsPageSize` are removed, please use ' +
|
||||
'fixed columns instead, see: https://u.ant.design/fixed-columns.',
|
||||
);
|
||||
|
||||
warning(
|
||||
!('expandedRowRender' in props) || !('scroll' in props),
|
||||
'Table',
|
||||
'`expandedRowRender` and `scroll` are not compatible. Please use one of them at one time.',
|
||||
);
|
||||
|
||||
@ -731,6 +733,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
typeof rowKey === 'function' ? rowKey(record, index) : (record as any)[rowKey!];
|
||||
warning(
|
||||
recordKey !== undefined,
|
||||
'Table',
|
||||
'Each record in dataSource of table should have a unique `key` prop, ' +
|
||||
'or set `rowKey` of Table to an unique primary key, ' +
|
||||
'see https://u.ant.design/table-row-key',
|
||||
@ -1020,7 +1023,6 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
let current: number;
|
||||
let pageSize: number;
|
||||
const state = this.state;
|
||||
const pagination = this.props.pagination || {};
|
||||
// 如果没有分页的话,默认全部展示
|
||||
if (!this.hasPagination()) {
|
||||
pageSize = Number.MAX_VALUE;
|
||||
@ -1034,11 +1036,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
// ---
|
||||
// 当数据量少于等于每页数量时,直接设置数据
|
||||
// 否则进行读取分页数据
|
||||
if (
|
||||
data.length > pageSize ||
|
||||
pageSize === Number.MAX_VALUE ||
|
||||
(pagination.current === undefined && current * pageSize > data.length)
|
||||
) {
|
||||
if (data.length > pageSize || pageSize === Number.MAX_VALUE) {
|
||||
data = data.filter((_, i) => {
|
||||
return i >= (current - 1) * pageSize && i < current * pageSize;
|
||||
});
|
||||
|
@ -5,6 +5,15 @@ import Table from '..';
|
||||
import Input from '../../input';
|
||||
import Button from '../../button';
|
||||
|
||||
function getDropdownWrapper(wrapper) {
|
||||
return mount(
|
||||
wrapper
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
);
|
||||
}
|
||||
|
||||
describe('Table.filter', () => {
|
||||
const filterFn = (value, record) => record.name.indexOf(value) !== -1;
|
||||
const column = {
|
||||
@ -268,12 +277,7 @@ describe('Table.filter', () => {
|
||||
it('fires change event', () => {
|
||||
const handleChange = jest.fn();
|
||||
const wrapper = mount(createTable({ onChange: handleChange }));
|
||||
const dropdownWrapper = mount(
|
||||
wrapper
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
);
|
||||
const dropdownWrapper = getDropdownWrapper(wrapper);
|
||||
|
||||
dropdownWrapper
|
||||
.find('MenuItem')
|
||||
@ -294,12 +298,7 @@ describe('Table.filter', () => {
|
||||
it('should not fire change event on close filterDropdown without changing anything', () => {
|
||||
const handleChange = jest.fn();
|
||||
const wrapper = mount(createTable({ onChange: handleChange }));
|
||||
const dropdownWrapper = mount(
|
||||
wrapper
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
);
|
||||
const dropdownWrapper = getDropdownWrapper(wrapper);
|
||||
|
||||
dropdownWrapper.find('.clear').simulate('click');
|
||||
|
||||
@ -339,12 +338,7 @@ describe('Table.filter', () => {
|
||||
}),
|
||||
);
|
||||
jest.useFakeTimers();
|
||||
const dropdownWrapper = mount(
|
||||
wrapper
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
);
|
||||
const dropdownWrapper = getDropdownWrapper(wrapper);
|
||||
dropdownWrapper
|
||||
.find('.ant-dropdown-menu-submenu-title')
|
||||
.at(0)
|
||||
@ -367,6 +361,40 @@ describe('Table.filter', () => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
describe('should support value types', () => {
|
||||
[['Light', 93], ['Bamboo', false]].forEach(([text, value]) => {
|
||||
it(`${typeof value} type`, () => {
|
||||
const onFilter = jest.fn();
|
||||
const filters = [{ text, value }];
|
||||
const wrapper = mount(
|
||||
createTable({
|
||||
columns: [
|
||||
{
|
||||
...column,
|
||||
filters,
|
||||
onFilter,
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
jest.useFakeTimers();
|
||||
const dropdownWrapper = getDropdownWrapper(wrapper);
|
||||
dropdownWrapper
|
||||
.find('MenuItem')
|
||||
.first()
|
||||
.simulate('click');
|
||||
dropdownWrapper.find('.confirm').simulate('click');
|
||||
wrapper.update();
|
||||
|
||||
expect(onFilter.mock.calls.length > 0).toBeTruthy();
|
||||
onFilter.mock.calls.forEach(([val]) => {
|
||||
expect(val).toBe(value);
|
||||
});
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('works with JSX in controlled mode', () => {
|
||||
const { Column } = Table;
|
||||
|
||||
@ -397,12 +425,7 @@ describe('Table.filter', () => {
|
||||
}
|
||||
|
||||
const wrapper = mount(<App />);
|
||||
const dropdownWrapper = mount(
|
||||
wrapper
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
);
|
||||
const dropdownWrapper = getDropdownWrapper(wrapper);
|
||||
|
||||
dropdownWrapper
|
||||
.find('MenuItem')
|
||||
|
@ -182,20 +182,6 @@ describe('Table.pagination', () => {
|
||||
).toHaveLength(1);
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/14557
|
||||
it('Show correct page data when pagination data length is less than pageSize.', () => {
|
||||
const wrapper = mount(
|
||||
createTable({ pagination: { pageSize: 10, total: 100 }, dataSource: data }),
|
||||
);
|
||||
expect(renderedNames(wrapper)[0]).toEqual('Jack');
|
||||
wrapper.find('.ant-pagination-item-2').simulate('click');
|
||||
expect(renderedNames(wrapper)).toEqual([]);
|
||||
wrapper.setProps({ pagination: { current: 1, pageSize: 10, total: 100 } });
|
||||
expect(renderedNames(wrapper)[0]).toEqual('Jack');
|
||||
wrapper.setProps({ pagination: { current: 2, pageSize: 10, total: 100 } });
|
||||
expect(renderedNames(wrapper)).toHaveLength(4);
|
||||
});
|
||||
|
||||
/**
|
||||
* `pagination` is not designed to accept `true` value,
|
||||
* but in practice, many people assign `true` to `pagination`,
|
||||
@ -205,4 +191,24 @@ describe('Table.pagination', () => {
|
||||
const wrapper = render(createTable({ pagination: true }));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('ajax render should keep display by the dataSource', () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
createTable({
|
||||
onChange,
|
||||
pagination: {
|
||||
total: 200,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(wrapper.find('.ant-table-tbody tr.ant-table-row')).toHaveLength(data.length);
|
||||
|
||||
wrapper.find('.ant-pagination .ant-pagination-item-2').simulate('click');
|
||||
expect(onChange.mock.calls[0][0].current).toBe(2);
|
||||
|
||||
expect(wrapper.find('.ant-table-tbody tr.ant-table-row')).toHaveLength(data.length);
|
||||
});
|
||||
});
|
||||
|
@ -90,7 +90,7 @@ describe('Table', () => {
|
||||
it('warning if both `expandedRowRender` & `scroll` are used', () => {
|
||||
mount(<Table expandedRowRender={() => null} scroll={{}} />);
|
||||
expect(warnSpy).toBeCalledWith(
|
||||
'Warning: `expandedRowRender` and `scroll` are not compatible. Please use one of them at one time.',
|
||||
'Warning: [antd: Table] `expandedRowRender` and `scroll` are not compatible. Please use one of them at one time.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -1582,9 +1582,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1621,9 +1618,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1660,9 +1654,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1700,9 +1691,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1740,9 +1728,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1780,9 +1765,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1820,9 +1802,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1859,9 +1838,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1899,9 +1875,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1990,9 +1963,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</label>
|
||||
</div>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -2100,9 +2070,6 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</label>
|
||||
</div>
|
||||
</span>
|
||||
<div
|
||||
class="ant-form-explain-holder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -34,18 +34,6 @@ class EditableCell extends React.Component {
|
||||
editing: false,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.editable) {
|
||||
document.addEventListener('click', this.handleClickOutside, true);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.props.editable) {
|
||||
document.removeEventListener('click', this.handleClickOutside, true);
|
||||
}
|
||||
}
|
||||
|
||||
toggleEdit = () => {
|
||||
const editing = !this.state.editing;
|
||||
this.setState({ editing }, () => {
|
||||
@ -55,13 +43,6 @@ class EditableCell extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
handleClickOutside = (e) => {
|
||||
const { editing } = this.state;
|
||||
if (editing && this.cell !== e.target && !this.cell.contains(e.target)) {
|
||||
this.save();
|
||||
}
|
||||
}
|
||||
|
||||
save = () => {
|
||||
const { record, handleSave } = this.props;
|
||||
this.form.validateFields((error, values) => {
|
||||
@ -103,6 +84,7 @@ class EditableCell extends React.Component {
|
||||
<Input
|
||||
ref={node => (this.input = node)}
|
||||
onPressEnter={this.save}
|
||||
onBlur={this.save}
|
||||
/>
|
||||
)}
|
||||
</FormItem>
|
||||
|
@ -203,6 +203,9 @@ class EditableTable extends React.Component {
|
||||
dataSource={this.state.data}
|
||||
columns={columns}
|
||||
rowClassName="editable-row"
|
||||
pagination={{
|
||||
onChange: this.cancel,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import Menu, { SubMenu, Item as MenuItem } from 'rc-menu';
|
||||
import closest from 'dom-closest';
|
||||
import classNames from 'classnames';
|
||||
@ -10,6 +11,7 @@ import Checkbox from '../checkbox';
|
||||
import Radio from '../radio';
|
||||
import FilterDropdownMenuWrapper from './FilterDropdownMenuWrapper';
|
||||
import { FilterMenuProps, FilterMenuState, ColumnProps, ColumnFilterItem } from './interface';
|
||||
import { generateValueMaps } from './util';
|
||||
|
||||
function stopPropagation(e: React.SyntheticEvent<any>) {
|
||||
e.stopPropagation();
|
||||
@ -18,38 +20,18 @@ function stopPropagation(e: React.SyntheticEvent<any>) {
|
||||
}
|
||||
}
|
||||
|
||||
export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, FilterMenuState> {
|
||||
class FilterMenu<T> extends React.Component<FilterMenuProps<T>, FilterMenuState<T>> {
|
||||
static defaultProps = {
|
||||
handleFilter() {},
|
||||
column: {},
|
||||
};
|
||||
|
||||
neverShown: boolean;
|
||||
|
||||
constructor(props: FilterMenuProps<T>) {
|
||||
super(props);
|
||||
|
||||
const visible =
|
||||
'filterDropdownVisible' in props.column ? props.column.filterDropdownVisible : false;
|
||||
|
||||
this.state = {
|
||||
selectedKeys: props.selectedKeys,
|
||||
keyPathOfSelectedItem: {}, // 记录所有有选中子菜单的祖先菜单
|
||||
visible,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { column } = this.props;
|
||||
this.setNeverShown(column);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: FilterMenuProps<T>) {
|
||||
static getDerivedStateFromProps<T>(nextProps: FilterMenuProps<T>, prevState: FilterMenuState<T>) {
|
||||
const { column } = nextProps;
|
||||
this.setNeverShown(column);
|
||||
const newState = {} as {
|
||||
selectedKeys: string[];
|
||||
visible: boolean;
|
||||
const { prevProps } = prevState;
|
||||
|
||||
const newState: Partial<FilterMenuState<T>> = {
|
||||
prevProps: nextProps,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -61,16 +43,44 @@ export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, F
|
||||
*/
|
||||
if (
|
||||
'selectedKeys' in nextProps &&
|
||||
!shallowequal(this.props.selectedKeys, nextProps.selectedKeys)
|
||||
!shallowequal(prevProps.selectedKeys, nextProps.selectedKeys)
|
||||
) {
|
||||
newState.selectedKeys = nextProps.selectedKeys;
|
||||
}
|
||||
if (!shallowequal((prevProps.column || {}).filters, (nextProps.column || {}).filters)) {
|
||||
newState.valueKeys = generateValueMaps(nextProps.column.filters);
|
||||
}
|
||||
if ('filterDropdownVisible' in column) {
|
||||
newState.visible = column.filterDropdownVisible as boolean;
|
||||
}
|
||||
if (Object.keys(newState).length > 0) {
|
||||
this.setState(newState);
|
||||
}
|
||||
return newState;
|
||||
}
|
||||
|
||||
neverShown: boolean;
|
||||
|
||||
constructor(props: FilterMenuProps<T>) {
|
||||
super(props);
|
||||
|
||||
const visible =
|
||||
'filterDropdownVisible' in props.column ? props.column.filterDropdownVisible : false;
|
||||
|
||||
this.state = {
|
||||
selectedKeys: props.selectedKeys,
|
||||
valueKeys: generateValueMaps(props.column.filters),
|
||||
keyPathOfSelectedItem: {}, // 记录所有有选中子菜单的祖先菜单
|
||||
visible,
|
||||
prevProps: props,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { column } = this.props;
|
||||
this.setNeverShown(column);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { column } = this.props;
|
||||
this.setNeverShown(column);
|
||||
}
|
||||
|
||||
getDropdownVisible() {
|
||||
@ -128,10 +138,14 @@ export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, F
|
||||
};
|
||||
|
||||
confirmFilter() {
|
||||
const { selectedKeys } = this.state;
|
||||
const { selectedKeys, valueKeys } = this.state;
|
||||
const { filterDropdown } = this.props.column;
|
||||
|
||||
if (!shallowequal(selectedKeys, this.props.selectedKeys)) {
|
||||
this.props.confirmFilter(this.props.column, selectedKeys);
|
||||
this.props.confirmFilter(
|
||||
this.props.column,
|
||||
filterDropdown ? selectedKeys : selectedKeys.map(key => valueKeys[key]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,6 +241,7 @@ export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, F
|
||||
};
|
||||
|
||||
render() {
|
||||
const { selectedKeys: originSelectedKeys } = this.state;
|
||||
const { column, locale, prefixCls, dropdownPrefixCls, getPopupContainer } = this.props;
|
||||
// default multiple selection in filter dropdown
|
||||
const multiple = 'filterMultiple' in column ? column.filterMultiple : true;
|
||||
@ -238,7 +253,7 @@ export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, F
|
||||
filterDropdown = filterDropdown({
|
||||
prefixCls: `${dropdownPrefixCls}-custom`,
|
||||
setSelectedKeys: (selectedKeys: Array<any>) => this.setSelectedKeys({ selectedKeys }),
|
||||
selectedKeys: this.state.selectedKeys,
|
||||
selectedKeys: originSelectedKeys,
|
||||
confirm: this.handleConfirm,
|
||||
clearFilters: this.handleClearFilters,
|
||||
filters: column.filters,
|
||||
@ -259,7 +274,7 @@ export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, F
|
||||
className={dropdownMenuClass}
|
||||
onSelect={this.setSelectedKeys}
|
||||
onDeselect={this.setSelectedKeys}
|
||||
selectedKeys={this.state.selectedKeys}
|
||||
selectedKeys={originSelectedKeys && originSelectedKeys.map(val => val.toString())}
|
||||
getPopupContainer={(triggerNode: HTMLElement) => triggerNode.parentNode}
|
||||
>
|
||||
{this.renderMenus(column.filters!)}
|
||||
@ -290,3 +305,7 @@ export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, F
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
polyfill(FilterMenu);
|
||||
|
||||
export default FilterMenu;
|
||||
|
@ -243,10 +243,12 @@ export interface FilterMenuProps<T> {
|
||||
getPopupContainer?: GetPopupContainer;
|
||||
}
|
||||
|
||||
export interface FilterMenuState {
|
||||
export interface FilterMenuState<T> {
|
||||
selectedKeys: string[];
|
||||
valueKeys: { [name: string]: any };
|
||||
keyPathOfSelectedItem: { [key: string]: string };
|
||||
visible?: boolean;
|
||||
prevProps: FilterMenuProps<T>;
|
||||
}
|
||||
|
||||
export type PrepareParamsArgumentsReturn<T> = [
|
||||
|
@ -99,6 +99,8 @@
|
||||
&.@{table-prefix-cls}-column-has-actions {
|
||||
position: relative;
|
||||
background-clip: padding-box; // For Firefox background bug, https://github.com/ant-design/ant-design/issues/12628
|
||||
/* stylelint-disable-next-line */
|
||||
-webkit-background-clip: border-box; // For Chrome extra space: https://github.com/ant-design/ant-design/issues/14926
|
||||
|
||||
&.@{table-prefix-cls}-column-has-filters {
|
||||
.@{iconfont-css-prefix}-filter,
|
||||
@ -366,11 +368,11 @@
|
||||
}
|
||||
|
||||
.@{table-prefix-cls}-body > table {
|
||||
border-top: 0;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.@{table-prefix-cls}-header + .@{table-prefix-cls}-body > table,
|
||||
.@{table-prefix-cls}-body-inner > table {
|
||||
border-top: 0;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { ColumnFilterItem } from './interface';
|
||||
|
||||
export function flatArray(data: any[] = [], childrenName = 'children') {
|
||||
const result: any[] = [];
|
||||
@ -69,3 +70,11 @@ export function normalizeColumns(elements: React.ReactChildren) {
|
||||
});
|
||||
return columns;
|
||||
}
|
||||
|
||||
export function generateValueMaps(items?: ColumnFilterItem[], maps: { [name: string]: any } = {}) {
|
||||
(items || []).forEach(({ value, children }) => {
|
||||
maps[value.toString()] = value;
|
||||
generateValueMaps(children, maps);
|
||||
});
|
||||
return maps;
|
||||
}
|
||||
|
@ -110,7 +110,8 @@ export default class Tabs extends React.Component<TabsProps, any> {
|
||||
|
||||
warning(
|
||||
!(type.indexOf('card') >= 0 && (size === 'small' || size === 'large')),
|
||||
"Tabs[type=card|editable-card] doesn't have small or large size, it's by design.",
|
||||
'Tabs',
|
||||
"`type=card|editable-card` doesn't have small or large size, it's by design.",
|
||||
);
|
||||
const prefixCls = getPrefixCls('tabs', customizePrefixCls);
|
||||
const cls = classNames(className, {
|
||||
|
@ -30,7 +30,7 @@ describe('TimePicker', () => {
|
||||
it('allowEmpty deprecated', () => {
|
||||
mount(<TimePicker allowEmpty />);
|
||||
expect(errorSpy).toBeCalledWith(
|
||||
'Warning: `allowEmpty` in TimePicker is deprecated. Please use `allowClear` instead.',
|
||||
'Warning: [antd: TimePicker] `allowEmpty` is deprecated. Please use `allowClear` instead.',
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -99,7 +99,8 @@ class TimePicker extends React.Component<TimePickerProps, any> {
|
||||
|
||||
warning(
|
||||
!('allowEmpty' in props),
|
||||
'`allowEmpty` in TimePicker is deprecated. Please use `allowClear` instead.',
|
||||
'TimePicker',
|
||||
'`allowEmpty` is deprecated. Please use `allowClear` instead.',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -269,7 +269,7 @@ describe('Transfer', () => {
|
||||
).toEqual('old1');
|
||||
|
||||
expect(consoleErrorSpy).toBeCalledWith(
|
||||
'Warning: Transfer[notFoundContent] and Transfer[searchPlaceholder] will be removed, please use Transfer[locale] instead.',
|
||||
'Warning: [antd: Transfer] `notFoundContent` and `searchPlaceholder` will be removed, please use `locale` instead.',
|
||||
);
|
||||
consoleErrorSpy.mockRestore();
|
||||
});
|
||||
|
@ -83,7 +83,7 @@ describe('Search', () => {
|
||||
.simulate('change', { target: { value: 'a' } });
|
||||
|
||||
expect(errorSpy.mock.calls[0][0]).toMatch(
|
||||
'Warning: `onSearchChange` in Transfer is deprecated. Please use `onSearch` instead.',
|
||||
'Warning: [antd: Transfer] `onSearchChange` is deprecated. Please use `onSearch` instead.',
|
||||
);
|
||||
expect(onSearchChange.mock.calls[0][0]).toEqual('left');
|
||||
expect(onSearchChange.mock.calls[0][1].target.value).toEqual('a');
|
||||
|
@ -110,8 +110,9 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
|
||||
warning(
|
||||
!('notFoundContent' in props || 'searchPlaceholder' in props),
|
||||
'Transfer[notFoundContent] and Transfer[searchPlaceholder] will be removed, ' +
|
||||
'please use Transfer[locale] instead.',
|
||||
'Transfer',
|
||||
'`notFoundContent` and `searchPlaceholder` will be removed, ' +
|
||||
'please use `locale` instead.',
|
||||
);
|
||||
|
||||
const { selectedKeys = [], targetKeys = [] } = props;
|
||||
@ -277,7 +278,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
[`${direction}Filter`]: value,
|
||||
});
|
||||
if (onSearchChange) {
|
||||
warning(false, '`onSearchChange` in Transfer is deprecated. Please use `onSearch` instead.');
|
||||
warning(false, 'Transfer', '`onSearchChange` is deprecated. Please use `onSearch` instead.');
|
||||
onSearchChange(direction, e);
|
||||
}
|
||||
if (onSearch) {
|
||||
|
@ -29,6 +29,7 @@ export default class TreeSelect extends React.Component<TreeSelectProps, any> {
|
||||
|
||||
warning(
|
||||
props.multiple !== false || !props.treeCheckable,
|
||||
'TreeSelect',
|
||||
'`multiple` will alway be `true` when `treeCheckable` is true',
|
||||
);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import omit from 'omit.js';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { conductExpandParent, convertTreeToEntities } from 'rc-tree/lib/util';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
|
||||
import Tree, {
|
||||
TreeProps,
|
||||
@ -34,12 +35,23 @@ function getIcon(props: AntdTreeNodeAttribute): React.ReactNode {
|
||||
return <Icon type={expanded ? 'folder-open' : 'folder'} />;
|
||||
}
|
||||
|
||||
export default class DirectoryTree extends React.Component<DirectoryTreeProps, DirectoryTreeState> {
|
||||
class DirectoryTree extends React.Component<DirectoryTreeProps, DirectoryTreeState> {
|
||||
static defaultProps = {
|
||||
showIcon: true,
|
||||
expandAction: 'click',
|
||||
};
|
||||
|
||||
static getDerivedStateFromProps(nextProps: DirectoryTreeProps) {
|
||||
const newState: DirectoryTreeState = {};
|
||||
if ('expandedKeys' in nextProps) {
|
||||
newState.expandedKeys = nextProps.expandedKeys;
|
||||
}
|
||||
if ('selectedKeys' in nextProps) {
|
||||
newState.selectedKeys = nextProps.selectedKeys;
|
||||
}
|
||||
return newState;
|
||||
}
|
||||
|
||||
state: DirectoryTreeState;
|
||||
tree: Tree;
|
||||
onDebounceExpand: (event: React.MouseEvent<HTMLElement>, node: AntTreeNode) => void;
|
||||
@ -82,15 +94,6 @@ export default class DirectoryTree extends React.Component<DirectoryTreeProps, D
|
||||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: DirectoryTreeProps) {
|
||||
if ('expandedKeys' in nextProps) {
|
||||
this.setState({ expandedKeys: nextProps.expandedKeys });
|
||||
}
|
||||
if ('selectedKeys' in nextProps) {
|
||||
this.setState({ selectedKeys: nextProps.selectedKeys });
|
||||
}
|
||||
}
|
||||
|
||||
onExpand = (expandedKeys: string[], info: AntTreeNodeExpandedEvent) => {
|
||||
const { onExpand } = this.props;
|
||||
|
||||
@ -226,3 +229,7 @@ export default class DirectoryTree extends React.Component<DirectoryTreeProps, D
|
||||
return <ConfigConsumer>{this.renderDirectoryTree}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
|
||||
polyfill(DirectoryTree);
|
||||
|
||||
export default DirectoryTree;
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
@tree-prefix-cls: ~'@{ant-prefix}-tree';
|
||||
@tree-showline-icon-color: @text-color-secondary;
|
||||
@tree-node-padding: 4px;
|
||||
|
||||
.antCheckboxFn(@checkbox-prefix-cls: ~'@{ant-prefix}-tree-checkbox');
|
||||
|
||||
@ -23,7 +24,7 @@
|
||||
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 4px 0;
|
||||
padding: @tree-node-padding 0;
|
||||
white-space: nowrap;
|
||||
list-style: none;
|
||||
outline: 0;
|
||||
@ -177,6 +178,19 @@
|
||||
&-open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/14958
|
||||
> li {
|
||||
// Provide additional padding between top child node and parent node
|
||||
&:first-child {
|
||||
padding-top: 2 * @tree-node-padding;
|
||||
}
|
||||
|
||||
// Hide additional padding between last child node and next parent node
|
||||
&:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
li&-treenode-disabled {
|
||||
> span:not(.@{tree-prefix-cls}-switcher),
|
||||
|
@ -110,7 +110,8 @@ class Base extends React.Component<InternalBlockProps & ConfigConsumerProps, Bas
|
||||
|
||||
warning(
|
||||
!editable || typeof children === 'string',
|
||||
'When `editable` is enabled, the `children` of Text component should use string.',
|
||||
'Typography',
|
||||
'When `editable` is enabled, the `children` should use string.',
|
||||
);
|
||||
|
||||
return {};
|
||||
@ -286,7 +287,8 @@ class Base extends React.Component<InternalBlockProps & ConfigConsumerProps, Bas
|
||||
|
||||
warning(
|
||||
toArray(children).every((child: React.ReactNode) => typeof child === 'string'),
|
||||
'`ellipsis` for Typography should use string as children only.',
|
||||
'Typography',
|
||||
'`ellipsis` should use string as children only.',
|
||||
);
|
||||
|
||||
const { content, text, ellipsis } = measure(
|
||||
|
@ -9,7 +9,8 @@ interface TextProps extends BlockProps {
|
||||
const Text: React.SFC<TextProps> = ({ ellipsis, ...restProps }) => {
|
||||
warning(
|
||||
typeof ellipsis !== 'object',
|
||||
'`ellipsis` in Typography.Text is only support boolean value.',
|
||||
'Typography.Text',
|
||||
'`ellipsis` is only support boolean value.',
|
||||
);
|
||||
return <Base {...restProps} ellipsis={!!ellipsis} component="span" />;
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ class Upload extends React.Component<UploadProps, UploadState> {
|
||||
|
||||
progressTimer: any;
|
||||
|
||||
private upload: any;
|
||||
upload: any;
|
||||
|
||||
constructor(props: UploadProps) {
|
||||
super(props);
|
||||
|
@ -360,4 +360,14 @@ describe('Upload', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/14439
|
||||
it('should allow call abort function through upload instance', () => {
|
||||
const wrapper = mount(
|
||||
<Upload>
|
||||
<button type="button">upload</button>
|
||||
</Upload>,
|
||||
);
|
||||
expect(typeof wrapper.instance().upload.abort).toBe('function');
|
||||
});
|
||||
});
|
||||
|
@ -7,17 +7,14 @@ Here are the frequently asked questions about Ant Design and antd that you shoul
|
||||
|
||||
---
|
||||
|
||||
### Are you going to provide Vue(etc...) edition?
|
||||
|
||||
No, but [the LICENSE of ant-design](https://github.com/ant-design/ant-design/blob/master/LICENSE) is MIT. So, you can try to implement it with ant-design's [style](https://github.com/ant-design/ant-design/tree/master/style), like: [ant-design-vue](https://github.com/vueComponent/ant-design-vue) [vue-beauty](https://github.com/FE-Driver/vue-beauty) or [antue](https://github.com/zzuu666/antue).
|
||||
|
||||
### Are you going to provide Sass/Stylus(etc...) style file?
|
||||
|
||||
No, actually, you can convert Less to Sass/Stylus(etc...) with tools (which you can Google).
|
||||
|
||||
### `Select Dropdown DatePicker TimePicker Popover Popconfirm` disappear when I click another popup component inside it, How to resolve it?
|
||||
|
||||
Use `<Select getPopupContainer={trigger => trigger.parentNode}>` to render component inside Popover. (Or other getXxxxContainer props)
|
||||
This has been fixed since 3.11.x.
|
||||
If you're still using old version, you can use `<Select getPopupContainer={trigger => trigger.parentNode}>` to render component inside Popover. (Or other getXxxxContainer props)
|
||||
|
||||
https://ant.design/components/select/#Select-props
|
||||
|
||||
|
@ -7,17 +7,14 @@ title: FAQ
|
||||
|
||||
---
|
||||
|
||||
### 你们会提供 Vue 版本的 Ant Design 吗?
|
||||
|
||||
不,但是 [ant-design 基于 MIT 协议开源](https://github.com/ant-design/ant-design/blob/master/LICENSE),所以你可以尝试用 ant-design 的[样式](https://github.com/ant-design/ant-design/tree/master/style)去实现一套,例如:[ant-design-vue](https://github.com/vueComponent/ant-design-vue) [vue-beauty](https://github.com/FE-Driver/vue-beauty) 或者 [antue](https://github.com/zzuu666/antue)。
|
||||
|
||||
### 你们会提供 Sass/Stylus 等格式的样式文件吗?
|
||||
|
||||
不。事实上你可以使用工具(请自行 Google)将 Less 转换成 Sass/Stylus 等。
|
||||
|
||||
### 当我点击 `Select Dropdown DatePicker TimePicker Popover Popconfirm` 内的另一个 popup 组件时它会消失,如何解决?
|
||||
|
||||
使用 `<Select getPopupContainer={trigger => trigger.parentNode}>` 来在 Popover 中渲染组件,或者使用其他的 getXxxxContainer 参数。
|
||||
该问题在 3.11.0 后已经解决。
|
||||
如果你仍在使用旧版本,你可以通过 `<Select getPopupContainer={trigger => trigger.parentNode}>` 来在 Popover 中渲染组件,或者使用其他的 getXxxxContainer 参数。
|
||||
|
||||
https://ant.design/components/select/#Select-props
|
||||
|
||||
|
@ -51,7 +51,7 @@ You can subscribe to this feed for new version notifications: https://github.com
|
||||
**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 antd --save
|
||||
$ npm install antd
|
||||
```
|
||||
|
||||
```bash
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "antd",
|
||||
"version": "3.13.3",
|
||||
"version": "3.13.6",
|
||||
"title": "Ant Design",
|
||||
"description": "An enterprise-class UI design language and React-based implementation",
|
||||
"homepage": "http://ant.design/",
|
||||
@ -106,6 +106,7 @@
|
||||
"antd-theme-generator": "^1.1.4",
|
||||
"antd-tools": "^7.0.1",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-plugin-add-react-displayname": "^0.0.5",
|
||||
"bisheng": "^1.1.0",
|
||||
"bisheng-plugin-antd": "^1.0.0",
|
||||
"bisheng-plugin-description": "^0.1.4",
|
||||
@ -139,6 +140,8 @@
|
||||
"jsdom": "^13.0.0",
|
||||
"jsonml.js": "^0.1.0",
|
||||
"lint-staged": "^8.0.2",
|
||||
"logrocket": "^0.6.19",
|
||||
"logrocket-react": "^3.0.0",
|
||||
"lz-string": "^1.4.4",
|
||||
"majo": "^0.7.1",
|
||||
"mockdate": "^2.0.2",
|
||||
@ -177,7 +180,7 @@
|
||||
"rimraf": "^2.6.2",
|
||||
"scrollama": "^1.4.4",
|
||||
"stylelint": "~9.10.1",
|
||||
"stylelint-config-prettier": "^4.0.0",
|
||||
"stylelint-config-prettier": "^5.0.0",
|
||||
"stylelint-config-rational-order": "^0.0.4",
|
||||
"stylelint-config-standard": "^18.2.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "^1.1.0",
|
||||
|
@ -15,6 +15,8 @@ function alertBabelConfig(rules) {
|
||||
rule.options.plugins = rule.options.plugins.filter(
|
||||
plugin => !plugin.indexOf || plugin.indexOf('babel-plugin-add-module-exports') === -1,
|
||||
);
|
||||
// Add babel-plugin-add-react-displayname
|
||||
rule.options.plugins.push(require.resolve('babel-plugin-add-react-displayname'));
|
||||
} else if (rule.use) {
|
||||
alertBabelConfig(rule.use);
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ export const categories = {
|
||||
'radius-bottomleft',
|
||||
'radius-bottomright',
|
||||
'radius-upleft',
|
||||
'radius-upright',
|
||||
'fullscreen',
|
||||
'fullscreen-exit',
|
||||
],
|
||||
|
@ -5,6 +5,8 @@ import { enquireScreen } from 'enquire-js';
|
||||
import { addLocaleData, IntlProvider } from 'react-intl';
|
||||
import 'moment/locale/zh-cn';
|
||||
import { LocaleProvider } from 'antd';
|
||||
import LogRocket from 'logrocket';
|
||||
import setupLogRocketReact from 'logrocket-react';
|
||||
import zhCN from 'antd/lib/locale-provider/zh_CN';
|
||||
import Header from './Header';
|
||||
import enLocale from '../../en-US';
|
||||
@ -26,6 +28,20 @@ if (typeof window !== 'undefined') {
|
||||
window['react-dom'] = ReactDOM;
|
||||
window.antd = require('antd');
|
||||
/* eslint-enable global-require */
|
||||
|
||||
// Error log statistic
|
||||
window.addEventListener('error', function(e) {
|
||||
// Ignore ResizeObserver error
|
||||
if (e.message === 'ResizeObserver loop limit exceeded') {
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
}
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
LogRocket.init('kpuw4z/ant-design');
|
||||
setupLogRocketReact(LogRocket);
|
||||
}
|
||||
}
|
||||
|
||||
let isMobile = false;
|
||||
|
Loading…
Reference in New Issue
Block a user