mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-02 20:19:44 +08:00
fix: update merge
This commit is contained in:
commit
7dd0bd396d
4
.github/CODEOWNERS
vendored
Normal file
4
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
package.json @ant-design/ant-design-core
|
||||
.github/workflows/ @ant-design/ant-design-core
|
||||
scripts/ @ant-design/ant-design-core
|
||||
LICENSE @ant-design/ant-design-core
|
@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: analysis
|
||||
uses: actions-cool/issues-similarity-analysis@v1.1.0
|
||||
uses: actions-cool/issues-similarity-analysis@v1
|
||||
with:
|
||||
filter-threshold: 0.5
|
||||
title-excludes: ''
|
||||
|
2
.github/workflows/rebase.yml
vendored
2
.github/workflows/rebase.yml
vendored
@ -20,6 +20,6 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Automatic Rebase
|
||||
uses: cirrus-actions/rebase@1.5
|
||||
uses: cirrus-actions/rebase@1.6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
17
.github/workflows/ui-upload.yml
vendored
17
.github/workflows/ui-upload.yml
vendored
@ -1,6 +1,5 @@
|
||||
# Upload 📷 UI snapshots to argos server, help visual regression testing.
|
||||
|
||||
name: UI Upload
|
||||
name: 📷 UI Upload
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
@ -21,6 +20,9 @@ jobs:
|
||||
if: >
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Download commit artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
@ -47,8 +49,15 @@ jobs:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
workflow_conclusion: success
|
||||
name: snapshots
|
||||
path: imageSnapshots
|
||||
|
||||
- name: Install
|
||||
run: npm i fast-glob lodash argos-cli
|
||||
|
||||
- name: Upload argos-ci
|
||||
id: deploy
|
||||
run: |
|
||||
npx argos-cli upload ./ --token ${{ secrets.ARGOS_TOKEN }} --branch ${{ steps.branch.outputs.id }} --commit ${{ steps.commit.outputs.id }}
|
||||
run: npm run argos
|
||||
env:
|
||||
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
|
||||
ARGOS_GITHUB_BRANCH: ${{ steps.branch.outputs.id }}
|
||||
ARGOS_GITHUB_COMMIT: ${{ steps.commit.outputs.id }}
|
||||
|
11
.github/workflows/ui.yml
vendored
11
.github/workflows/ui.yml
vendored
@ -4,19 +4,14 @@ on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
# Cancel prev CI if new commit come
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
imagesnapshot:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
@ -28,6 +23,10 @@ jobs:
|
||||
path: package-temp-dir
|
||||
key: lock-${{ github.sha }}
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16'
|
||||
|
||||
- name: create package-lock.json
|
||||
run: npm i --package-lock-only --ignore-scripts
|
||||
|
||||
|
4
.github/workflows/verify-files-modify.yml
vendored
4
.github/workflows/verify-files-modify.yml
vendored
@ -20,8 +20,9 @@ jobs:
|
||||
forbid-files: 'CHANGELOG.zh-CN.md, CHANGELOG.en-US.md, LICENSE'
|
||||
skip-verify-authority: 'write'
|
||||
assignees: 'afc163, zombieJ, xrkffgg, MadCcc'
|
||||
comment-mark: 'version'
|
||||
comment: |
|
||||
Hi @${{ github.event.pull_request.user.login }}. Thanks for your contribution. The path `.github/` or `scripts/` and `CHANGELOG` `package.json` is only maintained by team members. This current PR will be closed and team members will help on this.
|
||||
Hi @${{ github.event.pull_request.user.login }}. Thanks for your contribution. The path `.github/` or `scripts/` and `CHANGELOG` is only maintained by team members. This current PR will be closed and team members will help on this.
|
||||
close: true
|
||||
set-failed: false
|
||||
|
||||
@ -30,6 +31,7 @@ jobs:
|
||||
with:
|
||||
forbid-files: 'components/style/themes/default.less'
|
||||
skip-verify-authority: 'admin'
|
||||
comment-mark: 'less'
|
||||
comment: |
|
||||
🚨 Hi @${{ github.event.pull_request.user.login }}. Thanks for your contribution, as the `default.less` file is currently being upgraded, changes are not recommended.
|
||||
|
||||
|
187
AUTHORS.txt
187
AUTHORS.txt
@ -1,6 +1,7 @@
|
||||
+v <ljw@live.jp>
|
||||
07akioni <07akioni2@gmail.com>
|
||||
17073025 <17073025@cnsuning.com>
|
||||
2724635499 <2724635499@qq.com>
|
||||
282159468 <282159468@qq.com>
|
||||
778758944 <778758944@qq.com>
|
||||
Aaron Cawte <aaron@bbncreative.co>
|
||||
@ -9,6 +10,7 @@ Adam Stankiewicz <sheerun@sher.pl>
|
||||
Aditya Padhi <aditya.padhi@outlook.com>
|
||||
Adrian Dimitrov <dimitrov.adrian@gmail.com>
|
||||
Adriano Ruberto <adriano.ruberto@gmail.com>
|
||||
Aex <adaex@qq.com>
|
||||
Ahmad Abdelaziz <ahmad.abdelaziz@robustastudio.com>
|
||||
Ahmed AlSammany <ahmed.alsammany@incorta.com>
|
||||
Ahmet Simsek <iamaroott@gmail.com>
|
||||
@ -38,13 +40,18 @@ Alexey Vinogradov <vinogradov.a.i.93@gmail.com>
|
||||
Alexey Yakovlev <yallie@yandex.ru>
|
||||
Alfred Qiu <sc941203@gmail.com>
|
||||
Ali Zhdanov <makedonec88@gmail.com>
|
||||
Aliaksandr <puskin1914@gmail.com>
|
||||
Alireza <alireza.mh@gmail.com>
|
||||
Alvin Abia <alvin.abia@icloud.com>
|
||||
Aminul Islam <me@aminul.net>
|
||||
Amir Arafat <amirarafat1@gmail.com>
|
||||
Amorites <751809522@qq.com>
|
||||
Amour1688 <lcz_1996@foxmail.com>
|
||||
Amumu <yoyo837@hotmail.com>
|
||||
Anas Tawfeek <anas.tawfeek@outlook.com>
|
||||
Andre Perunicic <andre@intoli.com>
|
||||
Andre Zyczkowski <andre@oakslab.com>
|
||||
Andrea Blanco <estefania_8_3@hotmail.com>
|
||||
Andrew Murray <radarhere@gmail.com>
|
||||
Andrew Shearer <andrew@ashearer.com>
|
||||
Andrey G <plandem@gmail.com>
|
||||
@ -52,6 +59,7 @@ Andrzej Dybionka <andrzej@arabel.la>
|
||||
André <mazoni.andre@gmail.com>
|
||||
Andrés <andresin87@gmail.com>
|
||||
Ankit Babbar <ankit.babbar@valuebound.com>
|
||||
Antee <gtavctt@protonmail.com>
|
||||
Aobo Yang <yangaobo@gmail.com>
|
||||
Ardo Kusuma <ardo@uber.com>
|
||||
Arlindo Torres <arlindofontetorres@gmail.com>
|
||||
@ -61,6 +69,7 @@ Artin <lengthmin@gmail.com>
|
||||
Arvin Xu <arvinx@foxmail.com>
|
||||
Ash Kumar <kumar.ashwin@outlook.com>
|
||||
Ashot Mnatsakanyan <mnatsakanyan.ashot@gmail.com>
|
||||
Austaras <austaras@outlook.com>
|
||||
Aymen Bouchekoua <bouchekoua.aymen@gmail.com>
|
||||
Aymen Chebbi <a.chebi@klarx.com>
|
||||
BK Heleth <bon.hoo@hotmail.com>
|
||||
@ -102,15 +111,20 @@ C.J. Winslow <whoaa512@gmail.com>
|
||||
CORP\lianyufeng <15275222711@163.com>
|
||||
Calin Vlad <vlad.s.calin@gmail.com>
|
||||
Cam Song <neosoyn@gmail.com>
|
||||
Camol <kwwnjujlc@sina.com>
|
||||
Cang Ta <hoksilato176@gmail.com>
|
||||
Canwen Xu <canwenxu@126.com>
|
||||
Carlos Coves Prieto <carlos.coves@interacso.com>
|
||||
Carter Feldman <carter@carter.at>
|
||||
Caspian Chen <624081567@qq.com>
|
||||
Cat-XHS <1349021570@qq.com>
|
||||
Catalin Miron <mironcatalin@gmail.com>
|
||||
Cee Cirno <i@cee.moe>
|
||||
Cemre Mengu <cemremengu@gmail.com>
|
||||
Chalk <chalkpe@gmail.com>
|
||||
Chandler Moisen <chandlermoisen@gmail.com>
|
||||
Chang Wang <cheapsteak@gmail.com>
|
||||
Chang Wei <867597730@qq.com>
|
||||
Charles Covey-Brandt <chazcb@gmail.com>
|
||||
Charlie Jonas <charlie@callawaycloudconsulting.com>
|
||||
Chelsea Huang <chelsea.huang@sap.com>
|
||||
@ -130,10 +144,12 @@ Chuang Yu <cyu9960@gmail.com>
|
||||
Chuck <wfhtzcf@gmail.com>
|
||||
Claudio Restifo <claudio.restifo@gmail.com>
|
||||
Cody Chan <int64ago@gmail.com>
|
||||
Cole <cqiufan@outlook.com>
|
||||
Colton Pierson <colton@coltonpierson.com>
|
||||
Confiks <confiks@scriptbase.org>
|
||||
Cong Yoo <roopher@163.com>
|
||||
Cong Zhang <dancerphil1994@gmail.com>
|
||||
Connor White <connor.bcw@gmail.com>
|
||||
Conway Anderson <hello@conwayanderson.com>
|
||||
Cordaro <elvis07@163.com>
|
||||
CornerSkyless <573196853@qq.com>
|
||||
@ -149,6 +165,7 @@ Daniel <caishujunchn@163.com>
|
||||
Daniel Chang <danielchang2022@u.northwestern.edu>
|
||||
Daniel Gomez <dgomez@orangeloops.com>
|
||||
Daniel Harrison <daniel.equiknox@gmail.com>
|
||||
Daniel Pfeffer <mail@danielpfeffer.de>
|
||||
Danny Hoower Antonio Viasus Avila <danjavia@gmail.com>
|
||||
Daphne Won <daphne.won@shopee.com>
|
||||
Daqi Song <dqaria@gmail.com>
|
||||
@ -161,13 +178,18 @@ David Broder-Rodgers <david.broder-rodgers@softwire.com>
|
||||
David Hatten <dhatten@covermymeds.com>
|
||||
David Schneider <davschne@gmail.com>
|
||||
Davide Bianchi <bianchidavide12@gmail.com>
|
||||
Dawnlck <chaokai.lck@antgroup.com>
|
||||
Dean van Niekerk <deanvniekerk@gmail.com>
|
||||
Debiancc <never.be.evil.debian@gmail.com>
|
||||
DengYun <tdzl2003@gmail.com>
|
||||
Denis <shumkovdenis@gmail.com>
|
||||
Dennis273 <dennisc695@icloud.com>
|
||||
Derrick <derricktel@foxmail.com>
|
||||
Di Wu <di@gridx.cn>
|
||||
DiamondYuan <admin@diamondyuan.com>
|
||||
DiamondYuan <541832074@qq.com>
|
||||
Diego Barreiro <diego.barreiro.perez@gmail.com>
|
||||
Diego Villacís <diegovillacis101@gmail.com>
|
||||
Dimitri Mitropoulos <dimitrimitropoulos@gmail.com>
|
||||
Dmitriy <dimusig@gmail.com>
|
||||
Dmitriy Mironov <dima.dev01@gmail.com>
|
||||
@ -178,9 +200,12 @@ Dmitry Manannikov <email@slonoed.net>
|
||||
Dmitry Snegirev <rikkitp@gmail.com>
|
||||
Dmitry Tikhomirov <tikhomirov@element-soft.com>
|
||||
Dongcheng Wang <dongcheng6@qq.com>
|
||||
Dony Sukardi <donysukardi@gmail.com>
|
||||
Dorian <dorian@doma.io>
|
||||
DosLin <doslino@gmail.com>
|
||||
Douglas Mason <Demasonjr@gmail.com>
|
||||
Dreamcreative <m543438924@163.com>
|
||||
Dzmitry Yarmoshkin <spanb4@gmail.com>
|
||||
Eager <1226393396@qq.com>
|
||||
Eber Rodrigues <eberjoe@gmail.com>
|
||||
EcmaProSrc.P/ka <asoiso@foxmail.com>
|
||||
@ -193,14 +218,18 @@ Eduardo Ludi <eduludi@gmail.com>
|
||||
Edward <7047924@qq.com>
|
||||
Egor Yurtaev <yurtaev.egor@gmail.com>
|
||||
Elaina Cherudim <shr9192@gmail.com>
|
||||
Eldar Mirzabekov <prog.eldar@gmail.com>
|
||||
Eldar Mustafaiev <eldar.mustafaiev@gmail.com>
|
||||
Eli White <github@eli-white.com>
|
||||
Eliot Sanford <eliot587@gmail.com>
|
||||
Emerson Laurentino <emersonlaurentino@hotmail.com>
|
||||
Emily Xiong <xiongemi@gmail.com>
|
||||
Ender Lee <chnliquan@163.com>
|
||||
Eric <84263800@qq.com>
|
||||
Eric Bonow <ebonow@hotmail.com>
|
||||
Eric Celeste <efc@clst.org>
|
||||
Eric Chen <airkro@qq.com>
|
||||
Eric Lee <ericfly33@gmail.com>
|
||||
Eric Turriff <eric.turriff@gmail.com>
|
||||
Eric Wang <eric@canva.com>
|
||||
Eric Wang <wjun0912@gmail.com>
|
||||
@ -210,36 +239,50 @@ Eugene Matvejev <eugene.matvejev@gmail.com>
|
||||
Eugene Molokov <molokovev@gmail.com>
|
||||
Eusen <179530591@qq.com>
|
||||
Evan Charlton <evancharlton@gmail.com>
|
||||
EvanOne(文一) <1656081615@qq.com>
|
||||
Evgeny Kuznetsov <jackk@ya.ru>
|
||||
Eward Song <eward.song@gmail.com>
|
||||
FJHou <firemybugs@gmail.com>
|
||||
Fachreza Muslim <fachreza.muslim7396@gmail.com>
|
||||
Federico Marcos <marcosfede@gmail.com>
|
||||
Ferdi Koomen <info@madebyferdi.com>
|
||||
Fergus Leung <fergusleung96@gmail.com>
|
||||
Fernando Giarritiello <fgiarritiello@gmail.com>
|
||||
Filip Kukovec <filip.kukovec1@gmail.com>
|
||||
Filip Seman <filip.seman@protonmail.com>
|
||||
Florian Orpelière <florian.orpeliere@gmail.com>
|
||||
Flynn <li.fulin@foxmail.com>
|
||||
Fog3211 <fog3211@163.com>
|
||||
For177 <mengqiang.q@gmail.com>
|
||||
Frank <frankdingv@gmail.com>
|
||||
Frank Fang <FrankFang1990@gmail.com>
|
||||
Frezc <Frezcw@gmail.com>
|
||||
Fullstop000 <fullstop1005@gmail.com>
|
||||
GJ Wang <itellboy@foxmail.com>
|
||||
GSBL <2602140596@qq.com>
|
||||
Gabe Medrash <gabeme@alleninstitute.org>
|
||||
Gabriel Henrique <bielrockx@gmail.com>
|
||||
Gabriel Le Breton <lebreton.gabriel@gmail.com>
|
||||
Gabriel Mendez Reyes <gabriel.mendez0@hotmail.com>
|
||||
Gabriel Nunes <gabriel@multiverso.me>
|
||||
GalenWong <wonggalen1999@gmail.com>
|
||||
GannonSun <GannonSun@gmail.com>
|
||||
Gao Jiangmiao <tolbkni@gmail.com>
|
||||
Garrick Crouch <garrickcrouch@gmail.com>
|
||||
Gautier <rollingautier2@gmail.com>
|
||||
Geoff Holden <geoff@brightloudnoise.com>
|
||||
Geoffrey Bell <gtb104@yahoo.com>
|
||||
George Gray <george@ummodesign.com>
|
||||
Germini <634709523@qq.com>
|
||||
Gerson Garrido <ggarridom23@gmail.com>
|
||||
Gherciu Gheorghe <gherciu553@gmail.com>
|
||||
Gianmarco Rengucci <rengucci.gianmarco@gmail.com>
|
||||
Gin-X <xcbwyys@hotmail.com>
|
||||
Go7hic <gtfx0209@qq.com>
|
||||
Goh Zhao Yang <austinzy@airasia.com>
|
||||
Golevka <huangsamfisher@163.com>
|
||||
Googleplex <yyoung2001@gmail.com>
|
||||
Gourav Saini <mailtogouravsaini@gmail.com>
|
||||
Graeme Yeates <yeatesgraeme@gmail.com>
|
||||
Graeme Yeates <gyeates@clearpath.ai>
|
||||
Grant Klinsing <gklinsing@gmail.com>
|
||||
@ -247,10 +290,14 @@ Gray Choi <gray.choi.1988@gmail.com>
|
||||
Guan Hao <raptium@gmail.com>
|
||||
Guan Yu Pan (Jacky) <jackypan1989@gmail.com>
|
||||
Guichi Zhao <zgc910619@gmail.com>
|
||||
Guojun Wang <itwanggj@163.com>
|
||||
Guru Mahendran <me@gurubavan.com>
|
||||
HJin.me <hjin.me@gmail.com>
|
||||
Hai Phan Nguyen <pnghai@gmail.com>
|
||||
Haibin Yu <haibin.yu@oceanwing.com>
|
||||
Hal-pan <hms181231@gmail.com>
|
||||
Hale Deng <haledeng88@gmail.com>
|
||||
Han Han <haannn@qq.com>
|
||||
Hanai <ihanai1991@gmail.com>
|
||||
Hanjun Kim <hallazzang@gmail.com>
|
||||
Hanz Luo <lhz0516@gmail.com>
|
||||
@ -262,6 +309,7 @@ Harshit Mehrotra <harshitmehrotra@hotmail.com>
|
||||
Harutaka Kawamura <hkawamura0130@gmail.com>
|
||||
He Linming <hlm52pk@163.com>
|
||||
Heaven <ne_smalltown@163.com>
|
||||
Hell Cat <hellcatvn@gmail.com>
|
||||
Henri Normak <henri.normak@gmail.com>
|
||||
HeskeyBaozi <hezhiyu233@foxmail.com>
|
||||
HiddenMan <1196089730@qq.com>
|
||||
@ -282,6 +330,7 @@ ILdar Nogmanov <nogmanov@gmail.com>
|
||||
Igor <nemytyshew@yandex.ru>
|
||||
Igor Andriushchenko <igor.andriushchenko@snowsoftware.com>
|
||||
Igor G <i.gaidai4uk@gmail.com>
|
||||
Ikko Ashimine <eltociear@gmail.com>
|
||||
Ilan <hasanovtk@gmail.com>
|
||||
Ilya Bondarenko <bondarenko.ik@gmail.com>
|
||||
ImJoeHs <865439601@qq.com>
|
||||
@ -297,6 +346,7 @@ Ivan Tsybulin <vanyatsybulin@gmail.com>
|
||||
Ivan Yakovlev <addictional2013@gmail.com>
|
||||
Ivo Stratev <ivo.stratev.tues@gmail.com>
|
||||
JRoger <sjr_vip@126.com>
|
||||
Jabir K.H <khjabir@gmail.com>
|
||||
Jack <jacklee82814@gmail.com>
|
||||
Jack Hsieh <jack@egenware.com>
|
||||
Jack Lo <jack-lo@foxmail.com>
|
||||
@ -305,21 +355,27 @@ Jackie.Ls <418292038@qq.com>
|
||||
Jacques Kvam <jwkvam@gmail.com>
|
||||
JaePil Jung <jjp5023@gmail.com>
|
||||
Jaewook Ahn <ajw4586@gmail.com>
|
||||
Jaimy de Graaf <me@vfour.dev>
|
||||
Jake Richards <jake.richards@genesys.com>
|
||||
Jaly <dcdlove@qq.com>
|
||||
James <daoxingyue@live.cn>
|
||||
James <james@schoolshape.com>
|
||||
James Tsang <wentao_zeng1@163.com>
|
||||
James Yeung <shunjiey@hotmail.com>
|
||||
JamesYin <elantion@gmail.com>
|
||||
Jan Václavík <jvaclavik@gmail.com>
|
||||
Janry <wangzhili56@126.com>
|
||||
Jaroslav Bereza <github.com@bereza.cz>
|
||||
Jarret Moses <jarret.moses@gmail.com>
|
||||
Jarvis1010 <travis.mair@gmail.com>
|
||||
Jase Owens <jaseowens197@gmail.com>
|
||||
Jase Pellerin <jasepellerin@gmail.com>
|
||||
Jason <ceocjy@vip.qq.com>
|
||||
Jason Chung <shiningjason1989@gmail.com>
|
||||
Jason Yin <yinjiangsheng@gmail.com>
|
||||
Jay Fong <fjc0kb@gmail.com>
|
||||
Jean-Luc Sorak <jlsorak@icloud.com>
|
||||
Jean-Philippe Roy <ohnoesmyoreos@gmail.com>
|
||||
Jeff Wen <sinchangwen@gmail.com>
|
||||
Jeffrey Carl Faden <jeffreyatw@gmail.com>
|
||||
Jehu <z_zhihao@foxmail.com>
|
||||
@ -332,9 +388,11 @@ Jesper We <jesper@journeyman.se>
|
||||
Jesus The Hun <iletaitunefoisfenghuang@gmail.com>
|
||||
Jiabin Peng <png.inside@gmail.com>
|
||||
Jiahao <jahowchen@outlook.com>
|
||||
Jiajun Chen <tychenjiajun@live.cn>
|
||||
Jialei <jialeicui@126.com>
|
||||
Jiawei Huang <hjiawei@gmail.com>
|
||||
Jichao Zhong <felixjichao@gmail.com>
|
||||
Jiehui <jeffylaiakanull@gmail.com>
|
||||
Jieraaa <842533841@qq.com>
|
||||
Jin ZHANG <jz.zhangjin@gmail.com>
|
||||
JinXin <m18508218948@163.com>
|
||||
@ -350,6 +408,8 @@ Joe <qiaolibo@126.com>
|
||||
Joe Hsu <jhsu.x1@gmail.com>
|
||||
Johannes Andersen <johannes.andersen@signifyd.com>
|
||||
Johannes Loewe <johannes@loewe.pm>
|
||||
John <John60676@qq.com>
|
||||
John Carlo <johncarloaustria@pm.me>
|
||||
John Johnson III <john@johnjohnson.cc>
|
||||
John Nguyen <jtnguyen236@gmail.com>
|
||||
Johnny Lim <izeye@naver.com>
|
||||
@ -360,21 +420,29 @@ Jonathan Lee <1150974628@qq.com>
|
||||
Jonny Buchanan <jonathan.buchanan@gmail.com>
|
||||
Joo Wu <wuchu356@gmail.com>
|
||||
Jordan Hornblow <jordan@jch254.com>
|
||||
Joshua Chen <sidachen2003@gmail.com>
|
||||
Josue Peralta <jperal77@gmail.com>
|
||||
Josué <ujosuegt@outlook.com>
|
||||
JounQin <admin@1stg.me>
|
||||
JribiBelhassen <belha9inzaghi@gmail.com>
|
||||
Jtree03 <wowns0903@gmail.com>
|
||||
JuFeng Zhang <zjffun@gmail.com>
|
||||
Juan Carlos Lloret H <juan.carlos.lloret@lansweeper.com>
|
||||
Juan Rodrigo Venegas Boesch <jrvboesch@gmail.com>
|
||||
Julia Passynkova <ipassynk@hotmail.com>
|
||||
Julien Confetti <julien.confetti@ulg.ac.be>
|
||||
Jun Wooram <chatoo2412@gmail.com>
|
||||
JuniorTour <juniortour@qq.com>
|
||||
Junwoo Ji <jydrogen@gmail.com>
|
||||
Junyu Zhan <irrigator@yeah.net>
|
||||
Juraj Carnogursky <durisvk2@gmail.com>
|
||||
Justin Reich <reich.justin@gmail.com>
|
||||
Justin Schuldt <justinschuldt@gmail.com>
|
||||
Jógvan Olsen <jogvanolsen@hotmail.com>
|
||||
Kaan KÜÇÜK <kaankck@gmail.com>
|
||||
Kaien Liao <liaokaien@gmail.com>
|
||||
Kamal Mahmudi <kamalmahmudi@yahoo.co.id>
|
||||
Karott Schu <karott7@gmail.com>
|
||||
Kasra Bigdeli <kasra85@gmail.com>
|
||||
Kayson Wu <772663139@qq.com>
|
||||
Kelvin Chu <chubillkelvin@gmail.com>
|
||||
@ -421,6 +489,7 @@ LeoYang <LeoY.Dev@gmail.com>
|
||||
Leon Koole <leon@koole.io>
|
||||
Leon Shi <superRaytin@163.com>
|
||||
Leon Shi <superRaytin@gmail.com>
|
||||
Lewis <lewisfidlers@gmail.com>
|
||||
Li C. Pan <18306423262@163.com>
|
||||
Li Chao <rftstars@qq.com>
|
||||
Li Ming <armyiljfe@gmail.com>
|
||||
@ -428,18 +497,25 @@ LiPinghai <twopoles@163.com>
|
||||
LilyWakana <873435892@qq.com>
|
||||
Liming Jin <jinliming2@gmail.com>
|
||||
Liming Jin <jinlm@knownsec.com>
|
||||
Liron Lavy <liron.lavy@gmail.com>
|
||||
Liu Bowen <Mr_lbw@outlook.com>
|
||||
Liu Ya <liuya54892@gmail.com>
|
||||
Liu Yang <zation1@gmail.com>
|
||||
LongYinan <lynweklm@gmail.com>
|
||||
Loogeek <340017792@qq.com>
|
||||
Loïc Huvé <loic.huve@protonmail.com>
|
||||
Lu Yu <brantscube@hotmail.com>
|
||||
Lucien Lee <lkiral7903@gmail.com>
|
||||
Ludwig Bäcklund <ludli839@student.liu.se>
|
||||
Luke Vella <me@lukevella.com>
|
||||
Lyndon001 <lld207@126.com>
|
||||
M Mitchell <mail@megmitchell.ca>
|
||||
M. Burak Kalkan <mburakkalkan@gmail.com>
|
||||
MD. Ariful Alam <swazan.arif@gmail.com>
|
||||
MG12 <wuzhao.mail@gmail.com>
|
||||
Ma Tianxiao <matx2215@outlook.com>
|
||||
Maciej Czekaj <natanielcz@gmail.com>
|
||||
MadCcc <1075746765@qq.com>
|
||||
Madis Väin <madisvain@gmail.com>
|
||||
Maksim Nesterenko <alendorff@gmail.com>
|
||||
Maksim Slotvinskij <m.slotvinskij@gmail.com>
|
||||
@ -449,6 +525,7 @@ Manjit Kumar <manjit1727@gmail.com>
|
||||
Manoj Kumar <manoj.150283@gmail.com>
|
||||
Manweill <mic.liangwenwei@foxmail.com>
|
||||
MaoYiWei <137308365@qq.com>
|
||||
Map1en_ <maplenagisa@gmail.com>
|
||||
Marcel Jackwerth <marceljackwerth@gmail.com>
|
||||
Marcela Bomfim <mbomfim@live.com>
|
||||
Marcio Pamplona <marciopamplona79@gmail.com>
|
||||
@ -469,6 +546,7 @@ Matt Lein <matt.lein@code42.com>
|
||||
Matt Wilkinson <mattwilki17@gmail.com>
|
||||
Max <maksym.mosyura@kruschecompany.com>
|
||||
Maximilian Meyer <Maximilian.Meyer@br.de>
|
||||
Md_ZubairAhmed <m-zubairahmed@protonmail.com>
|
||||
MeiLin <postget.me@gmail.com>
|
||||
MengZhaoFly <1424254461@qq.com>
|
||||
Meow-z <372086270@qq.com>
|
||||
@ -476,6 +554,7 @@ Meowu <474384902@qq.com>
|
||||
Miaow <i@zfeng.net>
|
||||
Micah Guttman <memtech3@gmail.com>
|
||||
Michael Adams <mtadams007@gmail.com>
|
||||
Michael Crenshaw <michael@crenshaw.dev>
|
||||
Michael Krog <mic@apaq.dk>
|
||||
Michael Salaverry <michaels@axonize.com>
|
||||
Michael Salaverry <barakplasma@gmail.com>
|
||||
@ -493,6 +572,7 @@ Min <dicklwm@163.com>
|
||||
MinJeong Kim <min7859@gmail.com>
|
||||
MinYuan <s1124yy@gmail.com>
|
||||
Ming Hann <eldy8888@gmail.com>
|
||||
Minh Quy <sugiacupit@gmail.com>
|
||||
Minqi Pan <pmq2001@gmail.com>
|
||||
Minsung Ryu <ryums0227@gmail.com>
|
||||
Minwei Xu <faceswilliam@gmail.com>
|
||||
@ -501,11 +581,14 @@ Misha Kav <misha.kav@gmail.com>
|
||||
Mitchell Demler <mitchell.demler@harcourts.net>
|
||||
Moein Alizadeh <truemoein@gmail.com>
|
||||
Mohamed Seada <mohamed.seada.1994@gmail.com>
|
||||
Mohammad Anas <mohammad.anas190@gmail.com>
|
||||
Mohammad Arsalan <a4arshi@yahoo.com>
|
||||
Mohammad Faisal <faisalhmohd@gmail.com>
|
||||
Mohan Ban <banmohan@outlook.com>
|
||||
Mohelm97 <mohelm97@gmail.com>
|
||||
Mongkii <mongkii@hotmail.com>
|
||||
Moni <usmoni@gmail.com>
|
||||
Monty <montyma1207@163.com>
|
||||
Mounish Sai <pvsmounish@gmail.com>
|
||||
Mr.Biscuit <sunshuaiqi@gmail.com>
|
||||
Mr.Tone <vector@malubei.com>
|
||||
@ -523,12 +606,15 @@ Nathan Wells <nwwells@gmail.com>
|
||||
Naveen <mailtomassnaveen@gmail.com>
|
||||
Neekey <ni184775761@gmail.com>
|
||||
Nekron <nekron.hyt@gmail.com>
|
||||
Neo Tan <neotan12@hotmail.com>
|
||||
Neto Braghetto <netow93@gmail.com>
|
||||
Neverland <chenjiahan@buaa.edu.cn>
|
||||
Nico <nicolas@freddelacompta.com>
|
||||
Nidhi Agarwal <nidhi.agarwal@zomato.com>
|
||||
Nihal Saxena <saxenanihal95@gmail.com>
|
||||
Nikesh <nikesh.ramnani@gmail.com>
|
||||
Nikita Bystrov <arttsesoft@gmail.com>
|
||||
Nikita Marinosyan <nikita.marinosyan@gmail.com>
|
||||
Nikitenkova <katrin_7nes7@mail.ru>
|
||||
Niko Autio <niko.autio@fenten.fi>
|
||||
Nikolay <veseliy07@gmail.com>
|
||||
@ -551,6 +637,8 @@ Oren Kosto <orenkosto86@gmail.com>
|
||||
Oren Kosto <oren@panda-os.com>
|
||||
Orkhan Huseynli <orkhan.huseyn@outlook.com>
|
||||
OuYancey <ou.yancey@gmail.com>
|
||||
PCCCCCCC <zpc.excel@foxmail.com>
|
||||
Pablo Recalde <me@pablorecalde.com>
|
||||
Panjie Setiawan Wicaksono <panjie@panjiesw.com>
|
||||
Patrick Gidich <patrick.gidich@simnova.com>
|
||||
Patryk <longer44@gmail.com>
|
||||
@ -564,12 +652,16 @@ Peter Berg <atticusberg@gmail.com>
|
||||
Phanupong Janthapoon <panupong.jtp@gmail.com>
|
||||
Philip Oliver <philipodev@gmail.com>
|
||||
Phyllis <escapiststupor@gmail.com>
|
||||
Picsong <312465087@qq.com>
|
||||
Pierre <pierre@bazoge.com>
|
||||
Pierre Neter <pierreneter@gmail.com>
|
||||
Piotr Monwid-Olechnowicz <hasparus@gmail.com>
|
||||
Piper Chester <piperchester@gmail.com>
|
||||
Pixy Yuan <pixy.bupt@gmail.com>
|
||||
PlayerWho <who.zhuang@gmail.com>
|
||||
Pob Ch <590650@gmail.com>
|
||||
Pooya Parsa <pyapar@gmail.com>
|
||||
Primlx <primulax@live.com>
|
||||
Pubudu Kodikara <pubudu@leafycode.com>
|
||||
Pyiner <lijiuyang1992@gmail.com>
|
||||
Pyroboomka <qwaarty@mail.ru>
|
||||
@ -597,6 +689,7 @@ Regan Langford <regan.reihana@gmail.com>
|
||||
Renny Ren <rennyallen@hotmail.com>
|
||||
Renovate Bot <bot@renovateapp.com>
|
||||
Rex <zhangzilong.zzl@163.com>
|
||||
Ricardo Morais <moraispgsi@gmail.com>
|
||||
Ricardo Raphael Joson <rrjoson08@gmail.com>
|
||||
Richard D. Worth <rdworth@gmail.com>
|
||||
Rick Zhou <rinick@gmail.com>
|
||||
@ -608,6 +701,7 @@ Rohan Malhotra <rohan.root@gmail.com>
|
||||
Rongjian Zhang <pd4d10@gmail.com>
|
||||
Rrrandom <emanonhere@gmail.com>
|
||||
RunningCoderLee <sprint_l@aliyun.com>
|
||||
Ryan Lee <yigexbl@gmail.com>
|
||||
RyanHui <ryanhui1996@gmail.com>
|
||||
Régis Foucault <regisfoucault@gmail.com>
|
||||
SHEN Lin <shenlin192@gmail.com>
|
||||
@ -622,6 +716,7 @@ Sam Lanning <sam@samlanning.com>
|
||||
Sam Marks <sam@sammarks.me>
|
||||
Sam Maxwell <sam@paybase.io>
|
||||
Samed Düzçay <samedduzcay@gmail.com>
|
||||
Sami Mäkinen <zakarfin@gmail.com>
|
||||
Samuel Gaus <sam@gaus.co.uk>
|
||||
Sanghyeon Lee <yongdamsh@gmail.com>
|
||||
Sangle <whb97@163.com>
|
||||
@ -632,14 +727,18 @@ Scott Goci <scottjg@gmail.com>
|
||||
Scott Sturgeon <scott@tugboatlogic.com>
|
||||
Sean Lin <sean@ejoy.com>
|
||||
Sean Willis <sean.willis@incorta.com>
|
||||
Seba Kerckhof <seba.kerckhof@gmail.com>
|
||||
Sebastian Blade <blade254353074@hotmail.com>
|
||||
Sebastian Busch <s.busch@obg-gruppe.de>
|
||||
Sebastian Busch <mail@sebastian-bus.ch>
|
||||
Sebastian Busch <s.busch@qbus-enet.de>
|
||||
Sepush <sepush@outlook.com>
|
||||
Sergey Kachanovskiy <sergey.kachanovskiy@gmx.de>
|
||||
Sergey Levkovich <gosu.87@mail.ru>
|
||||
Sergey Volynkin <sergey.volynkin@akvelon.com>
|
||||
Sergio Crisostomo <sergiosbox@gmail.com>
|
||||
Sevak <shaderzak@gmail.com>
|
||||
Shanjie Chen <cnzxcsj@outlook.com>
|
||||
Shawn Sit <xueqingxiao@gmail.com>
|
||||
Shengnan <baxtergu@gmail.com>
|
||||
ShiTengFei <shitengfei@goyoo.com>
|
||||
@ -656,35 +755,46 @@ Sivaraj <contact@sdev.in>
|
||||
SkyAo <csvwolf@qq.com>
|
||||
Skylar艺璇 <mengxue.yx@gmail.com>
|
||||
Snyk bot <github+bot@snyk.io>
|
||||
Songhn <songhn233@gmail.com>
|
||||
Sonjeet Paul <sonjeetcp.98@gmail.com>
|
||||
SoraYama <sorayamahou@gmail.com>
|
||||
Spencer <spjy@hawaii.edu>
|
||||
Stanley Thijssen <stanley.thijssen@energybox.com>
|
||||
Stanley Thijssen <stanley.thijssen@gmail.com>
|
||||
Stef Schenkelaars <stef.schenkelaars@gmail.com>
|
||||
Stephen Esser <Stephen.Esser@gmail.com>
|
||||
Stevche Radevski <sradevski@live.com>
|
||||
Steven.zhong <953665604@qq.com>
|
||||
Subroto <shub1493biswas@gmail.com>
|
||||
Suki小火车 <463355954@qq.com>
|
||||
Sumit Vekariya <sumitvekariya7@gmail.com>
|
||||
Sunny Luo <sunnylqm@gmail.com>
|
||||
Sven Efftinge <sven.efftinge@typefox.io>
|
||||
SyMind <dacongsama@live.com>
|
||||
SylvanasGone <397009765@qq.com>
|
||||
TTC <345866517@qq.com>
|
||||
Tanmoy Bhowmik <tanmoy.openroot@gmail.com>
|
||||
Tannmay S Gupta <tanmaygup123@gmail.com>
|
||||
Tao <magicdawn@qq.com>
|
||||
Tao Zhang <windse7en@gmail.com>
|
||||
Taucher Christoph <taucher.ch@gmail.com>
|
||||
Taylor Sabell <taylorsabell@gmail.com>
|
||||
Ted Shin <ted.m.shin@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>
|
||||
Themi Tsiotas von Pfaler <themi1234@gmail.com>
|
||||
Theo Satloff <1golfball@gmail.com>
|
||||
Thibault Derousseaux <tde@activeviam.com>
|
||||
Thiebaud Thomas <thiebaud.tom@gmail.com>
|
||||
Thomas <tom@axisj.com>
|
||||
Thomas Ladd <thomas.ladd@stackpath.com>
|
||||
Thomas Zipner <thomas.zipner@gmail.com>
|
||||
Tianyuan Zhang <tianyuan233.zhang@gmail.com>
|
||||
Tino D <ginodeis@gmail.com>
|
||||
Tmk <i@tmk.im>
|
||||
Tom Gao <tom@zoomsoft.cc>
|
||||
Tom Xu <ycxzhkx@gmail.com>
|
||||
Tom Xu <tom.xu@antcosa.com>
|
||||
@ -699,10 +809,12 @@ TsesamLi <tsesamli17@gmail.com>
|
||||
Ty Mick <ty@tymick.me>
|
||||
Tyler <chaotyler@gmail.com>
|
||||
Ubaldo Quintana <blkdr@hotmail.com>
|
||||
Uladzimir Atroshchanka <Uladzimir.Atroshchanka@vertexinc.com>
|
||||
Vadim Macagon <vadim.macagon@gmail.com>
|
||||
Valentin Vichnal <valentin@vichnal.com>
|
||||
Van Nguyen <vnguyen94@gmail.com>
|
||||
Varun Dey <varundey20@gmail.com>
|
||||
Varun Sharma <varunsh@stepsecurity.io>
|
||||
Vemund Santi <vemund@santi.no>
|
||||
Vic <709147950@qq.com>
|
||||
Victor <saptefrativictor@gmail.com>
|
||||
@ -714,6 +826,7 @@ Viorel Cojocaru <vio@beanon.com>
|
||||
Vitaliy Mazurenko <vitaliymazurenko@gmail.com>
|
||||
Vitaly Budovski <vbudovski@gmail.com>
|
||||
ViviaRui <zr1450995198@163.com>
|
||||
Vlad Vovk <wolfykey@gmail.com>
|
||||
Vu Hoang Minh <vuhminh@gmail.com>
|
||||
Vyacheslav Kamenev <vy.kamenev@gmail.com>
|
||||
Walter Barbagallo <brb.walter@gmail.com>
|
||||
@ -725,7 +838,9 @@ Wang yb <wangyibu123@gmail.com>
|
||||
Warren Seymour <warren@fountainhead.tech>
|
||||
Webber Takken <webber@takken.io>
|
||||
Wei Zhu <yesmeck@gmail.com>
|
||||
WeijieChen <cwjTerrace@163.com>
|
||||
Wenchao Hu <zjuhwc@gmail.com>
|
||||
Wendell <wendellhu95@outlook.com>
|
||||
Wendell <wendzhue@gmail.com>
|
||||
Wenqi Chen <1264578441@qq.com>
|
||||
Wensheng Xu <xws@superid.cn>
|
||||
@ -737,6 +852,7 @@ William Stein <wstein@gmail.com>
|
||||
WingGao <wing.gao@live.com>
|
||||
Wu Haotian <whtsky@gmail.com>
|
||||
WuJiali <18767152447@163.com>
|
||||
X-Jagger <xl.jagger@gmail.com>
|
||||
XBTop1! <xbtop1@gmail.com>
|
||||
XTY <^@xty.dev>
|
||||
Xiaoming <yokiming1994@gmail.com>
|
||||
@ -744,6 +860,7 @@ Xie Guanglei <xieguanglei@hotmail.com>
|
||||
Xinxing Li <lixinxing.2019@bytedance.com>
|
||||
Xinzhe Wang <me@imwxz.com>
|
||||
Xiping.wang <527409987@qq.com>
|
||||
Xu Zhiwei <gcdxuzhiwei@gmail.com>
|
||||
XuMM_12 <owiatsq@sina.cn>
|
||||
Xudong Cai <fifsky@gmail.com>
|
||||
Xudong Huang <me@xudong.dev>
|
||||
@ -763,11 +880,13 @@ Yu <yutingzhao1991@sina.com>
|
||||
Yu Mao <maoyulore@outlook.com>
|
||||
Yu Mao <maoyu960320@hotmail.com>
|
||||
YuChao Liang <l.yuch@foxmail.com>
|
||||
YuTao <yutao0818@vip.qq.com>
|
||||
Yuan <1076849402@qq.com>
|
||||
Yuhang Liu <644186735@qq.com>
|
||||
Yulia Maximova <juliam2007@mail.ru>
|
||||
Yunfly <120562638@qq.com>
|
||||
Yunus EŞ <yunus@yunuses.com>
|
||||
Yunwoo Ji <unu12073@gmail.com>
|
||||
Yuri Pirola <yuri.pirola@unimi.it>
|
||||
Yury Kozyrev <urakozz@me.com>
|
||||
Yusuke Ito <novi.mad@gmail.com>
|
||||
@ -776,32 +895,40 @@ Yuxuan Huo <yuxuan.huo2011@gmail.com>
|
||||
YuyingWu <wuyuying1128@gmail.com>
|
||||
ZHANGYU <723156735@qq.com>
|
||||
ZYSzys <zyszys98@gmail.com>
|
||||
Zach Bird <546439325@qq.com>
|
||||
Zack Amiton <zamiton@outlook.com>
|
||||
Zack Craig <zack@zack6849.com>
|
||||
Zap <a124116186@qq.com>
|
||||
ZeroToOne <igeeke@163.com>
|
||||
Zester Quinn Albano <zesterquinn.albano@gmail.com>
|
||||
Zgo <zguoby@gmail.com>
|
||||
Zhang Zhi <fytriht@gmail.com>
|
||||
Zheeeng <hi@zheeeng.me>
|
||||
Zhiqiang Gong <elory0513@hotmail.com>
|
||||
ZhouZhen <503633021@qq.com>
|
||||
Zhuo Chen <chenzhuo@caicloud.io>
|
||||
Ziluo <gyfzzu@gmail.com>
|
||||
Zohaib Ijaz <mzohaib.qc@gmail.com>
|
||||
Zzzen <843968788@qq.com>
|
||||
_XiaoTian <istianlei@qq.com>
|
||||
aLIEzsss4 <15624958088@163.com>
|
||||
aashutoshrathi <aashutoshrathi@gmail.com>
|
||||
acfasj <acfasj@gmail.com>
|
||||
adam <adamwu1992@163.com>
|
||||
afc163 <afc163@gmail.com>
|
||||
agent-z <1607291079@qq.com>
|
||||
aghArdeshir <ardeshireo@gmail.com>
|
||||
ahalimkara <ahalimkara@gmail.com>
|
||||
ajuner <106791576@qq.com>
|
||||
alekslario <aleksandlario@gmail.com>
|
||||
alex89lj <379118572@qq.com>
|
||||
alexchen <alexchen@easyops.cn>
|
||||
amedora <americandragsterracing@gmail.com>
|
||||
aoxiang78 <ao_xiang@live.com>
|
||||
appleshell <appleshell@outlook.com>
|
||||
arange <panpan2558@gmail.com>
|
||||
arifemrecelik <ce.arifemre@gmail.com>
|
||||
arturpfb <arturpfb@gmail.com>
|
||||
ascodelife <394922886@qq.com>
|
||||
ascoders <576625322@qq.com>
|
||||
ashishg-qburst <ashishg@qburst.com>
|
||||
atomoo <yangpein@gmail.com>
|
||||
@ -812,9 +939,11 @@ baidumap <460807394@qq.com>
|
||||
bang <sqibang@gmail.com>
|
||||
baozefeng <727751065@qq.com>
|
||||
bcd337 <b.bcd337@gmail.com>
|
||||
benben <jinwentao0914@dingtalk.com>
|
||||
bigbigbo <zxb141242@163.com>
|
||||
binyellow <571704908@qq.com>
|
||||
blankzust <450811238@qq.com>
|
||||
btea <2356281422@qq.com>
|
||||
bukas <yhz1219@gmail.com>
|
||||
byuanama <byuan@ama.com.au>
|
||||
byzyk <bohdan.kh@gmail.com>
|
||||
@ -827,6 +956,7 @@ cc189 <cc189dev@gmail.com>
|
||||
chaofeis <408067385@qq.com>
|
||||
chchen <cc272309126@gmail.com>
|
||||
chen wen jun <731028571@qq.com>
|
||||
chen-jingjie <2383844893@qq.com>
|
||||
chencheng (云谦) <sorrycc@gmail.com>
|
||||
chenlei <745512023@qq.com>
|
||||
chenlong <long.chen@abssqr.com>
|
||||
@ -850,6 +980,7 @@ davidhatten <david.r.hatten@gmail.com>
|
||||
ddcat1115 <ddcat1115@gmail.com>
|
||||
decade <decadef20@gmail.com>
|
||||
delesseps <andrewlessels@gmail.com>
|
||||
dengqing <1247748612@qq.com>
|
||||
denzw <denzw@21cn.com>
|
||||
dependabot[bot] <support@dependabot.com>
|
||||
desperado <yuwei_149@163.com>
|
||||
@ -861,6 +992,7 @@ djorkaeff <djorkae55@gmail.com>
|
||||
dolfje <nikosverschore@gmail.com>
|
||||
douxc <douxc512@gmail.com>
|
||||
dpyzo0o <yang.xu940121@outlook.com>
|
||||
dujun <emolingzhu@126.com>
|
||||
duzliang <duzliang@gmail.com>
|
||||
edgji <j.edgji@gmail.com>
|
||||
eidonjoe <806488716@qq.com>
|
||||
@ -877,11 +1009,14 @@ flashback313 <windmark2012@gmail.com>
|
||||
flyerH <hzw758@qq.com>
|
||||
frezc <504021398@qq.com>
|
||||
gaoryrt <gaoryrt@gmail.com>
|
||||
gaozhenqian <837856276@qq.com>
|
||||
genie <genie88@163.com>
|
||||
gepd <guillermoepd@hotmail.com>
|
||||
godfather <greenday.wj@foxmail.com>
|
||||
gregahren <grega.hren@gmail.com>
|
||||
gxvv <gaoxin18000@gmail.com>
|
||||
gyh9457 <gyh9457@163.com>
|
||||
gzq <zguoby@gmail.com>
|
||||
haianweifeng <1531297152@qq.com>
|
||||
haimrait <haimrait@gmail.com>
|
||||
handy <lihandi@gmail.com>
|
||||
@ -895,6 +1030,7 @@ hauwa123 <hauwa.aminu@outlook.com>
|
||||
hebingchang <hebingchang1@live.com>
|
||||
hehe <xpc1993@gmail.com>
|
||||
hehe <xpc_kacl@163.com>
|
||||
hello-chinese <841030329@qq.com>
|
||||
henryv0 <henryvo94@gmail.com>
|
||||
hi-caicai <hi@cai-cai.me>
|
||||
hicrystal <295247343@qq.com>
|
||||
@ -904,6 +1040,8 @@ huangyan.py <huangyan.py@bytedance.com>
|
||||
hugorezende <hugorezendedev@gmail.com>
|
||||
huishiyi <zhou1maple@gmail.com>
|
||||
huzzbuzz <huzzbuzz@outlook.com>
|
||||
hydraZty <670688667@qq.com>
|
||||
i3web <itnote@qq.com>
|
||||
iamcastelli <sowed@cyberdude.com>
|
||||
iamkun <kunhello@outlook.com>
|
||||
ibrahim velinov <ibsukru@gmail.com>
|
||||
@ -912,6 +1050,8 @@ int2d <int2d@qq.com>
|
||||
iojichervo <ioji@chervonagura.com.ar>
|
||||
ioldfish <fish.wangl@gmail.com>
|
||||
iorikingdom <iorikingdom@hotmail.com>
|
||||
isakol <isakol@kth.se>
|
||||
itibbers <jxn2014@gmail.com>
|
||||
iugo <iugogogo@gmail.com>
|
||||
j3l11234 <297259024@qq.com>
|
||||
jasonslyvia <jasonslyvia@gmail.com>
|
||||
@ -925,11 +1065,11 @@ jieniu$ <jienius@outlook.com>
|
||||
jinouwuque <ee2win@gmail.com>
|
||||
jinyaqiao1102 <405782493@QQ.com>
|
||||
jojoLockLock <miffyschou@sina.com>
|
||||
jueinin <1014397160@qq.com>
|
||||
junjing.zhang <zhangjunjing@gmail.com>
|
||||
kacjay <45483388@qq.com>
|
||||
kaifei <150641329@qq.com>
|
||||
kailunyao <kailunyao@163.com>
|
||||
kanweiwei <kwwnjujlc@sina.com>
|
||||
kanweiwei <475801900@qq.com>
|
||||
kaoding <41830859@qq.com>
|
||||
kasinooya <kasinooya@gmail.com>
|
||||
@ -940,6 +1080,7 @@ kdepp <kdepp.cd@gmail.com>
|
||||
keng <keng@renderinghouse.com>
|
||||
kenve <zwei.xie@gmail.com>
|
||||
kermolaev <kermolaev@cloudally.com>
|
||||
kily zhou <keeliizhou@gmail.com>
|
||||
klouskingsley <harry_tse@163.com>
|
||||
ko <git@yaksok.net>
|
||||
konakona <lovekonakona@gmail.com>
|
||||
@ -962,6 +1103,7 @@ liekkas <zjq0717@163.com>
|
||||
lihqi <455711093@qq.com>
|
||||
lilun <lilun_cd@keruyun.com>
|
||||
limingxin <906529775@qq.com>
|
||||
lisenenkov <lisenenkov@mail.ru>
|
||||
littleLane <857183384@qq.com>
|
||||
liuchuzhang <liuweiminer@hotmail.com>
|
||||
liuchuzhang <liuweiminer@126.com>
|
||||
@ -975,6 +1117,7 @@ luyiming <luyimingchn@gmail.com>
|
||||
lvren <luren6049@qq.com>
|
||||
lxnxbnq <yuanddmail@163.com>
|
||||
lyhper <lyhper@gmail.com>
|
||||
lyon.han <lyon.han.china@outlook.com>
|
||||
mArker <252133226@qq.com>
|
||||
maks <pine3ree@gmail.com>
|
||||
maximest-pierre <me@maximest-pierre.me>
|
||||
@ -982,6 +1125,7 @@ melchior voidwolf <kmno4k2mno4@gmail.com>
|
||||
memoryza <jincai.wang@foxmail.com>
|
||||
mgrdevport <mgrdevport@gmail.com>
|
||||
mingyan.yu <mingyan.yu@wormpex.com>
|
||||
miracles1919 <516571350@qq.com>
|
||||
mjfwebb <bugeyedboy@gmail.com>
|
||||
mkermani144 <mkermani144@gmail.com>
|
||||
mmmveggies <jakeselig@gmail.com>
|
||||
@ -993,6 +1137,7 @@ mumiao <mumiao@dtstack.com>
|
||||
mushan0x0 <mushan0x0@gmail.com>
|
||||
muzuiget <muzuiget@gmail.com>
|
||||
natergj <nater_nater@me.com>
|
||||
netcon <netcon@live.com>
|
||||
ngolin <poodll@163.com>
|
||||
nick-ChenZe <chenze2168@gmail.com>
|
||||
niko <644506165@qq.com>
|
||||
@ -1003,6 +1148,7 @@ oldchicken <www.chao3208525@qq.com>
|
||||
paleface001 <liuye10@yahoo.com>
|
||||
paranoidjk <hust2012jiangkai@gmail.com>
|
||||
parlop <parlop@gmail.com>
|
||||
paul <34345790@qq.com>
|
||||
pbrink231 <pbrink231@gmail.com>
|
||||
peiming <hyrijk@gmail.com>
|
||||
pengtikui <949828390@qq.com>
|
||||
@ -1022,6 +1168,7 @@ qramilq <ramirez99@mail.ru>
|
||||
qubaoming <qubaoming@didichuxing.com>
|
||||
ravirambles <ravirambles@gmail.com>
|
||||
realEago <774855001@qq.com>
|
||||
renzhao1113 <547249523@qq.com>
|
||||
richardison <richard.ison@carleton.ca>
|
||||
ryangun <ryangun@foxmail.com>
|
||||
ryanhoho <hswacoal@gmail.com>
|
||||
@ -1031,6 +1178,7 @@ sallen450 <jqh101@sina.com>
|
||||
samir elsharkawy <samir.elsharkawy@gmail.com>
|
||||
sdli <1669375803@qq.com>
|
||||
seognil LC <seognil@gmail.com>
|
||||
serializedowen <wjh199455@gmail.com>
|
||||
sfturing <sfturing@gmail.com>
|
||||
shangyuan.ning <shangyuan.ning@manaowan.com>
|
||||
shawtung <shawtung@qq.com>
|
||||
@ -1045,8 +1193,10 @@ snadn <snadn@snadn.cn>
|
||||
snail <120216220@qq.com>
|
||||
soeyi <sixinlei0927@gmail.com>
|
||||
sojournerc <cmeyer@zvelo.com>
|
||||
soso <ethdud1@gmail.com>
|
||||
sosohime <theziming@126.com>
|
||||
spideeee <spideeee@github.com>
|
||||
stefango <nankongyinan@gmail.com>
|
||||
stevenyuysy <stevenyuysy@gmail.com>
|
||||
stickmy <stickmyc@gmail.com>
|
||||
susiwen8 <susiwen8@gmail.com>
|
||||
@ -1067,7 +1217,10 @@ toshi1127 <toshi.matsumoto.2n@stu.hosei.ac.jp>
|
||||
twobin <twobin@live.com>
|
||||
u3u <qwq@qwq.cat>
|
||||
ubuntugod <adarshron@gmail.com>
|
||||
uchanlee <uchanlee.dev@gmail.com>
|
||||
undefined <johann@objekt.stream>
|
||||
undefined <undefined>
|
||||
unknown <tongsiyuan@corp.netease.com>
|
||||
unknown <chenyizhongx@gmail.com>
|
||||
ustccjw <317713370@qq.com>
|
||||
vagusX <vagusxl@gmail.com>
|
||||
@ -1075,10 +1228,15 @@ valleykid <valleykiddy@gmail.com>
|
||||
vaytsel <vaytsel@gmail.com>
|
||||
veveue <veveue@dingtalk.com>
|
||||
vgeyi <vgeyiz@126.com>
|
||||
vldh <lidahao@sisyphe.com.cn>
|
||||
vldh <alwaysloseall@sina.com>
|
||||
vouis <16nding@gmail.com>
|
||||
wa-ri <tztl1995@gmail.com>
|
||||
wadezhan <wadezhan@tencent.com>
|
||||
wan wan <wancihua@qq.com>
|
||||
wangao <jameslahm17@gmail.com>
|
||||
wangao <1366463855@qq.com>
|
||||
wangao <wa17@mails.tsinghua.edu.cn>
|
||||
wangshantao <605682551@qq.com>
|
||||
wangshuai <wangshuai@momenta.ai>
|
||||
wangtao0101 <yuecjn@gmail.com>
|
||||
@ -1093,6 +1251,7 @@ wendellhu <wendellhu95@gmail.com>
|
||||
wenhong <wenhong.zw@antfin.com>
|
||||
whinc <whincwu@163.com>
|
||||
whtang906 <whtang906@gmail.com>
|
||||
whwangms <whwangms@outlook.com>
|
||||
willc001 <will.c001@163.com>
|
||||
wizawu <wizawu@gmail.com>
|
||||
wleven <408493323@qq.com>
|
||||
@ -1117,6 +1276,8 @@ y-take <y.takey@gmail.com>
|
||||
yanguoyu <841185308@qq.com>
|
||||
yangwukang <yangwukang@boco.com.cn>
|
||||
yangxiaolin <yangxiao2810279802@gmail.com>
|
||||
yanm1ng <644169721@qq.com>
|
||||
yaoweiprc <yaoweiprc@hotmail.com>
|
||||
ycjcl868 <45808948@qq.com>
|
||||
ye4241 <ye4241@gmail.com>
|
||||
yehq <yedi728@qq.com>
|
||||
@ -1125,7 +1286,9 @@ yeshan333 <1329441308@qq.com>
|
||||
yibu.wang <yibu.wang@orion.co.com>
|
||||
yiminanci <yiminanci@gmail.com>
|
||||
yiminghe <yiminghe@gmail.com>
|
||||
yingxirz <inseeing@gmail.com>
|
||||
youmoo <youmoo@vellichor.me>
|
||||
youngz <chinayangzhan@126.com>
|
||||
yuche <i@yuche.me>
|
||||
yuezk <yuezk001@gmail.com>
|
||||
yui <1151815317@qq.com>
|
||||
@ -1141,19 +1304,23 @@ zhangpc <zhangpc@tenxcloud.com>
|
||||
zhangyangxue <383632607@qq.com>
|
||||
zhangyanling77 <18783226594@163.com>
|
||||
zhangzh <zhangzh@cnlemon.net>
|
||||
zhao-huo-long <lijiuyi1995@outlook.com>
|
||||
zhaocai <lzc09008@gmail.com>
|
||||
zhaopeidong <lwindscar@gmail.com>
|
||||
zhenfan.yu <fanerge@qq.com>
|
||||
zhuguibiao <505418722@qq.com>
|
||||
zhujun24 <zhujun87654321@gmail.com>
|
||||
zhyupe <zyp108421@gmail.com>
|
||||
zilong <jzlxiaohei@163.com>
|
||||
zinkey <yaya@uloveit.com.cn>
|
||||
zj9495 <zj9495@gmail.com>
|
||||
zjf <zjffun@gmail.com>
|
||||
zkwolf <chenhao5866@gmail.com>
|
||||
zlljqn <zlljqn@gmail.com>
|
||||
zollero <corona7@163.com>
|
||||
zombiej <smith3816@gmail.com>
|
||||
zongzi531 <zongzi.xy@gmail.com>
|
||||
zoomdong <1344492820@qq.com>
|
||||
zqran <uuxnet@gmail.com>
|
||||
ztplz <mysticzt@gmail.com>
|
||||
zuiidea <zuiiidea@gmail.com>
|
||||
zx6658 <zx6658@naver.com>
|
||||
@ -1167,9 +1334,10 @@ zytjs <yitongzhao@163.com>
|
||||
不吃猫的鱼 <michael2ib1989@gmail.com>
|
||||
丶尘殇 <sean.snow@live.com>
|
||||
乔奕轩 <qiao_yixuan@163.com>
|
||||
九思⚡⚡⚡ <2228429150@qq.com>
|
||||
二哲 <kodo@forchange.cn>
|
||||
二手掉包工程师 <rustin.liu@gmail.com>
|
||||
二货机器人 <smith3816@gmail.com>
|
||||
云剪者 <584518260@qq.com>
|
||||
付引 <xxxquotes@gmail.com>
|
||||
何乐 <work@imhele.com>
|
||||
何志勇 <15988134176@163.com>
|
||||
@ -1199,25 +1367,31 @@ zytjs <yitongzhao@163.com>
|
||||
廖应龙 <vigossliao@gmail.com>
|
||||
廖星 <liaoxing.lx@bytedance.com>
|
||||
张大大 <249812928@qq.com>
|
||||
张威 <1051127659@qq.com>
|
||||
张秀玲 <18811794335@163.com>
|
||||
徐坤龙 <272992168@qq.com>
|
||||
徐新航 <xuxinhang@bytedance.com>
|
||||
愚道 <tingzhao.ytz@antfin.com>
|
||||
曾凯 <zengkai2009@foxmail.com>
|
||||
期贤 <qixian.cs@antgroup.com>
|
||||
朮厃 <cn.ah.liu@gmail.com>
|
||||
李环冀 <158757774@qq.com>
|
||||
杨兴洲 <dr2009.china@gmail.com>
|
||||
杨哲迪 <yangzhedi@yidian-inc.com>
|
||||
杨小事er <Uiryzd@163.com>
|
||||
松子 <window.pibarr@gmail.com>
|
||||
林煌东 <10543563@qq.com>
|
||||
柚子男 <yozman@sina.com>
|
||||
沐霖 <304647173@qq.com>
|
||||
爱but的苍蝇 <354788473@qq.com>
|
||||
王林涛 <hzwanglintao@corp.netease.com>
|
||||
王浩 <boomler@hotmail.com>
|
||||
王集鹄 <wjhu111@21cn.com>
|
||||
琚致远 <juzhiyuan@apache.org>
|
||||
白羊座小葛 <abeyuhang@gmail.com>
|
||||
砖家 <brickspert.fjl@antfin.com>
|
||||
砖家 <576679268@qq.com>
|
||||
章鱼 <ryker.zy@gmail.com>
|
||||
竹尔 <Juelchiang@gmail.com>
|
||||
米老朱 <laozhu.me@gmail.com>
|
||||
精武陈真 <546369005@qq.com>
|
||||
@ -1232,11 +1406,12 @@ zytjs <yitongzhao@163.com>
|
||||
蔡伦 <sliuqin@gmail.com>
|
||||
薛定谔的猫 <weiran.zsd@outlook.com>
|
||||
薛定谔的猫 <hh_2013@foxmail.com>
|
||||
诸岳 <fuping.dfp@antgroup.com>
|
||||
诸岳 <fuping.dfp@antfin.com>
|
||||
诸岳 <fuping.dfp@antgroup.com>
|
||||
诸岳 <dengfuping_private@163.com>
|
||||
诸岳 <dengfuping_develop@163.com>
|
||||
诸葛龙 <158362530@qq.com>
|
||||
谭真 <736420282@qq.com>
|
||||
超能刚哥 <margox@foxmail.com>
|
||||
迷渡 <justjavac@gmail.com>
|
||||
郑旭 <332171564@qq.com>
|
||||
@ -1254,7 +1429,9 @@ zytjs <yitongzhao@163.com>
|
||||
骗你是小猫咪 <darryshaw@gmail.com>
|
||||
高力 <3071730@qq.com>
|
||||
鬼厉 <shawdanon@qq.com>
|
||||
麦谷 <1141453778@qq.com>
|
||||
黄俊亮 <jayhuang@easyops.cn>
|
||||
黄文鉴 <concefly@foxmail.com>
|
||||
黄斌 <bin.huang02@hand-china.com>
|
||||
黑雨 <wangning4567@163.com>
|
||||
龚方闻 <fangwen.gong@baishancloud.com>
|
@ -15,6 +15,96 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 4.20.2
|
||||
|
||||
`2022-04-30`
|
||||
|
||||
- Segmented
|
||||
- 🐞 Fix Segmented inconsisit height with other controls. [#35281](https://github.com/ant-design/ant-design/pull/35281)
|
||||
- 🐞 Fix Segmented animation not working correct in StrictMode mode. [#35281](https://github.com/ant-design/ant-design/pull/35281)
|
||||
- 🆕 Segmented `options` now supports `icon` property. [#35256](https://github.com/ant-design/ant-design/pull/35256)
|
||||
- Table
|
||||
- ⌨️ Improve Table columns sorter a11y experience. [#35269](https://github.com/ant-design/ant-design/pull/35269)
|
||||
- 🇪🇸 Added Table filter localization for es_ES. [#35309](https://github.com/ant-design/ant-design/pull/35309) [@agarciaguillo](https://github.com/agarciaguillo)
|
||||
- 💄 Fix Switch color in dark theme. [#35332](https://github.com/ant-design/ant-design/pull/35332)
|
||||
- 💄 Tweak Breadcrumb link hover color. [#35324](https://github.com/ant-design/ant-design/pull/35324)
|
||||
- 🐞 Fix Space throws `Encountered two children with the same key` warning in some cases. [#35311](https://github.com/ant-design/ant-design/pull/35311)
|
||||
- 🐞 Fix Select tag remove icon position issue. [#35336](https://github.com/ant-design/ant-design/pull/35336) [@walidcherhane](https://github.com/walidcherhane)
|
||||
|
||||
## 4.20.1
|
||||
|
||||
`2022-04-26`
|
||||
|
||||
- 🐞 Fix Breadcrumb extra padding and margin style. [#35235](https://github.com/ant-design/ant-design/pull/35235)
|
||||
- 🐞 Fix Input.Seach inconsistent behavior of triggering `onSearch` when press enter using Chinese inputting method. [#35164](https://github.com/ant-design/ant-design/pull/35164) [@qyzzzz](https://github.com/qyzzzz)
|
||||
- 🐞 Fix circle reference between Upload and Dragger. [#34379](https://github.com/ant-design/ant-design/pull/34379) [@kanweiwei](https://github.com/kanweiwei)
|
||||
|
||||
## 4.20.0
|
||||
|
||||
`2022-04-24`
|
||||
|
||||
- 🔥 React 18 Support. Fix related known issue.
|
||||
- 🐞 Fix Form with React 18 StrictMode missing error message update. [#35096](https://github.com/ant-design/ant-design/pull/35096)
|
||||
- 🐞 Fix Notification and Message throw `createRoot` warning in React 18. [#35030](https://github.com/ant-design/ant-design/pull/35030)
|
||||
- 🐞 Fix BackTop not working in StrictMode. [#34858](https://github.com/ant-design/ant-design/pull/34858) [@tmkx](https://github.com/tmkx)
|
||||
- 🔥 New component Segmented. [#34319](https://github.com/ant-design/ant-design/pull/34319)
|
||||
- 🛠 Since v4.20.0 `Segemented` props `onChange` callback function parameter adjusted from `ChangeEvent` (v4.20.0-alpha.0, v4.20.0-alpha.1) to `value` to simplify API. [#35187](https://github.com/ant-design/ant-design/pull/35187) [@vagusX](https://github.com/vagusX)
|
||||
- Form
|
||||
- 🔥 Form support `useWatch` to get current field value. [#35036](https://github.com/ant-design/ant-design/pull/35036)
|
||||
- 🆕 Form support `useFormInstance` to get current context form instance. [#35039](https://github.com/ant-design/ant-design/pull/35039)
|
||||
- 💄 Fix Form broken layout when set `labelCol={{ sm: 24 }}` and `wrapperCol={{ sm: 24 }}`. [#34907](https://github.com/ant-design/ant-design/pull/34907)
|
||||
- 🛎 Menu support `items` for perf prepare, and `children` will be removed in next major version. [#34559](https://github.com/ant-design/ant-design/pull/34559)
|
||||
- 🆕 Image PreviewGroup Support top progress rendering. [#35038](https://github.com/ant-design/ant-design/pull/35038) [@zpc7](https://github.com/zpc7)
|
||||
- Upload
|
||||
- 🆕 Upload support `crossOrigin` for images in `picture-card` mode. [#34981](https://github.com/ant-design/ant-design/pull/34981) [@dragmove](https://github.com/dragmove)
|
||||
- 🐞 Fix Upload `prefixCls` don't work on file list. [#34944](https://github.com/ant-design/ant-design/pull/34944) [@swchen](https://github.com/swchen)
|
||||
- 💄 Improve Upload action styles. [#35052](https://github.com/ant-design/ant-design/pull/35052)
|
||||
- Table
|
||||
- 🆕 Support reset to the default value rather than empty, when click reset in Table column filter. [#34355](https://github.com/ant-design/ant-design/pull/34355) [@heiyu4585](https://github.com/heiyu4585)
|
||||
- 💄 Fix Table head background and selection column width styling issues when `size="small"`. [#34963](https://github.com/ant-design/ant-design/pull/34963)
|
||||
- 🇩🇪 Improve German translations for Table. [#34836](https://github.com/ant-design/ant-design/pull/34836) [@pfedan](https://github.com/pfedan)
|
||||
- ⚡️ Optimize Table filter calculation perfromance. [#35064](https://github.com/ant-design/ant-design/pull/35064) [@nieyuyao](https://github.com/nieyuyao)
|
||||
- 💄 Improve small and middle size Table selection dropdown margin style. [#35173](https://github.com/ant-design/ant-design/pull/35173)
|
||||
- Tree
|
||||
- 🆕 Tree `switcherIcon` prop support render-prop. [#34470](https://github.com/ant-design/ant-design/pull/34470) [@zqran](https://github.com/zqran)
|
||||
- 🆕 Tree support `rootClassName` and `rootStyle`. [#34578](https://github.com/ant-design/ant-design/pull/34578)
|
||||
- Breadcrumb
|
||||
- 🐞 Fix Breadcrumb deprecated warning of Dropdown `placement`. [#35162](https://github.com/ant-design/ant-design/pull/35162)
|
||||
- 🐞 Fix Breadcrumb show the number when is unexpected. [#35123](https://github.com/ant-design/ant-design/pull/35123)
|
||||
- ⌨️ Make structure of Breadcrumb be accessible. [#34082](https://github.com/ant-design/ant-design/pull/34082) [@VladimirOtroshchenko](https://github.com/VladimirOtroshchenko)
|
||||
- Anchor
|
||||
- 🆕 Anchor `getCurrentAnchor` has active link as argument. [#34799](https://github.com/ant-design/ant-design/pull/34799)
|
||||
- 🛠 Refactor Anchor to Function component. [#35073](https://github.com/ant-design/ant-design/pull/35073) [@LongHaoo](https://github.com/LongHaoo)
|
||||
- Cascader
|
||||
- 🆕 Cascader supports `showCheckedStrategy ` for value display strategy. [#34568](https://github.com/ant-design/ant-design/pull/34568) [@heiyu4585](https://github.com/heiyu4585)
|
||||
- 🐞 Fix Cascader search result do not fill the entrie panel. [#35019](https://github.com/ant-design/ant-design/pull/35019) [@boomler](https://github.com/boomler)
|
||||
- 🆕 Click event object can be accessed in `onCopy` function of Typography. [#34655](https://github.com/ant-design/ant-design/pull/34655) [@yzwxk](https://github.com/yzwxk)
|
||||
- 🆕 Grid supports `justify="space-evenly"`. [#34606](https://github.com/ant-design/ant-design/pull/34606) [@gp5251](https://github.com/gp5251)
|
||||
- 🆕 Support `rootClassName` property for Dialog and Image. [#34574](https://github.com/ant-design/ant-design/pull/34574) [@heiyu4585](https://github.com/heiyu4585)
|
||||
- 🐞 Fix error `Nothing was returned from render` when Skeleton use falsy `loading` props without `children`. [#34872](https://github.com/ant-design/ant-design/pull/34872) [@AlbertAZ1992](https://github.com/AlbertAZ1992)
|
||||
- 💄 Optimize Switch disabled color to fit colorful background. [#35103](https://github.com/ant-design/ant-design/pull/35103)
|
||||
- 💄 Remove Tabs `overflow: hidden` style to fix Select and sticky Table display problem inside Tabs. [#35195](https://github.com/ant-design/ant-design/pull/35195)
|
||||
- 💄 Fix Steps style issues in RTL mode. [#35088](https://github.com/ant-design/ant-design/pull/35088) [@zpc7](https://github.com/zpc7)
|
||||
- 💄 Fix animation for standalone Badge in RTL mode. [#34899](https://github.com/ant-design/ant-design/pull/34899) [@hmz22](https://github.com/hmz22)
|
||||
- 🛠 Optimize Modal id generate logic to improve accessibility experience. [#35072](https://github.com/ant-design/ant-design/pull/35072)
|
||||
- 🐞 Fix Select and AutoComplete scroll abnormal behavior when navigate via keyboard.。[#35025](https://github.com/ant-design/ant-design/pull/35025)
|
||||
- Spin
|
||||
- 💄 Fix Spin animation style being abnormally parsed in Parcel. [#35005](https://github.com/ant-design/ant-design/pull/35005)
|
||||
- ⌨️ Spin add `aria` attribute to improve accessibility. [#34408](https://github.com/ant-design/ant-design/pull/34408) [@heiyu4585](https://github.com/heiyu4585)
|
||||
- ⌨️ Dropdown support select option by keyboard. [#34738](https://github.com/ant-design/ant-design/pull/34738)
|
||||
- 🐞 Fix Title, Text, Paragraph components cannot get `ref` bug. [#34847](https://github.com/ant-design/ant-design/pull/34847) [@MQuy](https://github.com/MQuy)
|
||||
- Input
|
||||
- 💄 Input.Group prevent components from getting style from Form.Item. [#34764](https://github.com/ant-design/ant-design/pull/34764)
|
||||
- 💄 Adjust TextArea style in Form. [#34714](https://github.com/ant-design/ant-design/pull/34714)
|
||||
- ⌨️ Fix `aria-checked` attribute for Checkbox, to avoid screen reader getting an incorrect status. [#34862](https://github.com/ant-design/ant-design/pull/34862) [@SpaNb4](https://github.com/SpaNb4)
|
||||
- Less
|
||||
- 💄 Replace less html selector with related variable. [#35186](https://github.com/ant-design/ant-design/pull/35186) [@jeffdrumgod](https://github.com/jeffdrumgod)
|
||||
- 💄 Modify less `danger` value from the function to variable. [#35113](https://github.com/ant-design/ant-design/pull/35113) [@TrickyPi](https://github.com/TrickyPi)
|
||||
- 🐞 Arrow border radius variable use fixed value. [#35086](https://github.com/ant-design/ant-design/pull/35086) [@MadCcc](https://github.com/MadCcc)
|
||||
- TypeScript
|
||||
- 🤖 Fixed `Upload` component `UploadChangeParam<T>` internal `fileList` not using generics. [#35158](https://github.com/ant-design/ant-design/pull/35158) [@rendaoer](https://github.com/rendaoer)
|
||||
- 🤖 Update TypeScript definition for `@types/react@18` compatible. [#35075](https://github.com/ant-design/ant-design/pull/35075) [@AliRezaBeigy](https://github.com/AliRezaBeigy) [#35076](https://github.com/ant-design/ant-design/pull/35076) [@littledian](https://github.com/littledian)
|
||||
|
||||
## 4.19.5
|
||||
|
||||
`2022-04-02`
|
||||
|
@ -15,6 +15,96 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 4.20.2
|
||||
|
||||
`2022-04-30`
|
||||
|
||||
- Segmented
|
||||
- 🐞 修复 Segmented 组件高度和其他控件不一致的问题。[#35281](https://github.com/ant-design/ant-design/pull/35281)
|
||||
- 🐞 修复 React StrictMode 下 Segmented 动画丢失的问题。[#35281](https://github.com/ant-design/ant-design/pull/35281)
|
||||
- 🆕 Segmented `options` 支持设置 `icon` 属性。[#35256](https://github.com/ant-design/ant-design/pull/35256)
|
||||
- Table
|
||||
- ⌨️ 优化 Table 排序按钮的键盘可访问性。[#35269](https://github.com/ant-design/ant-design/pull/35269)
|
||||
- 🇪🇸 补充 Table 西班牙语筛选文案。[#35309](https://github.com/ant-design/ant-design/pull/35309) [@agarciaguillo](https://github.com/agarciaguillo)
|
||||
- 🐞 修复 Switch 在暗黑主题下关闭时的颜色问题。[#35332](https://github.com/ant-design/ant-design/pull/35332)
|
||||
- 💄 微调 Breadcrumb 链接 hover 色为中性色。[#35324](https://github.com/ant-design/ant-design/pull/35324)
|
||||
- 🐞 修复 Space 在某些情况下抛出 `Encountered two children with the same key` 警告的问题。[#35311](https://github.com/ant-design/ant-design/pull/35311)
|
||||
- 🐞 修复 Select 多选标签移除图标位置偏下的问题。[#35336](https://github.com/ant-design/ant-design/pull/35336) [@walidcherhane](https://github.com/walidcherhane)
|
||||
|
||||
## 4.20.1
|
||||
|
||||
`2022-04-26`
|
||||
|
||||
- 🐞 修复 Breadcrumb 多余的 `padding` 和 `margin` 样式。[#35235](https://github.com/ant-design/ant-design/pull/35235)
|
||||
- 🐞 修复 Input.Search 在中文输入法下回车键触发 `onSearch` 的行为不一致的问题。[#35164](https://github.com/ant-design/ant-design/pull/35164) [@qyzzzz](https://github.com/qyzzzz)
|
||||
- 🐞 修复 Upload 和 Upload.Dragger 之间循环依赖的问题。[#34379](https://github.com/ant-design/ant-design/pull/34379) [@kanweiwei](https://github.com/kanweiwei)
|
||||
|
||||
## 4.20.0
|
||||
|
||||
`2022-04-24`
|
||||
|
||||
- 🔥 支持 React 18 以及严格模式,修复了相关已知问题。
|
||||
- 🐞 修复 Form 在 React 18 的 StrictMode 下,错误信息无法更新的问题。[#35096](https://github.com/ant-design/ant-design/pull/35096)
|
||||
- 🐞 修复 Notification 和 Message 在 React 18 下抛出使用 `createRoot` 的警告信息。[#35030](https://github.com/ant-design/ant-design/pull/35030)
|
||||
- 🐞 修复 BackTop 组件在严格模式下不能正常工作的问题。[#34858](https://github.com/ant-design/ant-design/pull/34858) [@tmkx](https://github.com/tmkx)
|
||||
- 🔥 新增 Segmented 分段控制器组件。[#34319](https://github.com/ant-design/ant-design/pull/34319)
|
||||
- 🛠 4.20.0 正式版后,Segemented 的 `onChange` 回调函数的参数从 `ChangeEvent` 调整为 `value`。如果你使用了 `4.20.0-alpha.0` `4.20.0-alpha.1`,请注意这个变化。[#35187](https://github.com/ant-design/ant-design/pull/35187) [@vagusX](https://github.com/vagusX)
|
||||
- Form
|
||||
- 🔥 Form 添加 `useWatch` 支持获取当前字段值。[#35036](https://github.com/ant-design/ant-design/pull/35036)
|
||||
- 🆕 Form 支持 `useFormInstance` 以获取当前上下文中的 Form 实例。[#35039](https://github.com/ant-design/ant-design/pull/35039)
|
||||
- 💄 修复 Form `labelCol={{ sm: 24 }}` 和 `wrapperCol={{ sm: 24 }}` 时样式错乱的问题。[#34907](https://github.com/ant-design/ant-design/pull/34907)
|
||||
- 🛎 Menu 添加 `items` 数据化菜单项支持以为将来性能提升做准备,并且 `children` 将会在下个大版本中废弃。[#34559](https://github.com/ant-design/ant-design/pull/34559)
|
||||
- 🆕 Image PreviewGroup 支持顶部进度渲染。[#35038](https://github.com/ant-design/ant-design/pull/35038) [@zpc7](https://github.com/zpc7)
|
||||
- Upload
|
||||
- 🆕 Upload `picture-card` 模式支持配置图片的 `crossOrigin` 属性。[#34981](https://github.com/ant-design/ant-design/pull/34981) [@dragmove](https://github.com/dragmove)
|
||||
- 🐞 修复 Upload `prefixCls` 对列表不生效的问题。[#34944](https://github.com/ant-design/ant-design/pull/34944) [@swchen](https://github.com/swchen)
|
||||
- 💄 优化 Upload 操作按钮的样式细节。[#35052](https://github.com/ant-design/ant-design/pull/35052)
|
||||
- Table
|
||||
- 🆕 Table 列筛选条件重置时,支持重置为默认值而非空值。[#34355](https://github.com/ant-design/ant-design/pull/34355) [@heiyu4585](https://github.com/heiyu4585)
|
||||
- 💄 修复 Table `size="small"` 时列头背景色和选择列宽度的样式问题。[#34963](https://github.com/ant-design/ant-design/pull/34963)
|
||||
- 🇩🇪 补全 Table 的德语国际化文案。[#34836](https://github.com/ant-design/ant-design/pull/34836) [@pfedan](https://github.com/pfedan)
|
||||
- ⚡️ 优化 Table 过滤列表的计算性能。[#35064](https://github.com/ant-design/ant-design/pull/35064) [@nieyuyao](https://github.com/nieyuyao)
|
||||
- 💄 优化 Table `size="small"` 和 `size="middle"` 时选择下拉菜单的边距样式。[#35173](https://github.com/ant-design/ant-design/pull/35173)
|
||||
- Tree
|
||||
- 🆕 Tree 组件的 `switcherIcon` 属性支持 render-prop。[#34470](https://github.com/ant-design/ant-design/pull/34470) [@zqran](https://github.com/zqran)
|
||||
- 🆕 Tree 支持 `rootClassName` and `rootStyle`。[#34578](https://github.com/ant-design/ant-design/pull/34578)
|
||||
- Breadcrumb
|
||||
- 🐞 修复 Breadcrumb 抛出 `placement` 废弃警告的问题。[#35162](https://github.com/ant-design/ant-design/pull/35162)
|
||||
- 🐞 修复 Breadcrumb 展示非预期的数字符号的样式问题。[#35123](https://github.com/ant-design/ant-design/pull/35123)
|
||||
- ⌨️ 为 Breadcrumb 层次结构增加可访问性支持。[#34082](https://github.com/ant-design/ant-design/pull/34082) [@VladimirOtroshchenko](https://github.com/VladimirOtroshchenko)
|
||||
- Anchor
|
||||
- 🆕 Anchor `getCurrentAnchor` 参数中返回默认高亮项。[#34799](https://github.com/ant-design/ant-design/pull/34799)
|
||||
- 🛠 重构 Anchor 为函数组件。[#35073](https://github.com/ant-design/ant-design/pull/35073) [@LongHaoo](https://github.com/LongHaoo)
|
||||
- Cascader
|
||||
- 🆕 Cascader 添加 `showCheckedStrategy` 用于配置回填方式。[#34568](https://github.com/ant-design/ant-design/pull/34568) [@heiyu4585](https://github.com/heiyu4585)
|
||||
- 🐞 修复 Cascader 的搜索结果未占满整个面板的问题。[#35019](https://github.com/ant-design/ant-design/pull/35019) [@boomler](https://github.com/boomler)
|
||||
- 🆕 Typography 的 `onCopy` 方法支持获取点击事件对象。[#34655](https://github.com/ant-design/ant-design/pull/34655) [@yzwxk](https://github.com/yzwxk)
|
||||
- 🆕 Grid 支持 `justify="space-evenly"`。[#34606](https://github.com/ant-design/ant-design/pull/34606) [@gp5251](https://github.com/gp5251)
|
||||
- 🆕 Dialog 及 Image 支持 `rootClassName` 属性。[#34574](https://github.com/ant-design/ant-design/pull/34574) [@heiyu4585](https://github.com/heiyu4585)
|
||||
- 🐞 修复 Skeleton 在没有 `children` 并设置 `loading` 为 false 时提示 `Nothing was returned from render` 的问题。[#34872](https://github.com/ant-design/ant-design/pull/34872) [@AlbertAZ1992](https://github.com/AlbertAZ1992)
|
||||
- 💄 优化 Switch 禁用色以更好适应非白底背景。[#35103](https://github.com/ant-design/ant-design/pull/35103)
|
||||
- 💄 移除 Tabs `overflow: hidden` 样式以修复 Select 和 sticky Table 在 Tabs 中的展现问题。[#35195](https://github.com/ant-design/ant-design/pull/35195)
|
||||
- 💄 修正 Steps 在 RTL 模式下样式问题。[#35088](https://github.com/ant-design/ant-design/pull/35088) [@zpc7](https://github.com/zpc7)
|
||||
- 💄 修复 Badge 在 RTL 模式下、独立使用时的动画效果。[#34899](https://github.com/ant-design/ant-design/pull/34899) [@hmz22](https://github.com/hmz22)
|
||||
- 🛠 优化 Modal id 生成逻辑,以优化无障碍体验。[#35072](https://github.com/ant-design/ant-design/pull/35072)
|
||||
- 🐞 修复 Select 和 AutoComplete 使用键盘向下滚动时行为异常的问题。[#35025](https://github.com/ant-design/ant-design/pull/35025)
|
||||
- Spin
|
||||
- 💄 修复 Spin 动画样式在 Parcel 解析异常的问题。[#35005](https://github.com/ant-design/ant-design/pull/35005)
|
||||
- ⌨️ Spin 添加 `aria` 属性以提升可访问性。[#34408](https://github.com/ant-design/ant-design/pull/34408) [@heiyu4585](https://github.com/heiyu4585)
|
||||
- ⌨️ Dropdown 支持方向键切换选项。[#34738](https://github.com/ant-design/ant-design/pull/34738)
|
||||
- 🐞 修复 Title、Text、Paragraph 组件不支持 `ref` 的问题。[#34847](https://github.com/ant-design/ant-design/pull/34847) [@MQuy](https://github.com/MQuy)
|
||||
- Input
|
||||
- 💄 Input.Group 对子组件屏蔽 Form.Item 的样式。[#34764](https://github.com/ant-design/ant-design/pull/34764)
|
||||
- 💄 调整 Form 下 TextArea 的样式。[#34714](https://github.com/ant-design/ant-design/pull/34714) [@MadCcc](https://github.com/MadCcc)
|
||||
- ⌨️ 修复 Checkbox 缺少 `aria-checked` 属性导致屏幕阅读器识别错误的问题。[#34862](https://github.com/ant-design/ant-design/pull/34862) [@SpaNb4](https://github.com/SpaNb4)
|
||||
- Less
|
||||
- 💄 替换 less 中的 html 选择器为对应变量。[#35186](https://github.com/ant-design/ant-design/pull/35186) [@jeffdrumgod](https://github.com/jeffdrumgod)
|
||||
- 💄 修改 less 中 `danger` 值从函数改为变量。[#35113](https://github.com/ant-design/ant-design/pull/35113) [@TrickyPi](https://github.com/TrickyPi)
|
||||
- 🐞 箭头圆角使用固定值 2px 变量。[#35086](https://github.com/ant-design/ant-design/pull/35086) [@MadCcc](https://github.com/MadCcc)
|
||||
- TypeScript
|
||||
- 🤖 修正 Upload 组件中 `UploadChangeParam<T>` 内部 `fileList` 不使用泛型问题。[#35158](https://github.com/ant-design/ant-design/pull/35158) [@rendaoer](https://github.com/rendaoer)
|
||||
- 🤖 更新 TypeScript 定义以兼容 `@types/react@18`。[#35075](https://github.com/ant-design/ant-design/pull/35075) [@AliRezaBeigy](https://github.com/AliRezaBeigy) [#35076](https://github.com/ant-design/ant-design/pull/35076) [@littledian](https://github.com/littledian)
|
||||
|
||||
## 4.19.5
|
||||
|
||||
`2022-04-02`
|
||||
|
12
CODEOWNERS
12
CODEOWNERS
@ -1,12 +0,0 @@
|
||||
# CODEOWNERS syntax
|
||||
# A CODEOWNERS file uses a pattern that follows the same rules used in gitignore files.
|
||||
# The pattern is followed by one or more GitHub usernames or team names using the standard @username or @org/team-name format.
|
||||
# You can also refer to a user by an email address that has been added to their GitHub account, for example user@example.com.
|
||||
|
||||
# no default file owner
|
||||
#/* @afc163
|
||||
/components/tree/* @zombieJ
|
||||
/components/tree-select/* @zombieJ
|
||||
|
||||
# ...
|
||||
# other components
|
@ -12,7 +12,7 @@ Uma solução empresarial de design e biblioteca UI para React.
|
||||
|
||||
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
|
||||
|
||||
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
|
||||
[![Renovate status][renovate-image]][renovate-dashboard-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
|
||||
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![FOSSA Status][fossa-image]][fossa-url] [![Discussions][discussions-image]][discussions-url] [![][issues-helper-image]][issues-helper-url] [![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
|
||||
@ -22,10 +22,6 @@ Uma solução empresarial de design e biblioteca UI para React.
|
||||
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22
|
||||
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
|
||||
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
|
||||
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
|
||||
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
|
||||
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
|
||||
[david-url]: https://david-dm.org/ant-design/ant-design
|
||||
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/antd
|
||||
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
|
||||
@ -44,6 +40,8 @@ Uma solução empresarial de design e biblioteca UI para React.
|
||||
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
|
||||
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
|
||||
[issues-helper-url]: https://github.com/actions-cool/issues-helper
|
||||
[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square
|
||||
[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
|
||||
|
||||
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
|
||||
[![Renovate status][renovate-image]][renovate-dashboard-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
|
||||
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![FOSSA Status][fossa-image]][fossa-url] [![Discussions][discussions-image]][discussions-url] [![][issues-helper-image]][issues-helper-url] [![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
|
||||
@ -22,10 +22,6 @@
|
||||
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22
|
||||
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
|
||||
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
|
||||
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
|
||||
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
|
||||
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
|
||||
[david-url]: https://david-dm.org/ant-design/ant-design
|
||||
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/antd
|
||||
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
|
||||
@ -44,6 +40,8 @@
|
||||
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
|
||||
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
|
||||
[issues-helper-url]: https://github.com/actions-cool/issues-helper
|
||||
[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square
|
||||
[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
|
||||
|
||||
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
|
||||
[![Renovate status][renovate-image]][renovate-dashboard-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
|
||||
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![FOSSA Status][fossa-image]][fossa-url] [![Discussions][discussions-image]][discussions-url] [![][issues-helper-image]][issues-helper-url] [![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
|
||||
@ -22,10 +22,6 @@
|
||||
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22
|
||||
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
|
||||
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
|
||||
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
|
||||
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
|
||||
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
|
||||
[david-url]: https://david-dm.org/ant-design/ant-design
|
||||
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/antd
|
||||
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
|
||||
@ -44,6 +40,8 @@
|
||||
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
|
||||
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
|
||||
[issues-helper-url]: https://github.com/actions-cool/issues-helper
|
||||
[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square
|
||||
[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
import UnreachableException from '../unreachableException';
|
||||
|
||||
describe('UnreachableException', () => {
|
||||
it('error thrown matches snapshot', () => {
|
||||
const exception = new UnreachableException('some value');
|
||||
expect(exception.error.message).toMatchInlineSnapshot(`"unreachable case: \\"some value\\""`);
|
||||
});
|
||||
});
|
@ -148,7 +148,9 @@ describe('Test utils function', () => {
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
).instance();
|
||||
)
|
||||
.find(Wave)
|
||||
.instance();
|
||||
expect(wrapper.bindAnimationEvent()).toBe(undefined);
|
||||
});
|
||||
|
||||
@ -159,7 +161,9 @@ describe('Test utils function', () => {
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
).instance();
|
||||
)
|
||||
.find(Wave)
|
||||
.instance();
|
||||
expect(wrapper.bindAnimationEvent()).toBe(undefined);
|
||||
});
|
||||
|
||||
@ -168,7 +172,9 @@ describe('Test utils function', () => {
|
||||
<Wave>
|
||||
<input />
|
||||
</Wave>,
|
||||
).instance();
|
||||
)
|
||||
.find(Wave)
|
||||
.instance();
|
||||
expect(wrapper.bindAnimationEvent()).toBe(undefined);
|
||||
});
|
||||
|
||||
|
@ -4,4 +4,9 @@ export { resetWarned };
|
||||
|
||||
export default (valid: boolean, component: string, message: string): void => {
|
||||
devWarning(valid, `[antd: ${component}] ${message}`);
|
||||
|
||||
// StrictMode will inject console which will not throw warning in React 17.
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
resetWarned();
|
||||
}
|
||||
};
|
||||
|
@ -3,20 +3,9 @@ import { CSSInterpolation, Theme, useCacheToken, useStyleRegister } from '@ant-d
|
||||
import genComponentStyleHook from './util/genComponentStyleHook';
|
||||
import defaultSeedToken, { derivative as defaultDerivative } from './themes/default';
|
||||
import version from '../../version';
|
||||
import { resetComponent, resetIcon, clearFix, roundedArrow } from './util';
|
||||
import { resetComponent, resetIcon, clearFix, roundedArrow, operationUnit } from './util';
|
||||
import formatToken from './util/alias';
|
||||
import {
|
||||
initSlideMotion,
|
||||
slideUpIn,
|
||||
slideUpOut,
|
||||
slideDownIn,
|
||||
slideDownOut,
|
||||
slideLeftIn,
|
||||
slideLeftOut,
|
||||
slideRightIn,
|
||||
slideRightOut,
|
||||
} from './util/slide';
|
||||
import statisticToken, { merge as mergeToken } from './util/statistic';
|
||||
import statisticToken, { merge as mergeToken, statistic } from './util/statistic';
|
||||
import { GlobalToken, PresetColors } from './interface';
|
||||
import type {
|
||||
SeedToken,
|
||||
@ -28,25 +17,20 @@ import type {
|
||||
import type { FullToken } from './util/genComponentStyleHook';
|
||||
|
||||
export {
|
||||
PresetColors,
|
||||
// css utils
|
||||
resetComponent,
|
||||
resetIcon,
|
||||
clearFix,
|
||||
roundedArrow,
|
||||
initSlideMotion,
|
||||
slideUpIn,
|
||||
slideUpOut,
|
||||
slideDownIn,
|
||||
slideDownOut,
|
||||
slideLeftIn,
|
||||
slideLeftOut,
|
||||
slideRightIn,
|
||||
slideRightOut,
|
||||
useStyleRegister,
|
||||
operationUnit,
|
||||
// colors
|
||||
PresetColors,
|
||||
// Statistic
|
||||
statistic,
|
||||
statisticToken,
|
||||
mergeToken,
|
||||
// GenComponentStyleHook
|
||||
// hooks
|
||||
useStyleRegister,
|
||||
genComponentStyleHook,
|
||||
};
|
||||
|
||||
@ -73,6 +57,11 @@ export const DesignTokenContext = React.createContext<{
|
||||
});
|
||||
|
||||
// ================================== Hook ==================================
|
||||
// In dev env, we refresh salt per hour to avoid user use this
|
||||
// Note: Do not modify this to real time update which will make debug harder
|
||||
const saltPrefix =
|
||||
process.env.NODE_ENV === 'production' ? version : `${version}-${new Date().getHours()}`;
|
||||
|
||||
export function useToken(): [Theme<SeedToken, DerivativeToken>, GlobalToken, string] {
|
||||
const {
|
||||
token: rootDesignToken,
|
||||
@ -81,7 +70,7 @@ export function useToken(): [Theme<SeedToken, DerivativeToken>, GlobalToken, str
|
||||
hashed,
|
||||
} = React.useContext(DesignTokenContext);
|
||||
|
||||
const salt = `${version}-${hashed || ''}`;
|
||||
const salt = `${saltPrefix}-${hashed || ''}`;
|
||||
|
||||
const [token, hashId] = useCacheToken<GlobalToken, SeedToken>(
|
||||
theme,
|
||||
@ -100,5 +89,4 @@ export type UseComponentStyleResult = [(node: React.ReactNode) => React.ReactEle
|
||||
|
||||
export type GenerateStyle<ComponentToken extends object, ReturnType = CSSInterpolation> = (
|
||||
token: ComponentToken,
|
||||
hashId?: string,
|
||||
) => ReturnType;
|
||||
|
@ -1,6 +1,8 @@
|
||||
import type * as React from 'react';
|
||||
import type { ComponentToken as AnchorComponentToken } from '../../anchor/style';
|
||||
import type { ComponentToken as ButtonComponentToken } from '../../button/style';
|
||||
import type { ComponentToken as DividerComponentToken } from '../../divider/style';
|
||||
import type { ComponentToken as DropdownComponentToken } from '../../dropdown/style';
|
||||
import type { ComponentToken as EmptyComponentToken } from '../../empty/style';
|
||||
import type { ComponentToken as CascaderComponentToken } from '../../cascader/style';
|
||||
import type { ComponentToken as InputNumberComponentToken } from '../../input-number/style';
|
||||
@ -8,7 +10,13 @@ import type { ComponentToken as MentionsComponentToken } from '../../mentions/st
|
||||
import type { ComponentToken as SelectComponentToken } from '../../select/style';
|
||||
import type { ComponentToken as SliderComponentToken } from '../../slider/style';
|
||||
import type { ComponentToken as TypographyComponentToken } from '../../typography/style';
|
||||
import type { ComponentToken as BackTopComponentToken } from '../../back-top/style';
|
||||
import type { ComponentToken as DatePickerComponentToken } from '../../date-picker/style';
|
||||
import type { ComponentToken as TimelineComponentToken } from '../../timeline/style';
|
||||
import type { ComponentToken as MenuComponentToken } from '../../menu/style';
|
||||
import type { ComponentToken as UploadComponentToken } from '../../upload/style';
|
||||
import type { ComponentToken as CarouselComponentToken } from '../../carousel/style';
|
||||
import type { ComponentToken as SpaceComponentToken } from '../../space/style';
|
||||
|
||||
export const PresetColors = [
|
||||
'blue',
|
||||
@ -42,15 +50,20 @@ export interface OverrideToken {
|
||||
// Customize component
|
||||
Affix?: {};
|
||||
Alert?: {};
|
||||
Anchor?: AnchorComponentToken;
|
||||
Avatar?: {};
|
||||
BackTop?: BackTopComponentToken;
|
||||
Badge?: {};
|
||||
Button?: ButtonComponentToken;
|
||||
Carousel?: {};
|
||||
Carousel?: CarouselComponentToken;
|
||||
Cascader?: CascaderComponentToken;
|
||||
Checkbox?: {};
|
||||
Collapse?: {};
|
||||
DatePicker?: DatePickerComponentToken;
|
||||
Descriptions?: {};
|
||||
Divider?: DividerComponentToken;
|
||||
Drawer?: {};
|
||||
Dropdown?: DropdownComponentToken;
|
||||
Empty?: EmptyComponentToken;
|
||||
Form?: {};
|
||||
Grid?: {};
|
||||
@ -75,6 +88,13 @@ export interface OverrideToken {
|
||||
Typography?: TypographyComponentToken;
|
||||
Timeline?: TimelineComponentToken;
|
||||
Tabs?: {};
|
||||
Card?: {};
|
||||
Steps?: {};
|
||||
Menu?: MenuComponentToken;
|
||||
Layout?: {};
|
||||
Upload?: UploadComponentToken;
|
||||
Tooltip?: {};
|
||||
Space?: SpaceComponentToken;
|
||||
}
|
||||
|
||||
/** Final token which contains the components level override */
|
||||
@ -123,6 +143,7 @@ export interface SeedToken extends PresetColorType {
|
||||
// Size
|
||||
sizeUnit: number;
|
||||
sizeBaseStep: number;
|
||||
sizePopupArrow: number;
|
||||
|
||||
// Control Base
|
||||
controlHeight: number;
|
||||
@ -287,6 +308,8 @@ export interface AliasToken extends Omit<DerivativeToken, OmitDerivativeKey> {
|
||||
colorBgComponentDisabled: string;
|
||||
|
||||
// =============== Legacy: should be remove ===============
|
||||
colorLoadingOpacity: number;
|
||||
|
||||
padding: number;
|
||||
margin: number;
|
||||
|
||||
|
@ -73,9 +73,9 @@ export function derivative(token: SeedToken): DerivativeToken {
|
||||
...colorPalettes,
|
||||
|
||||
// motion
|
||||
motionDurationFast: `${motionBase + motionUnit * 1}s`,
|
||||
motionDurationMid: `${motionBase + motionUnit * 2}s`,
|
||||
motionDurationSlow: `${motionBase + motionUnit * 3}s`,
|
||||
motionDurationFast: `${(motionBase + motionUnit * 1).toFixed(1)}s`,
|
||||
motionDurationMid: `${(motionBase + motionUnit * 2).toFixed(1)}s`,
|
||||
motionDurationSlow: `${(motionBase + motionUnit * 3).toFixed(1)}s`,
|
||||
|
||||
// font
|
||||
fontSizes: fontSizes.map(fs => fs.size),
|
||||
@ -189,6 +189,7 @@ const seedToken: SeedToken = {
|
||||
// Size
|
||||
sizeUnit: 4,
|
||||
sizeBaseStep: 4,
|
||||
sizePopupArrow: 8 * Math.sqrt(2),
|
||||
|
||||
// Control Base
|
||||
controlHeight: 32,
|
||||
|
@ -99,6 +99,8 @@ export default function formatToken(derivativeToken: RawMergedToken): AliasToken
|
||||
// warningColors,
|
||||
// errorColors,
|
||||
|
||||
colorLoadingOpacity: 0.65,
|
||||
|
||||
colorSuccessSecondary: successColors[2],
|
||||
colorWarningSecondary: warningColors[2],
|
||||
colorErrorSecondary: errorColors[2],
|
||||
|
@ -9,16 +9,22 @@ export type OverrideTokenWithoutDerivative = Omit<OverrideToken, 'derivative'>;
|
||||
export type OverrideComponent = keyof OverrideTokenWithoutDerivative;
|
||||
export type GlobalTokenWithComponent<ComponentName extends OverrideComponent> = GlobalToken &
|
||||
OverrideToken[ComponentName];
|
||||
export type StyleInfo = {
|
||||
|
||||
export interface StyleInfo {
|
||||
hashId: string;
|
||||
prefixCls: string;
|
||||
rootPrefixCls: string;
|
||||
iconPrefixCls: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type TokenWithCommonCls<T> = T & {
|
||||
/** Wrap component class with `.` prefix */
|
||||
componentCls: string;
|
||||
/** Origin prefix which do not have `.` prefix */
|
||||
prefixCls: string;
|
||||
/** Wrap icon class with `.` prefix */
|
||||
iconCls: string;
|
||||
/** Wrap ant prefixCls class with `.` prefix */
|
||||
antCls: string;
|
||||
};
|
||||
export type FullToken<ComponentName extends OverrideComponent> = TokenWithCommonCls<
|
||||
@ -38,7 +44,7 @@ function genComponentStyleHook<ComponentName extends OverrideComponent>(
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
|
||||
return [
|
||||
useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => {
|
||||
useStyleRegister({ theme, token, hashId, path: [component, prefixCls] }, () => {
|
||||
const { token: proxyToken, flush } = statisticToken(token);
|
||||
|
||||
const defaultComponentToken =
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { CSSObject } from '@ant-design/cssinjs';
|
||||
import type { DerivativeToken } from '..';
|
||||
|
||||
export { operationUnit } from './operationUnit';
|
||||
export { roundedArrow } from './roundedArrow';
|
||||
|
||||
export const resetComponent = (token: DerivativeToken): CSSObject => ({
|
||||
|
@ -20,7 +20,7 @@ export const roundedArrow = (width: number, outerRadius: number, bgColor: string
|
||||
const ey = fy + outerRadius * (1 / Math.sqrt(2));
|
||||
|
||||
return {
|
||||
borderRadius: `0 0 ${radiusBase}px 0`,
|
||||
borderRadius: { _skip_check_: true, value: `0 0 2px` },
|
||||
pointerEvents: 'none',
|
||||
|
||||
'&::before': {
|
||||
|
@ -1,7 +0,0 @@
|
||||
export default class UnreachableException {
|
||||
error: Error;
|
||||
|
||||
constructor(value: never) {
|
||||
this.error = new Error(`unreachable case: ${JSON.stringify(value)}`);
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import { getObserverEntities } from '../utils';
|
||||
import Button from '../../button';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import accessibilityTest from '../../../tests/shared/accessibilityTest';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
import { sleep, render } from '../../../tests/utils';
|
||||
|
||||
const events: Partial<Record<keyof HTMLElementEventMap, (ev: Partial<Event>) => void>> = {};
|
||||
|
||||
@ -97,57 +97,47 @@ describe('Affix Render', () => {
|
||||
};
|
||||
|
||||
it('Anchor render perfectly', async () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
affixMounterWrapper = mount(<AffixMounter />, { attachTo: document.getElementById('mounter') });
|
||||
const { container } = render(<AffixMounter />);
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(0);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeFalsy();
|
||||
expect(container.querySelector('.ant-affix')).toBeFalsy();
|
||||
|
||||
await movePlaceholder(-100);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
expect(container.querySelector('.ant-affix')).toBeTruthy();
|
||||
|
||||
await movePlaceholder(0);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeFalsy();
|
||||
expect(container.querySelector('.ant-affix')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('support offsetBottom', async () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
|
||||
affixMounterWrapper = mount(<AffixMounter offsetBottom={0} />, {
|
||||
attachTo: document.getElementById('mounter'),
|
||||
});
|
||||
const { container } = render(<AffixMounter offsetBottom={0} />);
|
||||
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(300);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
expect(container.querySelector('.ant-affix')).toBeTruthy();
|
||||
|
||||
await movePlaceholder(0);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeFalsy();
|
||||
expect(container.querySelector('.ant-affix')).toBeFalsy();
|
||||
|
||||
await movePlaceholder(300);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
expect(container.querySelector('.ant-affix')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('updatePosition when offsetTop changed', async () => {
|
||||
document.body.innerHTML = '<div id="mounter" />';
|
||||
const onChange = jest.fn();
|
||||
|
||||
affixMounterWrapper = mount(<AffixMounter offsetTop={0} onChange={onChange} />, {
|
||||
attachTo: document.getElementById('mounter'),
|
||||
});
|
||||
const { container, rerender } = render(<AffixMounter offsetTop={0} onChange={onChange} />);
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(-100);
|
||||
expect(onChange).toHaveBeenLastCalledWith(true);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle?.top).toBe(0);
|
||||
affixMounterWrapper.setProps({
|
||||
offsetTop: 10,
|
||||
});
|
||||
expect(container.querySelector('.ant-affix')).toHaveStyle({ top: 0 });
|
||||
|
||||
rerender(<AffixMounter offsetTop={10} onChange={onChange} />);
|
||||
await sleep(20);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle?.top).toBe(10);
|
||||
expect(container.querySelector('.ant-affix')).toHaveStyle({ top: `10px` });
|
||||
});
|
||||
|
||||
describe('updatePosition when target changed', () => {
|
||||
@ -201,7 +191,9 @@ describe('Affix Render', () => {
|
||||
await sleep(20);
|
||||
|
||||
await movePlaceholder(300);
|
||||
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
|
||||
expect(
|
||||
(affixMounterWrapper.find(AffixMounter).instance() as any).affix.state.affixStyle,
|
||||
).toBeTruthy();
|
||||
await sleep(20);
|
||||
affixMounterWrapper.update();
|
||||
|
||||
|
@ -38,5 +38,5 @@ const Demo: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default () => <Demo />;
|
||||
export default Demo;
|
||||
```
|
||||
|
@ -35,5 +35,5 @@ const Demo: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default () => <Demo />;
|
||||
export default Demo;
|
||||
```
|
||||
|
@ -30,7 +30,7 @@ const Demo: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default () => <Demo />;
|
||||
export default Demo;
|
||||
```
|
||||
|
||||
<style>
|
||||
|
@ -32,5 +32,5 @@ const App: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default () => <App />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -3,12 +3,13 @@ import classNames from 'classnames';
|
||||
import memoizeOne from 'memoize-one';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import Affix from '../affix';
|
||||
import AnchorLink from './AnchorLink';
|
||||
import { ConfigContext, ConfigConsumerProps } from '../config-provider';
|
||||
import scrollTo from '../_util/scrollTo';
|
||||
import getScroll from '../_util/getScroll';
|
||||
import AnchorContext from './context';
|
||||
|
||||
import useStyle from './style';
|
||||
|
||||
export type AnchorContainer = HTMLElement | Window;
|
||||
|
||||
function getDefaultContainer() {
|
||||
@ -62,6 +63,11 @@ export interface AnchorProps {
|
||||
onChange?: (currentActiveLink: string) => void;
|
||||
}
|
||||
|
||||
interface InternalAnchorProps extends AnchorProps {
|
||||
anchorPrefixCls: string;
|
||||
rootClassName: string;
|
||||
}
|
||||
|
||||
export interface AnchorState {
|
||||
activeLink: null | string;
|
||||
}
|
||||
@ -84,9 +90,7 @@ export interface AntAnchor {
|
||||
) => void;
|
||||
}
|
||||
|
||||
export default class Anchor extends React.Component<AnchorProps, AnchorState, ConfigConsumerProps> {
|
||||
static Link: typeof AnchorLink;
|
||||
|
||||
class Anchor extends React.Component<InternalAnchorProps, AnchorState, ConfigConsumerProps> {
|
||||
static defaultProps = {
|
||||
affix: true,
|
||||
showInkInFixed: false,
|
||||
@ -268,9 +272,9 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState, Co
|
||||
);
|
||||
|
||||
render() {
|
||||
const { getPrefixCls, direction } = this.context;
|
||||
const { direction } = this.context;
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
anchorPrefixCls: prefixCls,
|
||||
className = '',
|
||||
style,
|
||||
offsetTop,
|
||||
@ -278,11 +282,10 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState, Co
|
||||
showInkInFixed,
|
||||
children,
|
||||
onClick,
|
||||
rootClassName,
|
||||
} = this.props;
|
||||
const { activeLink } = this.state;
|
||||
|
||||
const prefixCls = getPrefixCls('anchor', customizePrefixCls);
|
||||
|
||||
// To support old version react.
|
||||
// Have to add prefixCls on the instance.
|
||||
// https://github.com/facebook/react/issues/12397
|
||||
@ -293,6 +296,7 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState, Co
|
||||
});
|
||||
|
||||
const wrapperClass = classNames(
|
||||
rootClassName,
|
||||
`${prefixCls}-wrapper`,
|
||||
{
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
@ -335,3 +339,25 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState, Co
|
||||
);
|
||||
}
|
||||
}
|
||||
// just use in test
|
||||
export type InternalAnchorClass = Anchor;
|
||||
|
||||
const AnchorFC = React.forwardRef<Anchor, AnchorProps>((props, ref) => {
|
||||
const { prefixCls: customizePrefixCls } = props;
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
|
||||
const anchorPrefixCls = getPrefixCls('anchor', customizePrefixCls);
|
||||
|
||||
const [wrapSSR, hashId] = useStyle(anchorPrefixCls);
|
||||
|
||||
const anchorProps: InternalAnchorProps = {
|
||||
...props,
|
||||
|
||||
anchorPrefixCls,
|
||||
rootClassName: hashId,
|
||||
};
|
||||
|
||||
return wrapSSR(<Anchor {...anchorProps} ref={ref} />);
|
||||
});
|
||||
|
||||
export default AnchorFC;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Anchor from '..';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
import type { InternalAnchorClass } from '../Anchor';
|
||||
import { sleep, render, fireEvent } from '../../../tests/utils';
|
||||
|
||||
const { Link } = Anchor;
|
||||
|
||||
@ -47,41 +47,54 @@ describe('Anchor Render', () => {
|
||||
|
||||
it('Anchor render perfectly', () => {
|
||||
const hash = getHashUrl();
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { container } = render(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.find(`a[href="#${hash}"]`).simulate('click');
|
||||
|
||||
wrapper.instance().handleScroll();
|
||||
expect(wrapper.instance().state).not.toBe(null);
|
||||
fireEvent.click(container.querySelector(`a[href="#${hash}"]`)!);
|
||||
anchorInstance!.handleScroll();
|
||||
expect(anchorInstance!.state).not.toBe(null);
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - click', () => {
|
||||
const hash = getHashUrl();
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { container } = render(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`http://www.example.com/#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.find(`a[href="http://www.example.com/#${hash}"]`).simulate('click');
|
||||
expect(wrapper.instance().state.activeLink).toBe(`http://www.example.com/#${hash}`);
|
||||
fireEvent.click(container.querySelector(`a[href="http://www.example.com/#${hash}"]`)!);
|
||||
expect(anchorInstance!.state!.activeLink).toBe(`http://www.example.com/#${hash}`);
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - hash router', async () => {
|
||||
const root = createDiv();
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
mount(<div id="/faq?locale=en#Q1">Q1</div>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
render(<div id="/faq?locale=en#Q1">Q1</div>, { container: root });
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
render(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href="/#/faq?locale=en#Q1" title="Q1" />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.instance().handleScrollTo('/#/faq?locale=en#Q1');
|
||||
expect(wrapper.instance().state.activeLink).toBe('/#/faq?locale=en#Q1');
|
||||
anchorInstance!.handleScrollTo('/#/faq?locale=en#Q1');
|
||||
expect(anchorInstance!.state.activeLink).toBe('/#/faq?locale=en#Q1');
|
||||
expect(scrollToSpy).not.toHaveBeenCalled();
|
||||
await sleep(1000);
|
||||
expect(scrollToSpy).toHaveBeenCalled();
|
||||
@ -90,28 +103,39 @@ describe('Anchor Render', () => {
|
||||
it('Anchor render perfectly for complete href - scroll', () => {
|
||||
const hash = getHashUrl();
|
||||
const root = createDiv();
|
||||
mount(<div id={hash}>Hello</div>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
render(<div id={hash}>Hello</div>, { container: root });
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
render(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`http://www.example.com/#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScroll();
|
||||
expect(wrapper.instance().state.activeLink).toBe(`http://www.example.com/#${hash}`);
|
||||
anchorInstance!.handleScroll();
|
||||
expect(anchorInstance!.state!.activeLink).toBe(`http://www.example.com/#${hash}`);
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - scrollTo', async () => {
|
||||
const hash = getHashUrl();
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
const root = createDiv();
|
||||
mount(<div id={`#${hash}`}>Hello</div>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
render(<div id={`#${hash}`}>Hello</div>, { container: root });
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
render(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`##${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo(`##${hash}`);
|
||||
expect(wrapper.instance().state.activeLink).toBe(`##${hash}`);
|
||||
|
||||
anchorInstance!.handleScrollTo(`##${hash}`);
|
||||
expect(anchorInstance!.state.activeLink).toBe(`##${hash}`);
|
||||
const calls = scrollToSpy.mock.calls.length;
|
||||
await sleep(1000);
|
||||
expect(scrollToSpy.mock.calls.length).toBeGreaterThan(calls);
|
||||
@ -119,50 +143,60 @@ describe('Anchor Render', () => {
|
||||
|
||||
it('should remove listener when unmount', async () => {
|
||||
const hash = getHashUrl();
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { unmount } = render(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||
wrapper.unmount();
|
||||
|
||||
const removeListenerSpy = jest.spyOn((anchorInstance! as any).scrollEvent, 'remove');
|
||||
unmount();
|
||||
expect(removeListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should unregister link when unmount children', async () => {
|
||||
it('should unregister link when unmount children', () => {
|
||||
const hash = getHashUrl();
|
||||
const wrapper = mount<Anchor>(
|
||||
const { container, rerender } = render(
|
||||
<Anchor>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
expect((wrapper.instance() as any).links).toEqual([`#${hash}`]);
|
||||
wrapper.setProps({ children: null });
|
||||
expect((wrapper.instance() as any).links).toEqual([]);
|
||||
|
||||
expect(container.querySelectorAll('.ant-anchor-link-title')).toHaveLength(1);
|
||||
expect(container.querySelector('.ant-anchor-link-title')).toHaveAttribute('href', `#${hash}`);
|
||||
|
||||
rerender(<Anchor />);
|
||||
expect(container.querySelector('.ant-anchor-link-title')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should update links when link href update', async () => {
|
||||
const hash = getHashUrl();
|
||||
let anchorInstance: Anchor | null = null;
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
function AnchorUpdate({ href }: { href: string }) {
|
||||
return (
|
||||
<Anchor
|
||||
ref={c => {
|
||||
anchorInstance = c;
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={href} title={hash} />
|
||||
</Anchor>
|
||||
);
|
||||
}
|
||||
const wrapper = mount(<AnchorUpdate href={`#${hash}`} />);
|
||||
const { rerender } = render(<AnchorUpdate href={`#${hash}`} />);
|
||||
|
||||
if (anchorInstance == null) {
|
||||
if (anchorInstance! == null) {
|
||||
throw new Error('anchorInstance should not be null');
|
||||
}
|
||||
expect((anchorInstance as any).links).toEqual([`#${hash}`]);
|
||||
wrapper.setProps({ href: `#${hash}_1` });
|
||||
expect((anchorInstance as any).links).toEqual([`#${hash}_1`]);
|
||||
|
||||
expect((anchorInstance as any)!.links).toEqual([`#${hash}`]);
|
||||
rerender(<AnchorUpdate href={`#${hash}_1`} />);
|
||||
expect((anchorInstance as any)!.links).toEqual([`#${hash}_1`]);
|
||||
});
|
||||
|
||||
it('Anchor onClick event', () => {
|
||||
@ -179,16 +213,20 @@ describe('Anchor Render', () => {
|
||||
|
||||
const href = `#${hash}`;
|
||||
const title = hash;
|
||||
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor onClick={handleClick}>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { container } = render(
|
||||
<Anchor
|
||||
onClick={handleClick}
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={href} title={title} />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.find(`a[href="${href}"]`).simulate('click');
|
||||
|
||||
wrapper.instance().handleScroll();
|
||||
fireEvent.click(container.querySelector(`a[href="${href}"]`)!);
|
||||
anchorInstance!.handleScroll();
|
||||
expect(event).not.toBe(undefined);
|
||||
expect(link).toEqual({ href, title });
|
||||
});
|
||||
@ -196,18 +234,28 @@ describe('Anchor Render', () => {
|
||||
it('Different function returns the same DOM', async () => {
|
||||
const hash = getHashUrl();
|
||||
const root = createDiv();
|
||||
mount(<div id={hash}>Hello</div>, { attachTo: root });
|
||||
render(<div id={hash}>Hello</div>, { container: root });
|
||||
const getContainerA = createGetContainer(hash);
|
||||
const getContainerB = createGetContainer(hash);
|
||||
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor getContainer={getContainerA}>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { rerender } = render(
|
||||
<Anchor
|
||||
getContainer={getContainerA}
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||
|
||||
const removeListenerSpy = jest.spyOn((anchorInstance! as any).scrollEvent, 'remove');
|
||||
await sleep(1000);
|
||||
wrapper.setProps({ getContainer: getContainerB });
|
||||
rerender(
|
||||
<Anchor getContainer={getContainerB}>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@ -215,53 +263,73 @@ describe('Anchor Render', () => {
|
||||
const hash1 = getHashUrl();
|
||||
const hash2 = getHashUrl();
|
||||
const root = createDiv();
|
||||
mount(
|
||||
render(
|
||||
<div>
|
||||
<div id={hash1}>Hello</div>
|
||||
<div id={hash2}>World</div>
|
||||
</div>,
|
||||
{ attachTo: root },
|
||||
{ container: root },
|
||||
);
|
||||
const getContainerA = createGetContainer(hash1);
|
||||
const getContainerB = createGetContainer(hash2);
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor getContainer={getContainerA}>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { rerender } = render(
|
||||
<Anchor
|
||||
getContainer={getContainerA}
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||
|
||||
const removeListenerSpy = jest.spyOn((anchorInstance! as any).scrollEvent, 'remove');
|
||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||
await sleep(1000);
|
||||
wrapper.setProps({ getContainer: getContainerB });
|
||||
rerender(
|
||||
<Anchor getContainer={getContainerB}>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
);
|
||||
expect(removeListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Same function returns the same DOM', () => {
|
||||
const hash = getHashUrl();
|
||||
const root = createDiv();
|
||||
mount(<div id={hash}>Hello</div>, { attachTo: root });
|
||||
render(<div id={hash}>Hello</div>, { container: root });
|
||||
const getContainer = createGetContainer(hash);
|
||||
const wrapper = mount(
|
||||
<Anchor getContainer={getContainer}>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { container } = render(
|
||||
<Anchor
|
||||
getContainer={getContainer}
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.find(`a[href="#${hash}"]`).simulate('click');
|
||||
(wrapper.instance() as any).handleScroll();
|
||||
expect(wrapper.instance().state).not.toBe(null);
|
||||
|
||||
fireEvent.click(container.querySelector(`a[href="#${hash}"]`)!);
|
||||
|
||||
anchorInstance!.handleScroll();
|
||||
expect(anchorInstance!.state).not.toBe(null);
|
||||
});
|
||||
|
||||
it('Same function returns different DOM', async () => {
|
||||
const hash1 = getHashUrl();
|
||||
const hash2 = getHashUrl();
|
||||
const root = createDiv();
|
||||
mount(
|
||||
render(
|
||||
<div>
|
||||
<div id={hash1}>Hello</div>
|
||||
<div id={hash2}>World</div>
|
||||
</div>,
|
||||
{ attachTo: root },
|
||||
{ container: root },
|
||||
);
|
||||
const holdContainer = {
|
||||
container: document.getElementById(hash1),
|
||||
@ -272,17 +340,28 @@ describe('Anchor Render', () => {
|
||||
}
|
||||
return holdContainer.container;
|
||||
};
|
||||
const wrapper = mount(
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { rerender } = render(
|
||||
<Anchor
|
||||
getContainer={getContainer}
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn((anchorInstance! as any).scrollEvent, 'remove');
|
||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||
await sleep(1000);
|
||||
holdContainer.container = document.getElementById(hash2);
|
||||
rerender(
|
||||
<Anchor getContainer={getContainer}>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
);
|
||||
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||
await sleep(1000);
|
||||
holdContainer.container = document.getElementById(hash2);
|
||||
wrapper.setProps({ 'data-only-trigger-re-render': true });
|
||||
expect(removeListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@ -305,25 +384,45 @@ describe('Anchor Render', () => {
|
||||
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
const root = createDiv();
|
||||
mount(<h1 id={hash}>Hello</h1>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
render(<h1 id={hash}>Hello</h1>, { container: root });
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { rerender } = render(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
|
||||
const setProps = (props: Record<string, any>) =>
|
||||
rerender(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ offsetTop: 100 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
setProps({ offsetTop: 100 });
|
||||
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ targetOffset: 200 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
setProps({ targetOffset: 200 });
|
||||
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
|
||||
@ -350,25 +449,43 @@ describe('Anchor Render', () => {
|
||||
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
const root = createDiv();
|
||||
mount(<h1 id={hash}>Hello</h1>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
render(<h1 id={hash}>Hello</h1>, { container: root });
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { rerender } = render(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
|
||||
const setProps = (props: Record<string, any>) =>
|
||||
rerender(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ offsetTop: 100 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
setProps({ offsetTop: 100 });
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ targetOffset: 200 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
setProps({ targetOffset: 200 });
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
|
||||
@ -379,29 +496,44 @@ describe('Anchor Render', () => {
|
||||
const hash1 = getHashUrl();
|
||||
const hash2 = getHashUrl();
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor onChange={onChange}>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
render(
|
||||
<Anchor
|
||||
onChange={onChange}
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
// https://github.com/testing-library/react-testing-library/releases/tag/v13.0.0
|
||||
// @ts-ignore
|
||||
{ legacyRoot: true },
|
||||
);
|
||||
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
wrapper.instance().handleScrollTo(hash2);
|
||||
anchorInstance!.handleScrollTo(hash2);
|
||||
expect(onChange).toHaveBeenCalledTimes(2);
|
||||
expect(onChange).toHaveBeenCalledWith(hash2);
|
||||
});
|
||||
|
||||
it('invalid hash', async () => {
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { container } = render(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href="notexsited" title="title" />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.find(`a[href="notexsited"]`).simulate('click');
|
||||
fireEvent.click(container.querySelector(`a[href="notexsited"]`)!);
|
||||
|
||||
wrapper.instance().handleScrollTo('notexsited');
|
||||
expect(wrapper.instance().state).not.toBe(null);
|
||||
anchorInstance!.handleScrollTo('notexsited');
|
||||
expect(anchorInstance!.state).not.toBe(null);
|
||||
});
|
||||
|
||||
it('test edge case when getBoundingClientRect return zero size', async () => {
|
||||
@ -428,25 +560,42 @@ describe('Anchor Render', () => {
|
||||
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
const root = createDiv();
|
||||
mount(<h1 id={hash}>Hello</h1>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor>
|
||||
render(<h1 id={hash}>Hello</h1>, { container: root });
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { rerender } = render(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
|
||||
const setProps = (props: Record<string, any>) =>
|
||||
rerender(
|
||||
<Anchor
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ offsetTop: 100 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
setProps({ offsetTop: 100 });
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ targetOffset: 200 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
setProps({ targetOffset: 200 });
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
|
||||
@ -477,25 +626,44 @@ describe('Anchor Render', () => {
|
||||
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||
const root = createDiv();
|
||||
mount(<h1 id={hash}>Hello</h1>, { attachTo: root });
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor getContainer={() => document.body}>
|
||||
render(<h1 id={hash}>Hello</h1>, { container: root });
|
||||
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
const { rerender } = render(
|
||||
<Anchor
|
||||
getContainer={() => document.body}
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
|
||||
const setProps = (props: Record<string, any>) =>
|
||||
rerender(
|
||||
<Anchor
|
||||
getContainer={() => document.body}
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<Link href={`#${hash}`} title={hash} />
|
||||
</Anchor>,
|
||||
);
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ offsetTop: 100 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
setProps({ offsetTop: 100 });
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
dateNowMock = dataNowMockFn();
|
||||
|
||||
wrapper.setProps({ targetOffset: 200 });
|
||||
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||
setProps({ targetOffset: 200 });
|
||||
anchorInstance!.handleScrollTo(`#${hash}`);
|
||||
await sleep(30);
|
||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||
|
||||
@ -507,13 +675,20 @@ describe('Anchor Render', () => {
|
||||
const hash1 = getHashUrl();
|
||||
const hash2 = getHashUrl();
|
||||
const getCurrentAnchor = () => `#${hash2}`;
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor getCurrentAnchor={getCurrentAnchor}>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
render(
|
||||
<Anchor
|
||||
getCurrentAnchor={getCurrentAnchor}
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
);
|
||||
expect(wrapper.instance().state.activeLink).toBe(`#${hash2}`);
|
||||
|
||||
expect(anchorInstance!.state.activeLink).toBe(`#${hash2}`);
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/30584
|
||||
@ -521,14 +696,25 @@ describe('Anchor Render', () => {
|
||||
const hash1 = getHashUrl();
|
||||
const hash2 = getHashUrl();
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount<Anchor>(
|
||||
<Anchor onChange={onChange} getCurrentAnchor={() => hash1}>
|
||||
let anchorInstance: InternalAnchorClass;
|
||||
render(
|
||||
<Anchor
|
||||
onChange={onChange}
|
||||
getCurrentAnchor={() => hash1}
|
||||
ref={node => {
|
||||
anchorInstance = node as InternalAnchorClass;
|
||||
}}
|
||||
>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
// https://github.com/testing-library/react-testing-library/releases/tag/v13.0.0
|
||||
// @ts-ignore
|
||||
{ legacyRoot: true },
|
||||
);
|
||||
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
wrapper.instance().handleScrollTo(hash2);
|
||||
anchorInstance!.handleScrollTo(hash2);
|
||||
expect(onChange).toHaveBeenCalledTimes(2);
|
||||
expect(onChange).toHaveBeenCalledWith(hash2);
|
||||
});
|
||||
@ -538,16 +724,16 @@ describe('Anchor Render', () => {
|
||||
const hash1 = getHashUrl();
|
||||
const hash2 = getHashUrl();
|
||||
const getCurrentAnchor = jest.fn();
|
||||
const wrapper = mount<Anchor>(
|
||||
const { container } = render(
|
||||
<Anchor getCurrentAnchor={getCurrentAnchor}>
|
||||
<Link href={`#${hash1}`} title={hash1} />
|
||||
<Link href={`#${hash2}`} title={hash2} />
|
||||
</Anchor>,
|
||||
);
|
||||
|
||||
wrapper.find(`a[href="#${hash1}"]`).simulate('click');
|
||||
fireEvent.click(container.querySelector(`a[href="#${hash1}"]`)!);
|
||||
expect(getCurrentAnchor).toHaveBeenCalledWith(`#${hash1}`);
|
||||
wrapper.find(`a[href="#${hash2}"]`).simulate('click');
|
||||
fireEvent.click(container.querySelector(`a[href="#${hash2}"]`)!);
|
||||
expect(getCurrentAnchor).toHaveBeenCalledWith(`#${hash2}`);
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { memo, useState, useRef, useContext } from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Anchor from '../Anchor';
|
||||
import AnchorContext from '../context';
|
||||
import { getNodeText, render, fireEvent } from '../../../tests/utils';
|
||||
|
||||
// we use'memo' here in order to only render inner component while context changed.
|
||||
const CacheInner = memo(() => {
|
||||
@ -38,14 +38,16 @@ const CacheOuter = () => {
|
||||
};
|
||||
|
||||
it("Rendering on Anchor without changed AnchorContext won't trigger rendering on child component.", () => {
|
||||
const wrapper = mount(<CacheOuter />);
|
||||
const childCount = wrapper.find('#child_count').text();
|
||||
wrapper.find('#parent_btn').at(0).simulate('click');
|
||||
expect(wrapper.find('#parent_count').text()).toBe('2');
|
||||
const { container } = render(<CacheOuter />);
|
||||
const childCount = getNodeText(container.querySelector('#child_count')!);
|
||||
|
||||
fireEvent.click(container.querySelector('#parent_btn')!);
|
||||
|
||||
expect(getNodeText(container.querySelector('#parent_count')!)).toBe('2');
|
||||
// child component won't rerender
|
||||
expect(wrapper.find('#child_count').text()).toBe(childCount);
|
||||
wrapper.find('#parent_btn').at(0).simulate('click');
|
||||
expect(wrapper.find('#parent_count').text()).toBe('3');
|
||||
expect(getNodeText(container.querySelector('#child_count')!)).toBe(childCount);
|
||||
fireEvent.click(container.querySelector('#parent_btn')!);
|
||||
expect(getNodeText(container.querySelector('#parent_count')!)).toBe('3');
|
||||
// child component won't rerender
|
||||
expect(wrapper.find('#child_count').text()).toBe(childCount);
|
||||
expect(getNodeText(container.querySelector('#child_count')!)).toBe(childCount);
|
||||
});
|
||||
|
@ -1,8 +1,16 @@
|
||||
import Anchor from './Anchor';
|
||||
import InternalAnchor from './Anchor';
|
||||
import AnchorLink from './AnchorLink';
|
||||
|
||||
export { AnchorProps } from './Anchor';
|
||||
export { AnchorLinkProps } from './AnchorLink';
|
||||
|
||||
type InternalAnchorType = typeof InternalAnchor;
|
||||
|
||||
interface AnchorInterface extends InternalAnchorType {
|
||||
Link: typeof AnchorLink;
|
||||
}
|
||||
|
||||
const Anchor = InternalAnchor as AnchorInterface;
|
||||
|
||||
Anchor.Link = AnchorLink;
|
||||
export default Anchor;
|
||||
|
@ -1,87 +1,87 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
// @import '../../style/themes/index';
|
||||
// @import '../../style/mixins/index';
|
||||
|
||||
@anchor-border-width: 2px;
|
||||
// @anchor-border-width: 2px;
|
||||
|
||||
.@{ant-prefix}-anchor {
|
||||
.reset-component();
|
||||
// .@{ant-prefix}-anchor {
|
||||
// .reset-component();
|
||||
|
||||
position: relative;
|
||||
padding-left: @anchor-border-width;
|
||||
// position: relative;
|
||||
// padding-left: @anchor-border-width;
|
||||
|
||||
&-wrapper {
|
||||
margin-left: -4px;
|
||||
padding-left: 4px;
|
||||
overflow: auto;
|
||||
background-color: @anchor-bg;
|
||||
}
|
||||
// &-wrapper {
|
||||
// margin-left: -4px;
|
||||
// padding-left: 4px;
|
||||
// overflow: auto;
|
||||
// background-color: @anchor-bg;
|
||||
// }
|
||||
|
||||
&-ink {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
// &-ink {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// height: 100%;
|
||||
|
||||
&::before {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: @anchor-border-width;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
background-color: @anchor-border-color;
|
||||
content: ' ';
|
||||
}
|
||||
// &::before {
|
||||
// position: relative;
|
||||
// display: block;
|
||||
// width: @anchor-border-width;
|
||||
// height: 100%;
|
||||
// margin: 0 auto;
|
||||
// background-color: @anchor-border-color;
|
||||
// content: ' ';
|
||||
// }
|
||||
|
||||
&-ball {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
display: none;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: @component-background;
|
||||
border: 2px solid @primary-color;
|
||||
border-radius: 8px;
|
||||
transform: translateX(-50%);
|
||||
transition: top 0.3s ease-in-out;
|
||||
// &-ball {
|
||||
// position: absolute;
|
||||
// left: 50%;
|
||||
// display: none;
|
||||
// width: 8px;
|
||||
// height: 8px;
|
||||
// background-color: @component-background;
|
||||
// border: 2px solid @primary-color;
|
||||
// border-radius: 8px;
|
||||
// transform: translateX(-50%);
|
||||
// transition: top 0.3s ease-in-out;
|
||||
|
||||
&.visible {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
// &.visible {
|
||||
// display: inline-block;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
&-fixed &-ink &-ink-ball {
|
||||
display: none;
|
||||
}
|
||||
// &-fixed &-ink &-ink-ball {
|
||||
// display: none;
|
||||
// }
|
||||
|
||||
&-link {
|
||||
padding: @anchor-link-padding;
|
||||
line-height: 1.143;
|
||||
// &-link {
|
||||
// padding: @anchor-link-padding;
|
||||
// line-height: 1.143;
|
||||
|
||||
&-title {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
overflow: hidden;
|
||||
color: @text-color;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
transition: all 0.3s;
|
||||
// &-title {
|
||||
// position: relative;
|
||||
// display: block;
|
||||
// margin-bottom: 6px;
|
||||
// overflow: hidden;
|
||||
// color: @text-color;
|
||||
// white-space: nowrap;
|
||||
// text-overflow: ellipsis;
|
||||
// transition: all 0.3s;
|
||||
|
||||
&:only-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
// &:only-child {
|
||||
// margin-bottom: 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-active > &-title {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
// &-active > &-title {
|
||||
// color: @primary-color;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-link &-link {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
// &-link &-link {
|
||||
// padding-top: 5px;
|
||||
// padding-bottom: 5px;
|
||||
// }
|
||||
// }
|
||||
|
||||
@import './rtl';
|
||||
// @import './rtl';
|
||||
|
@ -1,5 +1,124 @@
|
||||
import '../../style/index.less';
|
||||
import './index.less';
|
||||
// deps-lint-skip-all
|
||||
import { CSSObject } from '@ant-design/cssinjs';
|
||||
import { genComponentStyleHook, mergeToken, resetComponent } from '../../_util/theme';
|
||||
import type { GenerateStyle, FullToken } from '../../_util/theme';
|
||||
|
||||
// style dependencies
|
||||
import '../../affix/style';
|
||||
export interface ComponentToken {}
|
||||
interface AnchorToken extends FullToken<'Anchor'> {
|
||||
anchorLinkTop: number;
|
||||
anchorLinkLeft: number;
|
||||
}
|
||||
|
||||
// ============================== Shared ==============================
|
||||
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
||||
const { componentCls } = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-wrapper`]: {
|
||||
// FIX ME
|
||||
marginBlockStart: -4,
|
||||
// FIX ME
|
||||
paddingBlockStart: 4,
|
||||
|
||||
// delete overflow: auto
|
||||
// overflow: 'auto',
|
||||
|
||||
// @anchor-bg
|
||||
backgroundColor: 'transparent',
|
||||
|
||||
[componentCls]: {
|
||||
...resetComponent(token),
|
||||
position: 'relative',
|
||||
// FIX ME @anchor-border-width
|
||||
paddingInlineStart: 2,
|
||||
|
||||
[`${componentCls}-ink`]: {
|
||||
position: 'absolute',
|
||||
// top: 0
|
||||
insetBlockStart: 0,
|
||||
// left: 0
|
||||
insetInlineStart: 0,
|
||||
height: '100%',
|
||||
|
||||
'&::before': {
|
||||
position: 'relative',
|
||||
display: 'block',
|
||||
// FIX ME
|
||||
width: 2,
|
||||
height: '100%',
|
||||
margin: '0 auto',
|
||||
// FIX ME @border-color-split
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.06)',
|
||||
content: '" "',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-ink-ball`]: {
|
||||
position: 'absolute',
|
||||
// left 50%
|
||||
insetInlineStart: '50%',
|
||||
display: 'none',
|
||||
// FIX ME
|
||||
width: 8,
|
||||
// FIX ME
|
||||
height: 8,
|
||||
// FIX '@component-background'
|
||||
backgroundColor: '#fff',
|
||||
border: `2px solid ${token.colorPrimary}`,
|
||||
borderRadius: 8,
|
||||
transform: 'translateX(-50%)',
|
||||
transition: `top ${token.motionDurationSlow} ease-in-out`,
|
||||
|
||||
'&.visible': {
|
||||
display: 'inline-block',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-link`]: {
|
||||
// FIX ME @anchor-link-padding
|
||||
paddingBlock: token.anchorLinkTop,
|
||||
paddingInline: `${token.anchorLinkLeft}px 0`,
|
||||
lineHeight: '1.143',
|
||||
|
||||
'&-title': {
|
||||
position: 'relative',
|
||||
display: 'block',
|
||||
// FIX ME margin-bottom
|
||||
marginBlockEnd: 6,
|
||||
overflow: 'hidden',
|
||||
color: token.colorText,
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
transition: `all ${token.motionDurationSlow}s`,
|
||||
|
||||
'&:only-child': {
|
||||
marginBlockEnd: 0,
|
||||
},
|
||||
},
|
||||
|
||||
[`&-active > ${componentCls}-link-title`]: {
|
||||
color: token.colorPrimary,
|
||||
},
|
||||
|
||||
// link link
|
||||
[`${componentCls}-link`]: {
|
||||
paddingBlock: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-fixed ${componentCls}-ink ${componentCls}-ink-ball`]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook('Anchor', token => {
|
||||
const anchorToken = mergeToken<AnchorToken>(token, {
|
||||
anchorLinkTop: 7,
|
||||
anchorLinkLeft: 16,
|
||||
});
|
||||
return [genSharedAnchorStyle(anchorToken)];
|
||||
});
|
||||
|
@ -34,7 +34,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -80,7 +80,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -163,7 +163,7 @@ exports[`renders ./components/auto-complete/demo/certain-category.md extend cont
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown certain-category-search-dropdown"
|
||||
style="opacity:0;pointer-events:none;width:500px"
|
||||
style="opacity:0;width:500px"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -501,7 +501,7 @@ exports[`renders ./components/auto-complete/demo/custom.md extend context correc
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -571,7 +571,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -640,7 +640,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-tree-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -785,7 +785,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-tree-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -898,7 +898,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -993,7 +993,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1066,7 +1066,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-tree-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1206,7 +1206,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1280,7 +1280,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-tree-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1429,7 +1429,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1503,7 +1503,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-tree-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1652,7 +1652,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1732,7 +1732,7 @@ exports[`renders ./components/auto-complete/demo/non-case-sensitive.md extend co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1862,7 +1862,7 @@ exports[`renders ./components/auto-complete/demo/options.md extend context corre
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1915,7 +1915,7 @@ exports[`renders ./components/auto-complete/demo/status.md extend context correc
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1961,7 +1961,7 @@ exports[`renders ./components/auto-complete/demo/status.md extend context correc
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -2045,7 +2045,7 @@ exports[`renders ./components/auto-complete/demo/uncertain-category.md extend co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none;width:252px"
|
||||
style="opacity:0;width:252px"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
|
@ -32,7 +32,7 @@ exports[`AutoComplete legacy dataSource should accept react element option 1`] =
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: 0; width: 0px;"
|
||||
style="opacity: 0; min-width: 0; width: 0px;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
|
@ -2,8 +2,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { mount } from 'enzyme';
|
||||
import { render } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
import Avatar from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
@ -88,7 +87,7 @@ describe('Avatar Render', () => {
|
||||
// https://github.com/jsdom/jsdom/issues/1816
|
||||
wrapper.find('img').simulate('error');
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(div.querySelector('img').getAttribute('src')).toBe(LOAD_SUCCESS_SRC);
|
||||
|
||||
wrapper.detach();
|
||||
@ -106,7 +105,7 @@ describe('Avatar Render', () => {
|
||||
const wrapper = mount(<Avatar src={LOAD_FAILURE_SRC}>Fallback</Avatar>, { attachTo: div });
|
||||
wrapper.find('img').simulate('error');
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapper.find('.ant-avatar-string').length).toBe(1);
|
||||
// children should show, when image load error without onError return false
|
||||
expect(wrapper.find('.ant-avatar-string').prop('style')).not.toHaveProperty('opacity', 0);
|
||||
@ -115,7 +114,7 @@ describe('Avatar Render', () => {
|
||||
wrapper.setProps({ src: LOAD_SUCCESS_SRC });
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapper.find('.ant-avatar-image').length).toBe(1);
|
||||
|
||||
// cleanup
|
||||
@ -124,8 +123,8 @@ describe('Avatar Render', () => {
|
||||
});
|
||||
|
||||
it('should calculate scale of avatar children correctly', () => {
|
||||
const wrapper = mount(<Avatar>Avatar</Avatar>);
|
||||
expect(wrapper.find('.ant-avatar-string')).toMatchSnapshot();
|
||||
const { container, rerender } = render(<Avatar>Avatar</Avatar>);
|
||||
expect(container.querySelector('.ant-avatar-string')).toMatchSnapshot();
|
||||
|
||||
Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {
|
||||
get() {
|
||||
@ -135,13 +134,14 @@ describe('Avatar Render', () => {
|
||||
return 40;
|
||||
},
|
||||
});
|
||||
wrapper.setProps({ children: 'xx' });
|
||||
expect(wrapper.find('.ant-avatar-string')).toMatchSnapshot();
|
||||
|
||||
rerender(<Avatar>xx</Avatar>);
|
||||
expect(container.querySelector('.ant-avatar-string')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should calculate scale of avatar children correctly with gap', () => {
|
||||
const wrapper = mount(<Avatar gap={2}>Avatar</Avatar>);
|
||||
expect(wrapper.find('.ant-avatar-string')).toMatchSnapshot();
|
||||
expect(wrapper.find('.ant-avatar-string').render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should warning when pass a string as icon props', () => {
|
||||
@ -176,8 +176,8 @@ describe('Avatar Render', () => {
|
||||
|
||||
it('support onMouseEnter', () => {
|
||||
const onMouseEnter = jest.fn();
|
||||
const wrapper = mount(<Avatar onMouseEnter={onMouseEnter}>TestString</Avatar>);
|
||||
wrapper.simulate('mouseenter');
|
||||
const { container } = render(<Avatar onMouseEnter={onMouseEnter}>TestString</Avatar>);
|
||||
fireEvent.mouseEnter(container.firstChild);
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
@ -110,14 +110,8 @@ exports[`Avatar Render rtl render component should be rendered correctly in RTL
|
||||
|
||||
exports[`Avatar Render should calculate scale of avatar children correctly 1`] = `
|
||||
<span
|
||||
className="ant-avatar-string"
|
||||
style={
|
||||
Object {
|
||||
"WebkitTransform": "scale(0.72) translateX(-50%)",
|
||||
"msTransform": "scale(0.72) translateX(-50%)",
|
||||
"transform": "scale(0.72) translateX(-50%)",
|
||||
}
|
||||
}
|
||||
class="ant-avatar-string"
|
||||
style="transform: scale(0.72) translateX(-50%);"
|
||||
>
|
||||
Avatar
|
||||
</span>
|
||||
@ -125,14 +119,8 @@ exports[`Avatar Render should calculate scale of avatar children correctly 1`] =
|
||||
|
||||
exports[`Avatar Render should calculate scale of avatar children correctly 2`] = `
|
||||
<span
|
||||
className="ant-avatar-string"
|
||||
style={
|
||||
Object {
|
||||
"WebkitTransform": "scale(0.72) translateX(-50%)",
|
||||
"msTransform": "scale(0.72) translateX(-50%)",
|
||||
"transform": "scale(0.72) translateX(-50%)",
|
||||
}
|
||||
}
|
||||
class="ant-avatar-string"
|
||||
style="transform: scale(0.72) translateX(-50%);"
|
||||
>
|
||||
xx
|
||||
</span>
|
||||
@ -140,93 +128,44 @@ exports[`Avatar Render should calculate scale of avatar children correctly 2`] =
|
||||
|
||||
exports[`Avatar Render should calculate scale of avatar children correctly with gap 1`] = `
|
||||
<span
|
||||
className="ant-avatar-string"
|
||||
style={
|
||||
Object {
|
||||
"WebkitTransform": "scale(0.36) translateX(-50%)",
|
||||
"msTransform": "scale(0.36) translateX(-50%)",
|
||||
"transform": "scale(0.36) translateX(-50%)",
|
||||
}
|
||||
}
|
||||
class="ant-avatar-string"
|
||||
style="transform: scale(0.36) translateX(-50%);"
|
||||
>
|
||||
Avatar
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Avatar Render should handle onError correctly 1`] = `
|
||||
<Foo>
|
||||
<Avatar
|
||||
onError={[Function]}
|
||||
shape="circle"
|
||||
size="default"
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-image"
|
||||
>
|
||||
<img
|
||||
src="https://joeschmoe.io/api/v1/random"
|
||||
>
|
||||
<span
|
||||
className="ant-avatar ant-avatar-circle ant-avatar-image"
|
||||
style={Object {}}
|
||||
>
|
||||
<img
|
||||
onError={[Function]}
|
||||
src="https://joeschmoe.io/api/v1/random"
|
||||
/>
|
||||
</span>
|
||||
</Avatar>
|
||||
</Foo>
|
||||
/>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Avatar Render should show image on success after a failure state 1`] = `
|
||||
<Avatar
|
||||
shape="circle"
|
||||
size="default"
|
||||
src="http://error.url"
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
>
|
||||
<span
|
||||
className="ant-avatar ant-avatar-circle"
|
||||
style={Object {}}
|
||||
class="ant-avatar-string"
|
||||
style="transform: scale(1) translateX(-50%);"
|
||||
>
|
||||
<ResizeObserver
|
||||
onResize={[Function]}
|
||||
>
|
||||
<SingleObserver
|
||||
key="rc-observer-key-0"
|
||||
onResize={[Function]}
|
||||
>
|
||||
<DomWrapper>
|
||||
<span
|
||||
className="ant-avatar-string"
|
||||
style={
|
||||
Object {
|
||||
"WebkitTransform": "scale(1) translateX(-50%)",
|
||||
"msTransform": "scale(1) translateX(-50%)",
|
||||
"transform": "scale(1) translateX(-50%)",
|
||||
}
|
||||
}
|
||||
>
|
||||
Fallback
|
||||
</span>
|
||||
</DomWrapper>
|
||||
</SingleObserver>
|
||||
</ResizeObserver>
|
||||
Fallback
|
||||
</span>
|
||||
</Avatar>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Avatar Render should show image on success after a failure state 2`] = `
|
||||
<Avatar
|
||||
shape="circle"
|
||||
size="default"
|
||||
src="https://joeschmoe.io/api/v1/random"
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-image"
|
||||
>
|
||||
<span
|
||||
className="ant-avatar ant-avatar-circle ant-avatar-image"
|
||||
style={Object {}}
|
||||
>
|
||||
<img
|
||||
onError={[Function]}
|
||||
src="https://joeschmoe.io/api/v1/random"
|
||||
/>
|
||||
</span>
|
||||
</Avatar>
|
||||
<img
|
||||
src="https://joeschmoe.io/api/v1/random"
|
||||
/>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Avatar Render support size is number 1`] = `
|
||||
|
@ -383,7 +383,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -468,7 +468,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-popover ant-avatar-group-popover"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-popover-content"
|
||||
@ -514,7 +514,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -604,7 +604,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-popover ant-avatar-group-popover"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-popover-content"
|
||||
@ -650,7 +650,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -740,7 +740,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-popover ant-avatar-group-popover"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-popover-content"
|
||||
@ -786,7 +786,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
|
@ -66,5 +66,5 @@ const Demo = () => (
|
||||
</>
|
||||
);
|
||||
|
||||
export default () => <Demo />;
|
||||
export default Demo;
|
||||
```
|
||||
|
@ -71,5 +71,5 @@ const App: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default () => <App />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -11,6 +11,8 @@ import getScroll from '../_util/getScroll';
|
||||
import scrollTo from '../_util/scrollTo';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
|
||||
import useStyle from './style';
|
||||
|
||||
export interface BackTopProps {
|
||||
visibilityHeight?: number;
|
||||
onClick?: React.MouseEventHandler<HTMLElement>;
|
||||
@ -105,7 +107,10 @@ const BackTop: React.FC<BackTopProps> = props => {
|
||||
const { prefixCls: customizePrefixCls, className = '' } = props;
|
||||
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
||||
const classString = classNames(
|
||||
hashId,
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
@ -123,10 +128,10 @@ const BackTop: React.FC<BackTopProps> = props => {
|
||||
'visible',
|
||||
]);
|
||||
|
||||
return (
|
||||
return wrapSSR(
|
||||
<div {...divProps} className={classString} onClick={scrollToTop} ref={ref}>
|
||||
{renderChildren({ prefixCls, rootPrefixCls })}
|
||||
</div>
|
||||
</div>,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,49 +1,49 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
// @import '../../style/themes/index';
|
||||
// @import '../../style/mixins/index';
|
||||
|
||||
@backtop-prefix-cls: ~'@{ant-prefix}-back-top';
|
||||
// @backtop-prefix-cls: ~'@{ant-prefix}-back-top';
|
||||
|
||||
.@{backtop-prefix-cls} {
|
||||
.reset-component();
|
||||
// .@{backtop-prefix-cls} {
|
||||
// .reset-component();
|
||||
|
||||
position: fixed;
|
||||
right: 100px;
|
||||
bottom: 50px;
|
||||
z-index: @zindex-back-top;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
// position: fixed;
|
||||
// right: 100px;
|
||||
// bottom: 50px;
|
||||
// z-index: @zindex-back-top;
|
||||
// width: 40px;
|
||||
// height: 40px;
|
||||
// cursor: pointer;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
// &:empty {
|
||||
// display: none;
|
||||
// }
|
||||
|
||||
&-rtl {
|
||||
right: auto;
|
||||
left: 100px;
|
||||
direction: rtl;
|
||||
}
|
||||
// &-rtl {
|
||||
// right: auto;
|
||||
// left: 100px;
|
||||
// direction: rtl;
|
||||
// }
|
||||
|
||||
&-content {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
overflow: hidden;
|
||||
color: @back-top-color;
|
||||
text-align: center;
|
||||
background-color: @back-top-bg;
|
||||
border-radius: 20px;
|
||||
transition: all 0.3s;
|
||||
// &-content {
|
||||
// width: 40px;
|
||||
// height: 40px;
|
||||
// overflow: hidden;
|
||||
// color: @back-top-color;
|
||||
// text-align: center;
|
||||
// background-color: @back-top-bg;
|
||||
// border-radius: 20px;
|
||||
// transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background-color: @back-top-hover-bg;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
}
|
||||
// &:hover {
|
||||
// background-color: @back-top-hover-bg;
|
||||
// transition: all 0.3s;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-icon {
|
||||
font-size: 24px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
// &-icon {
|
||||
// font-size: 24px;
|
||||
// line-height: 40px;
|
||||
// }
|
||||
// }
|
||||
|
||||
@import './responsive';
|
||||
// @import './responsive';
|
||||
|
@ -1,2 +1,108 @@
|
||||
import '../../style/index.less';
|
||||
import './index.less';
|
||||
// deps-lint-skip-all
|
||||
import { CSSObject } from '@ant-design/cssinjs';
|
||||
import {
|
||||
resetComponent,
|
||||
genComponentStyleHook,
|
||||
GenerateStyle,
|
||||
FullToken,
|
||||
mergeToken,
|
||||
} from '../../_util/theme';
|
||||
|
||||
/** Component only token. Which will handle additional calculation of alias token */
|
||||
export interface ComponentToken {}
|
||||
|
||||
type BackTopToken = FullToken<'BackTop'> & {
|
||||
backTopBackground: string;
|
||||
backTopColor: string;
|
||||
backTopHoverBackground: string;
|
||||
};
|
||||
|
||||
// ============================== Shared ==============================
|
||||
const genSharedBackTopStyle: GenerateStyle<BackTopToken, CSSObject> = (token): CSSObject => {
|
||||
const { componentCls } = token;
|
||||
|
||||
return {
|
||||
[componentCls]: {
|
||||
...resetComponent(token),
|
||||
|
||||
position: 'fixed',
|
||||
// FIXME right
|
||||
insetInlineEnd: 100,
|
||||
// FIXME bottom
|
||||
insetBlockEnd: 50,
|
||||
// FIX ME @zindex-back-top
|
||||
zIndex: token.zIndexPopup,
|
||||
width: 40,
|
||||
height: 40,
|
||||
cursor: 'pointer',
|
||||
|
||||
'&:empty': {
|
||||
display: 'none',
|
||||
},
|
||||
|
||||
[`${componentCls}-content`]: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
overflow: 'hidden',
|
||||
// FIXME @back-top-color
|
||||
color: token.backTopColor,
|
||||
textAlign: 'center',
|
||||
// FIXME @back-top-bg
|
||||
backgroundColor: token.backTopBackground,
|
||||
// FIXME
|
||||
borderRadius: 20,
|
||||
transition: `all ${token.motionDurationSlow}`,
|
||||
|
||||
'&:hover': {
|
||||
// FIX ME @back-top-hover-bg
|
||||
backgroundColor: token.backTopHoverBackground,
|
||||
transition: `all ${token.motionDurationSlow}`,
|
||||
},
|
||||
},
|
||||
|
||||
// change to .backtop .backtop-icon
|
||||
[`${componentCls}-icon`]: {
|
||||
// FIXME
|
||||
fontSize: 24,
|
||||
// FIXME
|
||||
lineHeight: '40px',
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const genMediaBackTopStyle: GenerateStyle<BackTopToken> = (token): CSSObject => {
|
||||
const { componentCls } = token;
|
||||
|
||||
return {
|
||||
[`@media (max-width: ${token.screenMD}px)`]: {
|
||||
[componentCls]: {
|
||||
marginInlineEnd: 60,
|
||||
},
|
||||
},
|
||||
|
||||
[`@media (max-width: ${token.screenXS}px)`]: {
|
||||
[componentCls]: {
|
||||
marginInlineEnd: 20,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook<'BackTop'>(
|
||||
'BackTop',
|
||||
|
||||
token => {
|
||||
const backTopBackground = 'rgb(16, 136, 233)';
|
||||
const backTopColor = '#fff';
|
||||
const backTopHoverBackground = '#000000d9';
|
||||
|
||||
const backTopToken = mergeToken<BackTopToken>(token, {
|
||||
backTopBackground,
|
||||
backTopColor,
|
||||
backTopHoverBackground,
|
||||
});
|
||||
return [genSharedBackTopStyle(backTopToken), genMediaBackTopStyle(backTopToken)];
|
||||
},
|
||||
);
|
||||
|
@ -1,21 +1,21 @@
|
||||
@media screen and (max-width: @screen-md) {
|
||||
.@{backtop-prefix-cls} {
|
||||
right: 60px;
|
||||
// @media screen and (max-width: @screen-md) {
|
||||
// .@{backtop-prefix-cls} {
|
||||
// right: 60px;
|
||||
|
||||
&-rtl {
|
||||
right: auto;
|
||||
left: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
// &-rtl {
|
||||
// right: auto;
|
||||
// left: 60px;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@media screen and (max-width: @screen-xs) {
|
||||
.@{backtop-prefix-cls} {
|
||||
right: 20px;
|
||||
// @media screen and (max-width: @screen-xs) {
|
||||
// .@{backtop-prefix-cls} {
|
||||
// right: 20px;
|
||||
|
||||
&-rtl {
|
||||
right: auto;
|
||||
left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
// &-rtl {
|
||||
// right: auto;
|
||||
// left: 20px;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { fireEvent, render } from '@testing-library/react';
|
||||
import Badge from '../index';
|
||||
import Tooltip from '../../tooltip';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
@ -54,14 +55,14 @@ describe('Badge', () => {
|
||||
// https://github.com/ant-design/ant-design/issues/10626
|
||||
it('should be composable with Tooltip', () => {
|
||||
const ref = React.createRef();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Tooltip title="Fix the error" ref={ref}>
|
||||
<Badge status="error" />
|
||||
</Tooltip>,
|
||||
);
|
||||
|
||||
act(() => {
|
||||
wrapper.find('Badge').simulate('mouseenter');
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-badge'));
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(ref.current.props.visible).toBeTruthy();
|
||||
|
@ -74,5 +74,5 @@ class Demo extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default () => <Demo />;
|
||||
export default Demo;
|
||||
```
|
||||
|
@ -36,5 +36,5 @@ const Demo = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default () => <Demo />;
|
||||
export default Demo;
|
||||
```
|
||||
|
@ -54,10 +54,7 @@ const antBadgeLoadingCircle = new Keyframes('antBadgeLoadingCircle', {
|
||||
},
|
||||
});
|
||||
|
||||
const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (
|
||||
token: BadgeToken,
|
||||
hashId: string,
|
||||
): CSSObject => {
|
||||
const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSObject => {
|
||||
const { componentCls, iconCls, antCls } = token;
|
||||
const numberPrefixCls = `${antCls}-scroll-number`;
|
||||
const ribbonPrefixCls = `${antCls}-ribbon`;
|
||||
@ -147,9 +144,10 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (
|
||||
transform: 'translate(50%, -50%)',
|
||||
transformOrigin: '100% 0%',
|
||||
[`${iconCls}-spin`]: {
|
||||
animation: `${antBadgeLoadingCircle.getName(hashId)} ${
|
||||
token.motionDurationFast
|
||||
} infinite linear`,
|
||||
animationName: antBadgeLoadingCircle,
|
||||
animationDuration: token.motionDurationFast,
|
||||
animationIterationCount: 'infinite',
|
||||
animationTimingFunction: 'linear',
|
||||
},
|
||||
},
|
||||
[`&${componentCls}-status`]: {
|
||||
@ -181,7 +179,10 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (
|
||||
height: '100%',
|
||||
border: `1px solid ${token.colorPrimary}`,
|
||||
borderRadius: '50%',
|
||||
animation: `${antStatusProcessing.getName(hashId)} 1.2s infinite ease-in-out`, // FIXME: hard code, copied from old less file
|
||||
animationName: antStatusProcessing,
|
||||
animationDuration: '1.2s',
|
||||
animationIterationCount: 'infinite',
|
||||
animationTimingFunction: 'ease-in-out',
|
||||
content: '""',
|
||||
},
|
||||
},
|
||||
@ -204,28 +205,28 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (
|
||||
},
|
||||
},
|
||||
[`${componentCls}-zoom-appear, ${componentCls}-zoom-enter`]: {
|
||||
animation: `${antZoomBadgeIn.getName(hashId)} ${token.motionDurationSlow} ${
|
||||
token.motionEaseOutBack
|
||||
}`,
|
||||
animationName: antZoomBadgeIn,
|
||||
animationDuration: token.motionDurationSlow,
|
||||
animationTimingFunction: token.motionEaseOutBack,
|
||||
animationFillMode: 'both',
|
||||
},
|
||||
[`${componentCls}-zoom-leave`]: {
|
||||
animation: `${antZoomBadgeOut.getName(hashId)} ${token.motionDurationSlow} ${
|
||||
token.motionEaseOutBack
|
||||
}`,
|
||||
animationName: antZoomBadgeOut,
|
||||
animationDuration: token.motionDurationSlow,
|
||||
animationTimingFunction: token.motionEaseOutBack,
|
||||
animationFillMode: 'both',
|
||||
},
|
||||
[`&${componentCls}-not-a-wrapper`]: {
|
||||
[`${componentCls}-zoom-appear, ${componentCls}-zoom-enter`]: {
|
||||
animation: `${antNoWrapperZoomBadgeIn.getName(hashId)} ${token.motionDurationSlow} ${
|
||||
token.motionEaseOutBack
|
||||
}`,
|
||||
animationName: antNoWrapperZoomBadgeIn,
|
||||
animationDuration: token.motionDurationSlow,
|
||||
animationTimingFunction: token.motionEaseOutBack,
|
||||
},
|
||||
|
||||
[`${componentCls}-zoom-leave`]: {
|
||||
animation: `${antNoWrapperZoomBadgeOut.getName(hashId)} ${token.motionDurationSlow} ${
|
||||
token.motionEaseOutBack
|
||||
}`,
|
||||
animationName: antNoWrapperZoomBadgeOut,
|
||||
animationDuration: token.motionDurationSlow,
|
||||
animationTimingFunction: token.motionEaseOutBack,
|
||||
},
|
||||
[`&:not(${componentCls}-status)`]: {
|
||||
verticalAlign: 'middle',
|
||||
@ -296,7 +297,7 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (
|
||||
...statusRibbonPreset,
|
||||
[`&${ribbonPrefixCls}-placement-end`]: {
|
||||
insetInlineEnd: -1 * token.marginXS,
|
||||
borderBottomRightRadius: 0,
|
||||
borderEndEndRadius: 0,
|
||||
[`${ribbonPrefixCls}-corner`]: {
|
||||
insetInlineEnd: 0,
|
||||
borderColor: 'currentcolor transparent transparent currentcolor',
|
||||
@ -304,24 +305,18 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (
|
||||
},
|
||||
[`&${ribbonPrefixCls}-placement-start`]: {
|
||||
insetInlineStart: -1 * token.marginXS,
|
||||
borderBottomLeftRadius: 0,
|
||||
borderEndStartRadius: 0,
|
||||
[`${ribbonPrefixCls}-corner`]: {
|
||||
insetInlineStart: 0,
|
||||
borderColor: 'currentcolor currentcolor transparent transparent',
|
||||
},
|
||||
},
|
||||
antStatusProcessing,
|
||||
antZoomBadgeIn,
|
||||
antZoomBadgeOut,
|
||||
antNoWrapperZoomBadgeIn,
|
||||
antNoWrapperZoomBadgeOut,
|
||||
antBadgeLoadingCircle,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook('Badge', (token, { hashId }) => {
|
||||
export default genComponentStyleHook('Badge', token => {
|
||||
const badgeZIndex = 'auto';
|
||||
const badgeHeight = 20; // FIXME: hard code
|
||||
const badgeTextColor = token.colorBgComponent;
|
||||
@ -346,5 +341,5 @@ export default genComponentStyleHook('Badge', (token, { hashId }) => {
|
||||
badgeStatusSize,
|
||||
});
|
||||
|
||||
return [genSharedBadgeStyle(badgeToken, hashId), { display: 'none' }];
|
||||
return [genSharedBadgeStyle(badgeToken), { display: 'none' }];
|
||||
});
|
||||
|
@ -1,15 +1,15 @@
|
||||
import * as React from 'react';
|
||||
import DownOutlined from '@ant-design/icons/DownOutlined';
|
||||
|
||||
import DropDown, { DropDownProps } from '../dropdown/dropdown';
|
||||
import Dropdown, { DropdownProps } from '../dropdown/dropdown';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
|
||||
export interface BreadcrumbItemProps {
|
||||
prefixCls?: string;
|
||||
separator?: React.ReactNode;
|
||||
href?: string;
|
||||
overlay?: DropDownProps['overlay'];
|
||||
dropdownProps?: DropDownProps;
|
||||
overlay?: DropdownProps['overlay'];
|
||||
dropdownProps?: DropdownProps;
|
||||
onClick?: React.MouseEventHandler<HTMLAnchorElement | HTMLSpanElement>;
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
@ -27,16 +27,16 @@ const BreadcrumbItem: BreadcrumbItemInterface = ({
|
||||
}) => {
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
|
||||
/** If overlay is have Wrap a DropDown */
|
||||
/** If overlay is have Wrap a Dropdown */
|
||||
const renderBreadcrumbNode = (breadcrumbItem: React.ReactNode) => {
|
||||
if (overlay) {
|
||||
return (
|
||||
<DropDown overlay={overlay} placement="bottomCenter" {...dropdownProps}>
|
||||
<Dropdown overlay={overlay} placement="bottom" {...dropdownProps}>
|
||||
<span className={`${prefixCls}-overlay-link`}>
|
||||
{breadcrumbItem}
|
||||
<DownOutlined />
|
||||
</span>
|
||||
</DropDown>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
return breadcrumbItem;
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { render } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import { render } from '../../../tests/utils';
|
||||
import Breadcrumb from '../index';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
@ -30,8 +29,7 @@ describe('Breadcrumb', () => {
|
||||
<MyCom />
|
||||
</Breadcrumb>,
|
||||
);
|
||||
expect(errorSpy.mock.calls).toHaveLength(1);
|
||||
expect(errorSpy.mock.calls[0][0]).toMatch(
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
"Warning: [antd: Breadcrumb] Only accepts Breadcrumb.Item and Breadcrumb.Separator as it's children",
|
||||
);
|
||||
});
|
||||
|
@ -134,10 +134,11 @@ exports[`renders ./components/breadcrumb/demo/overlay.md extend context correctl
|
||||
<div>
|
||||
<div
|
||||
class="ant-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<ul
|
||||
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical ant-dropdown-menu-light"
|
||||
data-dropdown-inject="true"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
@ -162,7 +163,7 @@ exports[`renders ./components/breadcrumb/demo/overlay.md extend context correctl
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -201,7 +202,7 @@ exports[`renders ./components/breadcrumb/demo/overlay.md extend context correctl
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -240,7 +241,7 @@ exports[`renders ./components/breadcrumb/demo/overlay.md extend context correctl
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -267,7 +268,7 @@ exports[`renders ./components/breadcrumb/demo/overlay.md extend context correctl
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -289,7 +290,7 @@ exports[`renders ./components/breadcrumb/demo/overlay.md extend context correctl
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -311,7 +312,7 @@ exports[`renders ./components/breadcrumb/demo/overlay.md extend context correctl
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
|
@ -1,166 +1,72 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`react router react router 3 1`] = `
|
||||
<Breadcrumb
|
||||
params={
|
||||
Object {
|
||||
"id": 1,
|
||||
}
|
||||
}
|
||||
routes={
|
||||
Array [
|
||||
Object {
|
||||
"breadcrumbName": "Home",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Application List",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Application:id",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Detail",
|
||||
"name": "detail",
|
||||
"path": "detail",
|
||||
},
|
||||
],
|
||||
"name": "app",
|
||||
"path": ":id",
|
||||
},
|
||||
],
|
||||
"name": "apps",
|
||||
"path": "apps",
|
||||
},
|
||||
],
|
||||
"name": "home",
|
||||
"path": "/",
|
||||
},
|
||||
Object {
|
||||
"breadcrumbName": "Application List",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Application:id",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Detail",
|
||||
"name": "detail",
|
||||
"path": "detail",
|
||||
},
|
||||
],
|
||||
"name": "app",
|
||||
"path": ":id",
|
||||
},
|
||||
],
|
||||
"name": "apps",
|
||||
"path": "apps",
|
||||
},
|
||||
Object {
|
||||
"breadcrumbName": "Application:id",
|
||||
"childRoutes": Array [
|
||||
Object {
|
||||
"breadcrumbName": "Detail",
|
||||
"name": "detail",
|
||||
"path": "detail",
|
||||
},
|
||||
],
|
||||
"name": "app",
|
||||
"path": ":id",
|
||||
},
|
||||
Object {
|
||||
"breadcrumbName": "Detail",
|
||||
"name": "detail",
|
||||
"path": "detail",
|
||||
},
|
||||
]
|
||||
}
|
||||
<nav
|
||||
class="ant-breadcrumb"
|
||||
>
|
||||
<nav
|
||||
className="ant-breadcrumb"
|
||||
>
|
||||
<ol>
|
||||
<BreadcrumbItem
|
||||
key="Home"
|
||||
separator="/"
|
||||
<ol>
|
||||
<li>
|
||||
<span
|
||||
class="ant-breadcrumb-link"
|
||||
>
|
||||
<li>
|
||||
<span
|
||||
className="ant-breadcrumb-link"
|
||||
>
|
||||
<a
|
||||
href="#/"
|
||||
>
|
||||
Home
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
className="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</li>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbItem
|
||||
key="apps"
|
||||
separator="/"
|
||||
<a
|
||||
href="#/"
|
||||
>
|
||||
Home
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
class="ant-breadcrumb-separator"
|
||||
>
|
||||
<li>
|
||||
<span
|
||||
className="ant-breadcrumb-link"
|
||||
>
|
||||
<a
|
||||
href="#/apps"
|
||||
>
|
||||
Application List
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
className="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</li>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbItem
|
||||
key="1"
|
||||
separator="/"
|
||||
/
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span
|
||||
class="ant-breadcrumb-link"
|
||||
>
|
||||
<li>
|
||||
<span
|
||||
className="ant-breadcrumb-link"
|
||||
>
|
||||
<a
|
||||
href="#/apps/1"
|
||||
>
|
||||
Application1
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
className="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</li>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbItem
|
||||
key="detail"
|
||||
separator="/"
|
||||
<a
|
||||
href="#/apps"
|
||||
>
|
||||
Application List
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
class="ant-breadcrumb-separator"
|
||||
>
|
||||
<li>
|
||||
<span
|
||||
className="ant-breadcrumb-link"
|
||||
>
|
||||
<span>
|
||||
Detail
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
className="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</li>
|
||||
</BreadcrumbItem>
|
||||
</ol>
|
||||
</nav>
|
||||
</Breadcrumb>
|
||||
/
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span
|
||||
class="ant-breadcrumb-link"
|
||||
>
|
||||
<a
|
||||
href="#/apps/1"
|
||||
>
|
||||
Application1
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
class="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span
|
||||
class="ant-breadcrumb-link"
|
||||
>
|
||||
<span>
|
||||
Detail
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
`;
|
||||
|
@ -144,6 +144,6 @@ describe('react router', () => {
|
||||
},
|
||||
];
|
||||
const wrapper = mount(<Breadcrumb routes={routes} params={{ id: 1 }} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -16,6 +16,9 @@
|
||||
ol {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -397,7 +397,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -480,7 +480,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -556,7 +556,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -631,7 +631,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -732,7 +732,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -815,7 +815,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -891,7 +891,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -966,7 +966,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1048,7 +1048,7 @@ Array [
|
||||
class="ant-btn-group ant-btn-group-sm"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1056,7 +1056,7 @@ Array [
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1068,7 +1068,7 @@ Array [
|
||||
style="display:inline-block;cursor:not-allowed"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
disabled=""
|
||||
style="pointer-events:none"
|
||||
type="button"
|
||||
@ -1097,7 +1097,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1119,7 +1119,7 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
@ -1145,7 +1145,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1223,7 +1223,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1271,7 +1271,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1300,7 +1300,7 @@ Array [
|
||||
class="ant-btn-group ant-btn-group-lg"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1308,7 +1308,7 @@ Array [
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1320,7 +1320,7 @@ Array [
|
||||
style="display:inline-block;cursor:not-allowed"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg ant-btn-icon-only"
|
||||
disabled=""
|
||||
style="pointer-events:none"
|
||||
type="button"
|
||||
@ -1349,7 +1349,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1371,7 +1371,7 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
@ -1397,7 +1397,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1671,10 +1671,11 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<ul
|
||||
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical ant-dropdown-menu-light"
|
||||
data-dropdown-inject="true"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
@ -1693,7 +1694,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1726,7 +1727,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1759,7 +1760,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1786,7 +1787,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1808,7 +1809,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
@ -1830,7 +1831,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
|
@ -856,7 +856,7 @@ Array [
|
||||
class="ant-btn-group ant-btn-group-sm"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -864,7 +864,7 @@ Array [
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -876,7 +876,7 @@ Array [
|
||||
style="display:inline-block;cursor:not-allowed"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
disabled=""
|
||||
style="pointer-events:none"
|
||||
type="button"
|
||||
@ -903,7 +903,7 @@ Array [
|
||||
</button>
|
||||
</span>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
@ -1012,7 +1012,7 @@ Array [
|
||||
class="ant-btn-group ant-btn-group-lg"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1020,7 +1020,7 @@ Array [
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1032,7 +1032,7 @@ Array [
|
||||
style="display:inline-block;cursor:not-allowed"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg ant-btn-icon-only"
|
||||
disabled=""
|
||||
style="pointer-events:none"
|
||||
type="button"
|
||||
@ -1059,7 +1059,7 @@ Array [
|
||||
</button>
|
||||
</span>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
|
@ -1,7 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { render } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import { resetWarned } from 'rc-util/lib/warning';
|
||||
@ -9,7 +7,7 @@ import Button from '..';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
import { sleep, render, fireEvent } from '../../../tests/utils';
|
||||
import { SizeType } from '../../config-provider/SizeContext';
|
||||
|
||||
describe('Button', () => {
|
||||
@ -38,14 +36,13 @@ describe('Button', () => {
|
||||
});
|
||||
|
||||
it('warns if size is wrong', () => {
|
||||
const mockWarn = jest.fn();
|
||||
jest.spyOn(console, 'warn').mockImplementation(mockWarn);
|
||||
resetWarned();
|
||||
const mockWarn = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const size = 'who am I' as any as SizeType;
|
||||
mount(<Button.Group size={size} />);
|
||||
expect(mockWarn).toHaveBeenCalledTimes(1);
|
||||
expect(mockWarn.mock.calls[0][0]).toMatchObject({
|
||||
message: 'unreachable case: "who am I"',
|
||||
});
|
||||
render(<Button.Group size={size} />);
|
||||
expect(mockWarn).toHaveBeenCalledWith('Warning: [antd: Button.Group] Invalid prop `size`.');
|
||||
|
||||
mockWarn.mockRestore();
|
||||
});
|
||||
|
||||
it('renders Chinese characters correctly', () => {
|
||||
@ -86,22 +83,26 @@ describe('Button', () => {
|
||||
|
||||
it('renders Chinese characters correctly in HOC', () => {
|
||||
const Text = ({ children }: { children: React.ReactNode }) => <span>{children}</span>;
|
||||
const wrapper = mount(
|
||||
const { container, rerender } = render(
|
||||
<Button>
|
||||
<Text>按钮</Text>
|
||||
</Button>,
|
||||
);
|
||||
expect(wrapper.find('.ant-btn').hasClass('ant-btn-two-chinese-chars')).toBe(true);
|
||||
wrapper.setProps({
|
||||
children: <Text>大按钮</Text>,
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-btn').hasClass('ant-btn-two-chinese-chars')).toBe(false);
|
||||
wrapper.setProps({
|
||||
children: <Text>按钮</Text>,
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-btn').hasClass('ant-btn-two-chinese-chars')).toBe(true);
|
||||
expect(container.querySelector('.ant-btn')).toHaveClass('ant-btn-two-chinese-chars');
|
||||
|
||||
rerender(
|
||||
<Button>
|
||||
<Text>大按钮</Text>
|
||||
</Button>,
|
||||
);
|
||||
expect(container.querySelector('.ant-btn')).not.toHaveClass('ant-btn-two-chinese-chars');
|
||||
|
||||
rerender(
|
||||
<Button>
|
||||
<Text>按钮</Text>
|
||||
</Button>,
|
||||
);
|
||||
expect(container.querySelector('.ant-btn')).toHaveClass('ant-btn-two-chinese-chars');
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/18118
|
||||
@ -124,7 +125,7 @@ describe('Button', () => {
|
||||
|
||||
it('have static property for type detecting', () => {
|
||||
const wrapper = mount(<Button>Button Text</Button>);
|
||||
expect((wrapper.type() as any).__ANT_BUTTON).toBe(true);
|
||||
expect((wrapper.find(Button).type() as any).__ANT_BUTTON).toBe(true);
|
||||
});
|
||||
|
||||
it('should change loading state instantly by default', () => {
|
||||
@ -195,12 +196,12 @@ describe('Button', () => {
|
||||
|
||||
it('should not clickable when button is loading', () => {
|
||||
const onClick = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Button loading onClick={onClick}>
|
||||
button
|
||||
</Button>,
|
||||
);
|
||||
wrapper.simulate('click');
|
||||
fireEvent.click(container.firstChild!);
|
||||
expect(onClick).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
@ -314,12 +315,12 @@ describe('Button', () => {
|
||||
|
||||
it('should not redirect when button is disabled', () => {
|
||||
const onClick = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Button href="https://ant.design" onClick={onClick} disabled>
|
||||
click me
|
||||
</Button>,
|
||||
);
|
||||
wrapper.simulate('click');
|
||||
fireEvent.click(container.firstChild!);
|
||||
expect(onClick).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
@ -210,28 +210,6 @@
|
||||
.@{btnClassName}-icon-only {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
// size
|
||||
&-lg > .@{btnClassName},
|
||||
&-lg > span > .@{btnClassName} {
|
||||
.button-size(@btn-height-lg; @btn-padding-horizontal-lg; @btn-font-size-lg; 0);
|
||||
}
|
||||
&-lg .@{btnClassName}.@{btnClassName}-icon-only {
|
||||
.square(@btn-height-lg);
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
&-sm > .@{btnClassName},
|
||||
&-sm > span > .@{btnClassName} {
|
||||
.button-size(@btn-height-sm; @btn-padding-horizontal-sm; @font-size-base; 0);
|
||||
> .@{iconfont-css-prefix} {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
}
|
||||
&-sm .@{btnClassName}.@{btnClassName}-icon-only {
|
||||
.square(@btn-height-sm);
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
// Base styles of buttons
|
||||
// --------------------------------------------------
|
||||
|
@ -1,8 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { SizeType } from '../config-provider/SizeContext';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import UnreachableException from '../_util/unreachableException';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import devWarning from '../_util/devWarning';
|
||||
import { useToken } from '../_util/theme';
|
||||
|
||||
export interface ButtonGroupProps {
|
||||
size?: SizeType;
|
||||
@ -12,42 +13,49 @@ export interface ButtonGroupProps {
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const ButtonGroup: React.FC<ButtonGroupProps> = props => (
|
||||
<ConfigConsumer>
|
||||
{({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, size, className, ...others } = props;
|
||||
const prefixCls = getPrefixCls('btn-group', customizePrefixCls);
|
||||
export const GroupSizeContext = React.createContext<SizeType | undefined>(undefined);
|
||||
|
||||
// large => lg
|
||||
// small => sm
|
||||
let sizeCls = '';
|
||||
switch (size) {
|
||||
case 'large':
|
||||
sizeCls = 'lg';
|
||||
break;
|
||||
case 'small':
|
||||
sizeCls = 'sm';
|
||||
break;
|
||||
case 'middle':
|
||||
case undefined:
|
||||
break;
|
||||
default:
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(new UnreachableException(size).error);
|
||||
}
|
||||
const ButtonGroup: React.FC<ButtonGroupProps> = props => {
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
|
||||
const classes = classNames(
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
const { prefixCls: customizePrefixCls, size, className, ...others } = props;
|
||||
const prefixCls = getPrefixCls('btn-group', customizePrefixCls);
|
||||
|
||||
return <div {...others} className={classes} />;
|
||||
}}
|
||||
</ConfigConsumer>
|
||||
);
|
||||
// Here we only need hashId
|
||||
const [, , hashId] = useToken();
|
||||
|
||||
// large => lg
|
||||
// small => sm
|
||||
let sizeCls = '';
|
||||
switch (size) {
|
||||
case 'large':
|
||||
sizeCls = 'lg';
|
||||
break;
|
||||
case 'small':
|
||||
sizeCls = 'sm';
|
||||
break;
|
||||
case 'middle':
|
||||
case undefined:
|
||||
break;
|
||||
default:
|
||||
devWarning(!size, 'Button.Group', 'Invalid prop `size`.');
|
||||
}
|
||||
|
||||
const classes = classNames(
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
hashId,
|
||||
);
|
||||
|
||||
return (
|
||||
<GroupSizeContext.Provider value={size}>
|
||||
<div {...others} className={classes} />
|
||||
</GroupSizeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ButtonGroup;
|
||||
|
@ -3,7 +3,7 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'rc-util/lib/omit';
|
||||
|
||||
import Group from './button-group';
|
||||
import Group, { GroupSizeContext } from './button-group';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import Wave from '../_util/wave';
|
||||
import { tuple } from '../_util/type';
|
||||
@ -21,7 +21,7 @@ function isString(str: any) {
|
||||
return typeof str === 'string';
|
||||
}
|
||||
|
||||
function isUnborderedButtonType(type: ButtonType | undefined) {
|
||||
function isUnBorderedButtonType(type: ButtonType | undefined) {
|
||||
return type === 'text' || type === 'link';
|
||||
}
|
||||
|
||||
@ -97,7 +97,11 @@ export function convertLegacyProps(type?: LegacyButtonType): ButtonProps {
|
||||
export interface BaseButtonProps {
|
||||
type?: ButtonType;
|
||||
icon?: React.ReactNode;
|
||||
/** @default default */
|
||||
/**
|
||||
* Shape of Button
|
||||
*
|
||||
* @default default
|
||||
*/
|
||||
shape?: ButtonShape;
|
||||
size?: SizeType;
|
||||
loading?: boolean | { delay?: number };
|
||||
@ -161,12 +165,13 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
||||
const size = React.useContext(SizeContext);
|
||||
const groupSize = React.useContext(GroupSizeContext);
|
||||
const [innerLoading, setLoading] = React.useState<Loading>(!!loading);
|
||||
const [hasTwoCNChar, setHasTwoCNChar] = React.useState(false);
|
||||
const buttonRef = (ref as any) || React.createRef<HTMLElement>();
|
||||
|
||||
const isNeedInserted = () =>
|
||||
React.Children.count(children) === 1 && !icon && !isUnborderedButtonType(type);
|
||||
React.Children.count(children) === 1 && !icon && !isUnBorderedButtonType(type);
|
||||
|
||||
const fixTwoCNChar = () => {
|
||||
// Fix for HOC usage like <FormatMessage />
|
||||
@ -228,7 +233,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
);
|
||||
|
||||
devWarning(
|
||||
!(ghost && isUnborderedButtonType(type)),
|
||||
!(ghost && isUnBorderedButtonType(type)),
|
||||
'Button',
|
||||
"`link` or `text` button can't be a `ghost` button.",
|
||||
);
|
||||
@ -236,7 +241,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
const autoInsertSpace = autoInsertSpaceInButton !== false;
|
||||
|
||||
const sizeClassNameMap = { large: 'lg', small: 'sm', middle: undefined };
|
||||
const sizeFullname = customizeSize || size;
|
||||
const sizeFullname = groupSize || customizeSize || size;
|
||||
const sizeCls = sizeFullname ? sizeClassNameMap[sizeFullname] || '' : '';
|
||||
|
||||
const iconType = innerLoading ? 'loading' : icon;
|
||||
@ -249,7 +254,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
[`${prefixCls}-${type}`]: type,
|
||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||
[`${prefixCls}-icon-only`]: !children && children !== 0 && !!iconType,
|
||||
[`${prefixCls}-background-ghost`]: ghost && !isUnborderedButtonType(type),
|
||||
[`${prefixCls}-background-ghost`]: ghost && !isUnBorderedButtonType(type),
|
||||
[`${prefixCls}-loading`]: innerLoading,
|
||||
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace,
|
||||
[`${prefixCls}-block`]: block,
|
||||
@ -294,7 +299,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
</button>
|
||||
);
|
||||
|
||||
if (!isUnborderedButtonType(type)) {
|
||||
if (!isUnBorderedButtonType(type)) {
|
||||
buttonNode = <Wave disabled={!!innerLoading}>{buttonNode}</Wave>;
|
||||
}
|
||||
|
||||
|
@ -45,9 +45,3 @@ export default () => (
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
```css
|
||||
#components-button-demo-legacy-group .ant-btn {
|
||||
margin: 0;
|
||||
}
|
||||
```
|
||||
|
@ -81,5 +81,5 @@ class App extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default () => <App />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -57,18 +57,14 @@ Following the Ant Design specification, we will add one space between if Button
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/MY%26THAPZrW/38f06cb9-293a-4b42-b183-9f443e79ffea.png" style="box-shadow: none; margin: 0; width: 100px" alt="Button with two Chinese characters" />
|
||||
|
||||
<style>
|
||||
[id^=components-button-demo-] .ant-btn {
|
||||
[id^="components-button-demo-"]:not([id^="components-button-demo-legacy-group"]) .ant-btn {
|
||||
margin-right: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
[id^="components-button-demo-"] .ant-btn-rtl {
|
||||
[id^="components-button-demo-"]:not([id^="components-button-demo-legacy-group"]) .ant-btn-rtl {
|
||||
margin-right: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
[id^=components-button-demo-] .ant-btn-group > .ant-btn,
|
||||
[id^=components-button-demo-] .ant-btn-group > span > .ant-btn {
|
||||
margin-right: 0;
|
||||
}
|
||||
[data-theme="dark"] .site-button-ghost-wrapper {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
@ -62,17 +62,14 @@ cover: https://gw.alipayobjects.com/zos/alicdn/fNUKzY1sk/Button.svg
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/MY%26THAPZrW/38f06cb9-293a-4b42-b183-9f443e79ffea.png" style="box-shadow: none; margin: 0; width: 100px" alt="移除两个汉字之间的空格" />
|
||||
|
||||
<style>
|
||||
[id^="components-button-demo-"] .ant-btn {
|
||||
[id^="components-button-demo-"]:not([id^="components-button-demo-legacy-group"]) .ant-btn {
|
||||
margin-right: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
[id^="components-button-demo-"] .ant-btn-rtl {
|
||||
[id^="components-button-demo-"]:not([id^="components-button-demo-legacy-group"]) .ant-btn-rtl {
|
||||
margin-right: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
[id^="components-button-demo-"] .ant-btn-group > .ant-btn {
|
||||
margin-right: 0;
|
||||
}
|
||||
[data-theme="dark"] .site-button-ghost-wrapper {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
81
components/button/style/group.tsx
Normal file
81
components/button/style/group.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
import type { GenerateStyle } from '../../_util/theme';
|
||||
import type { ButtonToken } from '.';
|
||||
|
||||
const genButtonBorderStyle = (buttonTypeCls: string, borderColor: string) => ({
|
||||
// Border
|
||||
[`> span, > ${buttonTypeCls}`]: {
|
||||
'&:not(:last-child)': {
|
||||
[`&, & > ${buttonTypeCls}`]: {
|
||||
'&:not(:disabled)': {
|
||||
borderInlineEndColor: borderColor,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
'&:not(:first-child)': {
|
||||
[`&, & > ${buttonTypeCls}`]: {
|
||||
'&:not(:disabled)': {
|
||||
borderInlineStartColor: borderColor,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const genGroupStyle: GenerateStyle<ButtonToken> = token => {
|
||||
const { componentCls, fontSizeBase, controlLineWidth, colorPrimaryHover, colorErrorHover } =
|
||||
token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-group`]: [
|
||||
{
|
||||
position: 'relative',
|
||||
display: 'inline-flex',
|
||||
|
||||
// Border
|
||||
[`> span, > ${componentCls}`]: {
|
||||
'&:not(:last-child)': {
|
||||
[`&, & > ${componentCls}`]: {
|
||||
borderStartEndRadius: 0,
|
||||
borderEndEndRadius: 0,
|
||||
},
|
||||
},
|
||||
|
||||
'&:not(:first-child)': {
|
||||
marginInlineStart: -controlLineWidth,
|
||||
|
||||
[`&, & > ${componentCls}`]: {
|
||||
borderStartStartRadius: 0,
|
||||
borderEndStartRadius: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[componentCls]: {
|
||||
position: 'relative',
|
||||
zIndex: 1,
|
||||
|
||||
[`&:hover,
|
||||
&:focus,
|
||||
&:active`]: {
|
||||
zIndex: 2,
|
||||
},
|
||||
|
||||
'&[disabled]': {
|
||||
zIndex: 0,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-icon-only`]: {
|
||||
fontSize: fontSizeBase,
|
||||
},
|
||||
},
|
||||
|
||||
// Border Color
|
||||
genButtonBorderStyle(`${componentCls}-primary`, colorPrimaryHover),
|
||||
genButtonBorderStyle(`${componentCls}-danger`, colorErrorHover),
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
export default genGroupStyle;
|
@ -3,6 +3,7 @@ import { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import { mergeToken, genComponentStyleHook } from '../../_util/theme';
|
||||
import type { GenerateStyle, FullToken } from '../../_util/theme';
|
||||
import genGroupStyle from './group';
|
||||
|
||||
/** Component only token. Which will handle additional calculation of alias token */
|
||||
export interface ComponentToken {
|
||||
@ -10,7 +11,7 @@ export interface ComponentToken {
|
||||
colorBgTextActive: string;
|
||||
}
|
||||
|
||||
interface ButtonToken extends FullToken<'Button'> {}
|
||||
export interface ButtonToken extends FullToken<'Button'> {}
|
||||
|
||||
// ============================== Shared ==============================
|
||||
const genSharedButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token): CSSObject => {
|
||||
@ -325,7 +326,7 @@ const genSizeButtonStyle = (token: ButtonToken, sizePrefixCls: string = ''): CSS
|
||||
|
||||
// Loading
|
||||
[`&${componentCls}-loading`]: {
|
||||
opacity: 0.65,
|
||||
opacity: token.colorLoadingOpacity,
|
||||
cursor: 'default',
|
||||
},
|
||||
|
||||
@ -383,6 +384,9 @@ export default genComponentStyleHook(
|
||||
|
||||
// Group (type, ghost, danger, disabled, loading)
|
||||
genTypeButtonStyle(token),
|
||||
|
||||
// Button Group
|
||||
genGroupStyle(token),
|
||||
],
|
||||
token => {
|
||||
const { colorText } = token;
|
||||
|
@ -42,7 +42,7 @@ exports[`renders ./components/calendar/demo/basic.md extend context correctly 1`
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -489,7 +489,7 @@ exports[`renders ./components/calendar/demo/basic.md extend context correctly 1`
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1627,7 +1627,7 @@ exports[`renders ./components/calendar/demo/card.md extend context correctly 1`]
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -2074,7 +2074,7 @@ exports[`renders ./components/calendar/demo/card.md extend context correctly 1`]
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -3274,7 +3274,7 @@ exports[`renders ./components/calendar/demo/customize-header.md extend context c
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -3724,7 +3724,7 @@ exports[`renders ./components/calendar/demo/customize-header.md extend context c
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -4819,7 +4819,7 @@ exports[`renders ./components/calendar/demo/notice-calendar.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -5266,7 +5266,7 @@ exports[`renders ./components/calendar/demo/notice-calendar.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -6814,7 +6814,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -7261,7 +7261,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import Dayjs from 'dayjs';
|
||||
import 'dayjs/locale/zh-cn';
|
||||
import dayjsGenerateConfig from 'rc-picker/lib/generate/dayjs';
|
||||
import { mount } from 'enzyme';
|
||||
import MockDate from 'mockdate';
|
||||
@ -10,7 +11,7 @@ import Group from '../../radio/group';
|
||||
import Button from '../../radio/radioButton';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import 'dayjs/locale/zh-cn';
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
|
||||
describe('Calendar', () => {
|
||||
mountTest(Calendar);
|
||||
@ -41,14 +42,20 @@ describe('Calendar', () => {
|
||||
});
|
||||
|
||||
it('Calendar should be selectable', () => {
|
||||
MockDate.set(Moment('2000-01-01').valueOf());
|
||||
|
||||
const onSelect = jest.fn();
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<Calendar onSelect={onSelect} onChange={onChange} />);
|
||||
wrapper.find('.ant-picker-cell').at(0).simulate('click');
|
||||
const { container } = render(<Calendar onSelect={onSelect} onChange={onChange} />);
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-picker-cell'));
|
||||
expect(onSelect).toHaveBeenCalledWith(expect.anything());
|
||||
|
||||
const value = onSelect.mock.calls[0][0];
|
||||
expect(Dayjs.isDayjs(value)).toBe(true);
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
|
||||
MockDate.reset();
|
||||
});
|
||||
|
||||
it('only Valid range should be selectable', () => {
|
||||
|
@ -47,5 +47,5 @@ class App extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default () => <App />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -139,6 +139,8 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||
};
|
||||
|
||||
const triggerChange = (date: DateType) => {
|
||||
console.log('trigger change!!!', isSameDate(date, mergedValue));
|
||||
console.log('trigger change!!!', String(date), String(mergedValue));
|
||||
setMergedValue(date);
|
||||
|
||||
if (!isSameDate(date, mergedValue)) {
|
||||
|
@ -912,11 +912,12 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tabs-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<ul
|
||||
aria-label="expanded dropdown"
|
||||
class="ant-tabs-dropdown-menu ant-tabs-dropdown-menu-root ant-tabs-dropdown-menu-vertical"
|
||||
data-dropdown-inject="true"
|
||||
data-menu-list="true"
|
||||
id="null-more-popup"
|
||||
role="listbox"
|
||||
@ -1065,11 +1066,12 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-tabs-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<ul
|
||||
aria-label="expanded dropdown"
|
||||
class="ant-tabs-dropdown-menu ant-tabs-dropdown-menu-root ant-tabs-dropdown-menu-vertical"
|
||||
data-dropdown-inject="true"
|
||||
data-menu-list="true"
|
||||
id="null-more-popup"
|
||||
role="listbox"
|
||||
|
@ -4,6 +4,7 @@ import Card from '../index';
|
||||
import Button from '../../button/index';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { render } from '../../../tests/utils';
|
||||
|
||||
describe('Card', () => {
|
||||
mountTest(Card);
|
||||
@ -84,20 +85,14 @@ describe('Card', () => {
|
||||
});
|
||||
|
||||
it('get ref of card', () => {
|
||||
class WrapperComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Card
|
||||
// eslint-disable-next-line react/no-string-refs
|
||||
ref="firstRef"
|
||||
title="Card title"
|
||||
>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
const wrapper = mount(<WrapperComponent />);
|
||||
expect(wrapper.ref('firstRef').className.includes('ant-card')).toBe(true);
|
||||
const cardRef = React.createRef();
|
||||
|
||||
render(
|
||||
<Card ref={cardRef} title="Card title">
|
||||
<p>Card content</p>
|
||||
</Card>,
|
||||
);
|
||||
|
||||
expect(cardRef.current).toHaveClass('ant-card');
|
||||
});
|
||||
});
|
||||
|
@ -64,5 +64,5 @@ class App extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default () => <App />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -8,6 +8,7 @@ import Row from '../row';
|
||||
import Col from '../col';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import SizeContext from '../config-provider/SizeContext';
|
||||
import useStyle from './style';
|
||||
|
||||
function getAction(actions: React.ReactNode[]) {
|
||||
const actionList = actions.map((action, index) => (
|
||||
@ -103,6 +104,7 @@ const Card = React.forwardRef((props: CardProps, ref: React.Ref<HTMLDivElement>)
|
||||
} = props;
|
||||
|
||||
const prefixCls = getPrefixCls('card', customizePrefixCls);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
||||
const loadingBlockStyle =
|
||||
bodyStyle.padding === 0 || bodyStyle.padding === '0px' ? { padding: 24 } : undefined;
|
||||
@ -193,15 +195,16 @@ const Card = React.forwardRef((props: CardProps, ref: React.Ref<HTMLDivElement>)
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
hashId,
|
||||
);
|
||||
|
||||
return (
|
||||
return wrapSSR(
|
||||
<div ref={ref} {...divProps} className={classString}>
|
||||
{head}
|
||||
{coverDom}
|
||||
{body}
|
||||
{actionDom}
|
||||
</div>
|
||||
</div>,
|
||||
);
|
||||
}) as CardInterface;
|
||||
|
||||
|
@ -1,308 +1,308 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
// @import '../../style/themes/index';
|
||||
// @import '../../style/mixins/index';
|
||||
|
||||
@card-prefix-cls: ~'@{ant-prefix}-card';
|
||||
@card-hoverable-hover-border: transparent;
|
||||
@card-action-icon-size: 16px;
|
||||
// @card-prefix-cls: ~'@{ant-prefix}-card';
|
||||
// @card-hoverable-hover-border: transparent;
|
||||
// @card-action-icon-size: 16px;
|
||||
|
||||
@gradient-min: fade(@card-skeleton-bg, 20%);
|
||||
@gradient-max: fade(@card-skeleton-bg, 40%);
|
||||
// @gradient-min: fade(@card-skeleton-bg, 20%);
|
||||
// @gradient-max: fade(@card-skeleton-bg, 40%);
|
||||
|
||||
.@{card-prefix-cls} {
|
||||
.reset-component();
|
||||
// .@{card-prefix-cls} {
|
||||
// .reset-component();
|
||||
|
||||
position: relative;
|
||||
background: @card-background;
|
||||
border-radius: @card-radius;
|
||||
// position: relative;
|
||||
// background: @card-background;
|
||||
// border-radius: @card-radius;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
// &-rtl {
|
||||
// direction: rtl;
|
||||
// }
|
||||
|
||||
&-hoverable {
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.3s, border-color 0.3s;
|
||||
// &-hoverable {
|
||||
// cursor: pointer;
|
||||
// transition: box-shadow 0.3s, border-color 0.3s;
|
||||
|
||||
&:hover {
|
||||
border-color: @card-hoverable-hover-border;
|
||||
box-shadow: @card-shadow;
|
||||
}
|
||||
}
|
||||
// &:hover {
|
||||
// border-color: @card-hoverable-hover-border;
|
||||
// box-shadow: @card-shadow;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-bordered {
|
||||
border: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
// &-bordered {
|
||||
// border: @border-width-base @border-style-base @border-color-split;
|
||||
// }
|
||||
|
||||
&-head {
|
||||
min-height: @card-head-height;
|
||||
margin-bottom: -1px; // Fix card grid overflow bug: https://gw.alipayobjects.com/zos/rmsportal/XonYxBikwpgbqIQBeuhk.png
|
||||
padding: 0 @card-padding-base;
|
||||
color: @card-head-color;
|
||||
font-weight: 500;
|
||||
font-size: @card-head-font-size;
|
||||
background: @card-head-background;
|
||||
border-bottom: @border-width-base @border-style-base @border-color-split;
|
||||
border-radius: @card-radius @card-radius 0 0;
|
||||
.clearfix();
|
||||
// &-head {
|
||||
// min-height: @card-head-height;
|
||||
// margin-bottom: -1px; // Fix card grid overflow bug: https://gw.alipayobjects.com/zos/rmsportal/XonYxBikwpgbqIQBeuhk.png
|
||||
// padding: 0 @card-padding-base;
|
||||
// color: @card-head-color;
|
||||
// font-weight: 500;
|
||||
// font-size: @card-head-font-size;
|
||||
// background: @card-head-background;
|
||||
// border-bottom: @border-width-base @border-style-base @border-color-split;
|
||||
// border-radius: @card-radius @card-radius 0 0;
|
||||
// .clearfix();
|
||||
|
||||
&-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
// &-wrapper {
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// }
|
||||
|
||||
&-title {
|
||||
display: inline-block;
|
||||
flex: 1;
|
||||
padding: @card-head-padding 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
// &-title {
|
||||
// display: inline-block;
|
||||
// flex: 1;
|
||||
// padding: @card-head-padding 0;
|
||||
// overflow: hidden;
|
||||
// white-space: nowrap;
|
||||
// text-overflow: ellipsis;
|
||||
|
||||
> .@{ant-prefix}-typography,
|
||||
> .@{ant-prefix}-typography-edit-content {
|
||||
left: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
// > .@{ant-prefix}-typography,
|
||||
// > .@{ant-prefix}-typography-edit-content {
|
||||
// left: 0;
|
||||
// margin-top: 0;
|
||||
// margin-bottom: 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
.@{ant-prefix}-tabs-top {
|
||||
clear: both;
|
||||
margin-bottom: @card-head-tabs-margin-bottom;
|
||||
color: @text-color;
|
||||
font-weight: normal;
|
||||
font-size: @font-size-base;
|
||||
// .@{ant-prefix}-tabs-top {
|
||||
// clear: both;
|
||||
// margin-bottom: @card-head-tabs-margin-bottom;
|
||||
// color: @text-color;
|
||||
// font-weight: normal;
|
||||
// font-size: @font-size-base;
|
||||
|
||||
&-bar {
|
||||
border-bottom: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
}
|
||||
}
|
||||
// &-bar {
|
||||
// border-bottom: @border-width-base @border-style-base @border-color-split;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
&-extra {
|
||||
float: right;
|
||||
// https://stackoverflow.com/a/22429853/3040605
|
||||
margin-left: auto;
|
||||
padding: @card-head-padding 0;
|
||||
color: @card-head-extra-color;
|
||||
font-weight: normal;
|
||||
font-size: @font-size-base;
|
||||
// &-extra {
|
||||
// float: right;
|
||||
// // https://stackoverflow.com/a/22429853/3040605
|
||||
// margin-left: auto;
|
||||
// padding: @card-head-padding 0;
|
||||
// color: @card-head-extra-color;
|
||||
// font-weight: normal;
|
||||
// font-size: @font-size-base;
|
||||
|
||||
.@{card-prefix-cls}-rtl & {
|
||||
margin-right: auto;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
// .@{card-prefix-cls}-rtl & {
|
||||
// margin-right: auto;
|
||||
// margin-left: 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-body {
|
||||
padding: @card-padding-base;
|
||||
.clearfix();
|
||||
}
|
||||
// &-body {
|
||||
// padding: @card-padding-base;
|
||||
// .clearfix();
|
||||
// }
|
||||
|
||||
&-contain-grid:not(&-loading) &-body {
|
||||
margin: -1px 0 0 -1px;
|
||||
padding: 0;
|
||||
}
|
||||
// &-contain-grid:not(&-loading) &-body {
|
||||
// margin: -1px 0 0 -1px;
|
||||
// padding: 0;
|
||||
// }
|
||||
|
||||
&-grid {
|
||||
float: left;
|
||||
width: 33.33%;
|
||||
padding: @card-padding-base;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: 1px 0 0 0 @border-color-split, 0 1px 0 0 @border-color-split,
|
||||
1px 1px 0 0 @border-color-split, 1px 0 0 0 @border-color-split inset,
|
||||
0 1px 0 0 @border-color-split inset;
|
||||
transition: all 0.3s;
|
||||
// &-grid {
|
||||
// float: left;
|
||||
// width: 33.33%;
|
||||
// padding: @card-padding-base;
|
||||
// border: 0;
|
||||
// border-radius: 0;
|
||||
// box-shadow: 1px 0 0 0 @border-color-split, 0 1px 0 0 @border-color-split,
|
||||
// 1px 1px 0 0 @border-color-split, 1px 0 0 0 @border-color-split inset,
|
||||
// 0 1px 0 0 @border-color-split inset;
|
||||
// transition: all 0.3s;
|
||||
|
||||
.@{card-prefix-cls}-rtl & {
|
||||
float: right;
|
||||
}
|
||||
// .@{card-prefix-cls}-rtl & {
|
||||
// float: right;
|
||||
// }
|
||||
|
||||
&-hoverable {
|
||||
&:hover {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-shadow: @card-shadow;
|
||||
}
|
||||
}
|
||||
}
|
||||
// &-hoverable {
|
||||
// &:hover {
|
||||
// position: relative;
|
||||
// z-index: 1;
|
||||
// box-shadow: @card-shadow;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
&-contain-tabs > &-head &-head-title {
|
||||
min-height: @card-head-height - @card-head-padding;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
// &-contain-tabs > &-head &-head-title {
|
||||
// min-height: @card-head-height - @card-head-padding;
|
||||
// padding-bottom: 0;
|
||||
// }
|
||||
|
||||
&-contain-tabs > &-head &-extra {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
// &-contain-tabs > &-head &-extra {
|
||||
// padding-bottom: 0;
|
||||
// }
|
||||
|
||||
&-bordered &-cover {
|
||||
margin-top: -1px;
|
||||
margin-right: -1px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
// &-bordered &-cover {
|
||||
// margin-top: -1px;
|
||||
// margin-right: -1px;
|
||||
// margin-left: -1px;
|
||||
// }
|
||||
|
||||
&-cover {
|
||||
> * {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
// &-cover {
|
||||
// > * {
|
||||
// display: block;
|
||||
// width: 100%;
|
||||
// }
|
||||
|
||||
img {
|
||||
border-radius: @card-radius @card-radius 0 0;
|
||||
}
|
||||
}
|
||||
// img {
|
||||
// border-radius: @card-radius @card-radius 0 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-actions {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
background: @card-actions-background;
|
||||
border-top: @border-width-base @border-style-base @border-color-split;
|
||||
.clearfix();
|
||||
// &-actions {
|
||||
// margin: 0;
|
||||
// padding: 0;
|
||||
// list-style: none;
|
||||
// background: @card-actions-background;
|
||||
// border-top: @border-width-base @border-style-base @border-color-split;
|
||||
// .clearfix();
|
||||
|
||||
& > li {
|
||||
float: left;
|
||||
margin: @card-actions-li-margin;
|
||||
color: @text-color-secondary;
|
||||
text-align: center;
|
||||
// & > li {
|
||||
// float: left;
|
||||
// margin: @card-actions-li-margin;
|
||||
// color: @text-color-secondary;
|
||||
// text-align: center;
|
||||
|
||||
.@{card-prefix-cls}-rtl & {
|
||||
float: right;
|
||||
}
|
||||
// .@{card-prefix-cls}-rtl & {
|
||||
// float: right;
|
||||
// }
|
||||
|
||||
> span {
|
||||
position: relative;
|
||||
display: block;
|
||||
min-width: 32px;
|
||||
font-size: @font-size-base;
|
||||
line-height: @line-height-base;
|
||||
cursor: pointer;
|
||||
// > span {
|
||||
// position: relative;
|
||||
// display: block;
|
||||
// min-width: 32px;
|
||||
// font-size: @font-size-base;
|
||||
// line-height: @line-height-base;
|
||||
// cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
// &:hover {
|
||||
// color: @primary-color;
|
||||
// transition: color 0.3s;
|
||||
// }
|
||||
|
||||
a:not(.@{ant-prefix}-btn),
|
||||
> .@{iconfont-css-prefix} {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
color: @text-color-secondary;
|
||||
line-height: 22px;
|
||||
transition: color 0.3s;
|
||||
// a:not(.@{ant-prefix}-btn),
|
||||
// > .@{iconfont-css-prefix} {
|
||||
// display: inline-block;
|
||||
// width: 100%;
|
||||
// color: @text-color-secondary;
|
||||
// line-height: 22px;
|
||||
// transition: color 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
// &:hover {
|
||||
// color: @primary-color;
|
||||
// }
|
||||
// }
|
||||
|
||||
> .@{iconfont-css-prefix} {
|
||||
font-size: @card-action-icon-size;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
// > .@{iconfont-css-prefix} {
|
||||
// font-size: @card-action-icon-size;
|
||||
// line-height: 22px;
|
||||
// }
|
||||
// }
|
||||
|
||||
&:not(:last-child) {
|
||||
border-right: @border-width-base @border-style-base @border-color-split;
|
||||
// &:not(:last-child) {
|
||||
// border-right: @border-width-base @border-style-base @border-color-split;
|
||||
|
||||
.@{card-prefix-cls}-rtl & {
|
||||
border-right: none;
|
||||
border-left: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// .@{card-prefix-cls}-rtl & {
|
||||
// border-right: none;
|
||||
// border-left: @border-width-base @border-style-base @border-color-split;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
&-type-inner &-head {
|
||||
padding: 0 @card-padding-base;
|
||||
background: @background-color-light;
|
||||
// &-type-inner &-head {
|
||||
// padding: 0 @card-padding-base;
|
||||
// background: @background-color-light;
|
||||
|
||||
&-title {
|
||||
padding: @card-inner-head-padding 0;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
}
|
||||
// &-title {
|
||||
// padding: @card-inner-head-padding 0;
|
||||
// font-size: @font-size-base;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-type-inner &-body {
|
||||
padding: 16px @card-padding-base;
|
||||
}
|
||||
// &-type-inner &-body {
|
||||
// padding: 16px @card-padding-base;
|
||||
// }
|
||||
|
||||
&-type-inner &-extra {
|
||||
padding: @card-inner-head-padding + 1.5px 0;
|
||||
}
|
||||
// &-type-inner &-extra {
|
||||
// padding: @card-inner-head-padding + 1.5px 0;
|
||||
// }
|
||||
|
||||
&-meta {
|
||||
margin: -4px 0;
|
||||
.clearfix();
|
||||
// &-meta {
|
||||
// margin: -4px 0;
|
||||
// .clearfix();
|
||||
|
||||
&-avatar {
|
||||
float: left;
|
||||
padding-right: 16px;
|
||||
// &-avatar {
|
||||
// float: left;
|
||||
// padding-right: 16px;
|
||||
|
||||
.@{card-prefix-cls}-rtl & {
|
||||
float: right;
|
||||
padding-right: 0;
|
||||
padding-left: 16px;
|
||||
}
|
||||
}
|
||||
// .@{card-prefix-cls}-rtl & {
|
||||
// float: right;
|
||||
// padding-right: 0;
|
||||
// padding-left: 16px;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-detail {
|
||||
overflow: hidden;
|
||||
// &-detail {
|
||||
// overflow: hidden;
|
||||
|
||||
> div:not(:last-child) {
|
||||
margin-bottom: @margin-xs;
|
||||
}
|
||||
}
|
||||
// > div:not(:last-child) {
|
||||
// margin-bottom: @margin-xs;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-title {
|
||||
overflow: hidden;
|
||||
color: @card-head-color;
|
||||
font-weight: 500;
|
||||
font-size: @font-size-lg;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
// &-title {
|
||||
// overflow: hidden;
|
||||
// color: @card-head-color;
|
||||
// font-weight: 500;
|
||||
// font-size: @font-size-lg;
|
||||
// white-space: nowrap;
|
||||
// text-overflow: ellipsis;
|
||||
// }
|
||||
|
||||
&-description {
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
}
|
||||
// &-description {
|
||||
// color: @text-color-secondary;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-loading {
|
||||
overflow: hidden;
|
||||
}
|
||||
// &-loading {
|
||||
// overflow: hidden;
|
||||
// }
|
||||
|
||||
&-loading &-body {
|
||||
user-select: none;
|
||||
}
|
||||
// &-loading &-body {
|
||||
// user-select: none;
|
||||
// }
|
||||
|
||||
&-loading-content {
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
// &-loading-content {
|
||||
// p {
|
||||
// margin: 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-loading-block {
|
||||
height: 14px;
|
||||
margin: 4px 0;
|
||||
background: linear-gradient(90deg, @gradient-min, @gradient-max, @gradient-min);
|
||||
background-size: 600% 600%;
|
||||
border-radius: @card-radius;
|
||||
animation: card-loading 1.4s ease infinite;
|
||||
}
|
||||
}
|
||||
// &-loading-block {
|
||||
// height: 14px;
|
||||
// margin: 4px 0;
|
||||
// background: linear-gradient(90deg, @gradient-min, @gradient-max, @gradient-min);
|
||||
// background-size: 600% 600%;
|
||||
// border-radius: @card-radius;
|
||||
// animation: card-loading 1.4s ease infinite;
|
||||
// }
|
||||
// }
|
||||
|
||||
@keyframes card-loading {
|
||||
0%,
|
||||
100% {
|
||||
background-position: 0 50%;
|
||||
}
|
||||
// @keyframes card-loading {
|
||||
// 0%,
|
||||
// 100% {
|
||||
// background-position: 0 50%;
|
||||
// }
|
||||
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
}
|
||||
// 50% {
|
||||
// background-position: 100% 50%;
|
||||
// }
|
||||
// }
|
||||
|
||||
@import './size';
|
||||
// @import './size';
|
||||
|
@ -1,7 +1,460 @@
|
||||
import '../../style/index.less';
|
||||
import './index.less';
|
||||
// import '../../style/index.less';
|
||||
// import './index.less';
|
||||
|
||||
// style dependencies
|
||||
import '../../tabs/style';
|
||||
import '../../row/style';
|
||||
import '../../col/style';
|
||||
// import '../../tabs/style';
|
||||
// import '../../row/style';
|
||||
// import '../../col/style';
|
||||
|
||||
// deps-lint-skip-all
|
||||
import { CSSObject, Keyframes } from '@ant-design/cssinjs';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
|
||||
import {
|
||||
resetComponent,
|
||||
GenerateStyle,
|
||||
genComponentStyleHook,
|
||||
FullToken,
|
||||
mergeToken,
|
||||
clearFix,
|
||||
} from '../../_util/theme';
|
||||
|
||||
interface CardToken extends FullToken<'Card'> {
|
||||
rootPrefixCls: string;
|
||||
cardHoverableHoverBorder: string;
|
||||
cardShadow: string;
|
||||
cardHeadHeight: number;
|
||||
cardHeadHeightSM: number;
|
||||
cardHeadPadding: number;
|
||||
cardPaddingBase: number;
|
||||
cardHeadTabsMarginBottom: number;
|
||||
cardInnerHeadPadding: number;
|
||||
cardActionsLiMargin: string;
|
||||
cardActionsIconSize: number;
|
||||
cardSkeletonBg: string;
|
||||
borderColorSplit: string;
|
||||
backgroundColorLight: string;
|
||||
gradientMin: string;
|
||||
gradientMax: string;
|
||||
}
|
||||
|
||||
// ============================== Motion ==============================
|
||||
const antCardLoading = new Keyframes('antCardLoading', {
|
||||
'0%, 100%': {
|
||||
backgroundPosition: '0 50%',
|
||||
},
|
||||
|
||||
'50%': {
|
||||
backgroundPosition: '100% 50%',
|
||||
},
|
||||
});
|
||||
|
||||
// ============================== Styles ==============================
|
||||
|
||||
// ============================== Head ==============================
|
||||
const genCardHeadStyle: GenerateStyle<CardToken> = (token): CSSObject => {
|
||||
const {
|
||||
rootPrefixCls,
|
||||
componentCls,
|
||||
cardHoverableHoverBorder,
|
||||
cardHeadHeight,
|
||||
cardHeadPadding,
|
||||
cardPaddingBase,
|
||||
cardHeadTabsMarginBottom,
|
||||
borderColorSplit,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
minHeight: cardHeadHeight,
|
||||
marginBottom: -1, // Fix card grid overflow bug: https://gw.alipayobjects.com/zos/rmsportal/XonYxBikwpgbqIQBeuhk.png
|
||||
padding: `0 ${cardPaddingBase}px`,
|
||||
color: token.colorTextHeading,
|
||||
fontWeight: 500, // FIXME: hardcode in v4
|
||||
fontSize: token.fontSizeLG,
|
||||
background: cardHoverableHoverBorder,
|
||||
borderBottom: `${token.controlLineWidth}px ${token.controlLineType} ${borderColorSplit}`,
|
||||
borderRadius: `${token.radiusBase}px ${token.radiusBase}px 0 0`,
|
||||
|
||||
...clearFix(),
|
||||
|
||||
'&-wrapper': {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
||||
'&-title': {
|
||||
display: 'inline-block',
|
||||
flex: 1,
|
||||
padding: `${cardHeadPadding}px 0`,
|
||||
overflow: 'hidden',
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
|
||||
[`
|
||||
> ${componentCls}-typography,
|
||||
> ${componentCls}-typography-edit-content
|
||||
`]: {
|
||||
insetInlineStart: 0,
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
},
|
||||
},
|
||||
|
||||
[`.${rootPrefixCls}-tabs-top`]: {
|
||||
clear: 'both',
|
||||
marginBottom: cardHeadTabsMarginBottom,
|
||||
color: token.colorText,
|
||||
fontWeight: 'normal',
|
||||
fontSize: token.fontSizeBase,
|
||||
|
||||
'&-bar': {
|
||||
borderBottom: `${token.controlLineWidth}px ${token.controlLineType} ${borderColorSplit}`,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Grid ==============================
|
||||
const genCardGridStyle: GenerateStyle<CardToken> = (token): CSSObject => {
|
||||
const { cardPaddingBase, borderColorSplit, cardShadow } = token;
|
||||
return {
|
||||
width: '33.33%', // FIXME: hardcode in v4
|
||||
padding: cardPaddingBase,
|
||||
border: 0,
|
||||
borderRadius: 0,
|
||||
boxShadow: `
|
||||
1px 0 0 0 ${borderColorSplit},
|
||||
0 1px 0 0 ${borderColorSplit},
|
||||
1px 1px 0 0 ${borderColorSplit},
|
||||
1px 0 0 0 ${borderColorSplit} inset,
|
||||
0 1px 0 0 ${borderColorSplit} inset;
|
||||
transition: all ${token.motionDurationSlow}
|
||||
`, // FIXME: hardcode in v4
|
||||
|
||||
'&-hoverable:hover': {
|
||||
position: 'relative',
|
||||
zIndex: 1,
|
||||
boxShadow: cardShadow,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Actions ==============================
|
||||
const genCardActionsStyle: GenerateStyle<CardToken> = (token): CSSObject => {
|
||||
const { componentCls, iconCls, cardActionsLiMargin, cardActionsIconSize, borderColorSplit } =
|
||||
token;
|
||||
return {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
listStyle: 'none',
|
||||
background: token.colorBgComponent,
|
||||
borderTop: `${token.controlLineWidth}px ${token.controlLineType} ${borderColorSplit}`,
|
||||
display: 'flex',
|
||||
...clearFix(),
|
||||
|
||||
'& > li': {
|
||||
margin: cardActionsLiMargin,
|
||||
color: token.colorTextSecondary,
|
||||
textAlign: 'center',
|
||||
|
||||
'> span': {
|
||||
position: 'relative',
|
||||
display: 'block',
|
||||
minWidth: 32, // FIXME: hardcode in v4
|
||||
fontSize: token.fontSizeBase,
|
||||
lineHeight: token.lineHeight,
|
||||
cursor: 'pointer',
|
||||
|
||||
'&:hover': {
|
||||
color: token.colorPrimary,
|
||||
transition: `color ${token.motionDurationSlow}`,
|
||||
},
|
||||
|
||||
[`a:not(${componentCls}-btn), > ${iconCls}`]: {
|
||||
display: 'inline-block',
|
||||
width: '100%',
|
||||
color: token.colorTextSecondary,
|
||||
lineHeight: '22px', // FIXME: hardcode in v4
|
||||
transition: `color ${token.motionDurationSlow}`,
|
||||
|
||||
'&:hover': {
|
||||
color: token.colorPrimary,
|
||||
},
|
||||
},
|
||||
|
||||
[`> ${iconCls}`]: {
|
||||
fontSize: cardActionsIconSize,
|
||||
lineHeight: '22px', // FIXME: hardcode in v4
|
||||
},
|
||||
},
|
||||
|
||||
'&:not(:last-child)': {
|
||||
borderInlineEnd: `${token.controlLineWidth}px ${token.controlLineType} ${borderColorSplit}`,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Meta ==============================
|
||||
const genCardMetaStyle: GenerateStyle<CardToken> = (token): CSSObject => ({
|
||||
margin: '-4px 0', // FIXME: hardcode in v4
|
||||
display: 'flex',
|
||||
...clearFix(),
|
||||
|
||||
'&-avatar': {
|
||||
paddingInlineEnd: 16, // FIXME: hardcode in v4
|
||||
},
|
||||
|
||||
'&-detail': {
|
||||
overflow: 'hidden',
|
||||
|
||||
'> div:not(:last-child)': {
|
||||
marginBottom: token.marginXS,
|
||||
},
|
||||
},
|
||||
|
||||
'&-title': {
|
||||
overflow: 'hidden',
|
||||
color: token.colorTextHeading,
|
||||
fontWeight: 500, // FIXME: hardcode in v4
|
||||
fontSize: token.fontSizeLG,
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
|
||||
'&-description': {
|
||||
color: token.colorTextSecondary,
|
||||
},
|
||||
});
|
||||
|
||||
// ============================== Inner ==============================
|
||||
const genCardTypeInnerStyle: GenerateStyle<CardToken> = (token): CSSObject => {
|
||||
const { componentCls, cardPaddingBase, backgroundColorLight, cardInnerHeadPadding } = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-head`]: {
|
||||
padding: `0 ${cardPaddingBase}px`,
|
||||
background: backgroundColorLight,
|
||||
|
||||
'&-title': {
|
||||
padding: `${cardInnerHeadPadding}px 0`,
|
||||
fontSize: token.fontSizeBase,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-body`]: {
|
||||
padding: `16px ${cardPaddingBase}px`, // FIXME: hardcode in v4
|
||||
},
|
||||
|
||||
[`${componentCls}-extra`]: {
|
||||
padding: `${cardInnerHeadPadding + 1.5}px 0`,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Loading ==============================
|
||||
const genCardLoadingStyle: GenerateStyle<CardToken> = (token): CSSObject => {
|
||||
const { componentCls, gradientMin, gradientMax } = token;
|
||||
|
||||
return {
|
||||
overflow: 'hidden',
|
||||
|
||||
[`${componentCls}-body`]: {
|
||||
userSelect: 'none',
|
||||
},
|
||||
|
||||
[`${componentCls}-loading-content p`]: {
|
||||
margin: 0,
|
||||
},
|
||||
|
||||
[`${componentCls}-loading-block`]: {
|
||||
height: 14, // FIXME: hardcode in v4
|
||||
margin: '4px 0', // FIXME: hardcode in v4
|
||||
background: `linear-gradient(90deg, ${gradientMin}, ${gradientMax}, ${gradientMin})`,
|
||||
backgroundSize: '600% 600%',
|
||||
borderRadius: token.radiusBase,
|
||||
animationName: antCardLoading,
|
||||
animationDuration: '1.4s', // FIXME: hardcode
|
||||
animationTimingFunction: 'ease',
|
||||
animationIterationCount: 'infinite',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Basic ==============================
|
||||
const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
|
||||
const {
|
||||
componentCls,
|
||||
cardHoverableHoverBorder,
|
||||
cardShadow,
|
||||
cardHeadHeight,
|
||||
cardHeadPadding,
|
||||
cardPaddingBase,
|
||||
borderColorSplit,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[componentCls]: {
|
||||
...resetComponent(token),
|
||||
|
||||
position: 'relative',
|
||||
background: token.colorBgComponent,
|
||||
borderRadius: token.radiusBase,
|
||||
|
||||
[`${componentCls}-head`]: genCardHeadStyle(token),
|
||||
|
||||
[`${componentCls}-extra`]: {
|
||||
// https://stackoverflow.com/a/22429853/3040605
|
||||
marginInlineStart: 'auto',
|
||||
padding: '',
|
||||
color: '',
|
||||
fontWeight: 'normal',
|
||||
fontSize: token.fontSizeBase,
|
||||
},
|
||||
|
||||
[`${componentCls}-body`]: {
|
||||
padding: cardPaddingBase,
|
||||
...clearFix(),
|
||||
},
|
||||
|
||||
[`${componentCls}-grid`]: genCardGridStyle(token),
|
||||
|
||||
[`${componentCls}-cover`]: {
|
||||
'> *': {
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
},
|
||||
|
||||
img: {
|
||||
borderRadius: `${token.radiusBase}px ${token.radiusBase}px 0 0`,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-actions`]: genCardActionsStyle(token),
|
||||
|
||||
[`${componentCls}-meta`]: genCardMetaStyle(token),
|
||||
},
|
||||
|
||||
[`${componentCls}-bordered`]: {
|
||||
border: `${token.controlLineWidth}px ${token.controlLineType} ${borderColorSplit}`,
|
||||
|
||||
[`${componentCls}-cover`]: {
|
||||
marginTop: -1,
|
||||
marginInlineStart: -1,
|
||||
marginInlineEnd: -1,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-hoverable`]: {
|
||||
cursor: 'pointer',
|
||||
transition: `box-shadow ${token.motionDurationSlow}, border-color ${token.motionDurationSlow}`,
|
||||
|
||||
'&:hover': {
|
||||
borderColor: cardHoverableHoverBorder,
|
||||
boxShadow: cardShadow,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-contain-grid`]: {
|
||||
[`${componentCls}-body`]: {
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
|
||||
[`&:not(${componentCls}-loading) ${componentCls}-body`]: {
|
||||
margin: {
|
||||
_skip_check_: true,
|
||||
value: '-1px 0 0 -1px', // FIXME: hardcode in v4
|
||||
},
|
||||
padding: 0,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-contain-tabs`]: {
|
||||
[`> ${componentCls}-head`]: {
|
||||
[`${componentCls}-head-title`]: {
|
||||
minHeight: cardHeadHeight - cardHeadPadding,
|
||||
paddingBottom: 0,
|
||||
},
|
||||
|
||||
[`${componentCls}-extra`]: {
|
||||
paddingBottom: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-type-inner`]: genCardTypeInnerStyle(token),
|
||||
|
||||
[`${componentCls}-loading`]: genCardLoadingStyle(token),
|
||||
|
||||
[`${componentCls}-rtl`]: {
|
||||
direction: 'rtl',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Size ==============================
|
||||
const genCardSizeStyle: GenerateStyle<CardToken> = (token): CSSObject => {
|
||||
const { componentCls, cardHeadHeightSM, cardPaddingBase, cardHeadPadding } = token;
|
||||
const cardPaddingBaseSM = cardPaddingBase / 2;
|
||||
const cardHeadPaddingSM = cardHeadPadding / 2;
|
||||
|
||||
return {
|
||||
[`${componentCls}-small`]: {
|
||||
[`> ${componentCls}-head`]: {
|
||||
minHeight: cardHeadHeightSM,
|
||||
padding: `0 ${cardPaddingBaseSM}px`,
|
||||
fontSize: token.fontSizeBase,
|
||||
|
||||
[`> ${componentCls}-head-wrapper`]: {
|
||||
[`> ${componentCls}-head-title`]: {
|
||||
padding: `${cardHeadPaddingSM}px 0`,
|
||||
},
|
||||
|
||||
[`> ${componentCls}-extra`]: {
|
||||
padding: `${cardHeadPaddingSM}px 0`,
|
||||
fontSize: token.fontSizeBase,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`> ${componentCls}-body`]: {
|
||||
padding: cardPaddingBaseSM,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook('Card', (token, { rootPrefixCls }) => {
|
||||
const cardToken = mergeToken<CardToken>(token, {
|
||||
rootPrefixCls,
|
||||
|
||||
cardHoverableHoverBorder: 'transparent', // FIXME: hardcode in v4
|
||||
cardShadow: `
|
||||
0 1px 2px -2px ${new TinyColor('rgba(0, 0, 0, 0.16)').toRgbString()},
|
||||
0 3px 6px 0 ${new TinyColor('rgba(0, 0, 0, 0.12)').toRgbString()},
|
||||
0 5px 12px 4px ${new TinyColor('rgba(0, 0, 0, 0.09)').toRgbString()}
|
||||
`, // FIXME: hardcode in v4
|
||||
cardHeadHeight: 48, // FIXME: hardcode in v4
|
||||
cardHeadHeightSM: 30, // FIXME: hardcode in v4
|
||||
cardHeadPadding: 16, // FIXME: hardcode in v4
|
||||
cardPaddingBase: 24, // FIXME: hardcode in v4
|
||||
cardHeadTabsMarginBottom: -17, // FIXME: hardcode in v4
|
||||
cardInnerHeadPadding: 12, // FIXME: hardcode in v4
|
||||
cardActionsLiMargin: '12px 0', // FIXME: hardcode in v4
|
||||
cardActionsIconSize: 16, // FIXME: hardcode in v4
|
||||
borderColorSplit: new TinyColor({ h: 0, s: 0, v: 94 }).toHexString(), // FIXME: hardcode in v4
|
||||
backgroundColorLight: new TinyColor({ h: 0, s: 0, v: 98 }).toHexString(), // FIXME: hardcode in v4
|
||||
gradientMin: new TinyColor('#cfd8dc').setAlpha(0.2).toRgbString(), // FIXME: hardcode in v4
|
||||
gradientMax: new TinyColor('#cfd8dc').setAlpha(0.4).toRgbString(), // FIXME: hardcode in v4
|
||||
});
|
||||
|
||||
return [
|
||||
// Style
|
||||
genCardStyle(cardToken),
|
||||
|
||||
// Size
|
||||
genCardSizeStyle(cardToken),
|
||||
];
|
||||
});
|
||||
|
@ -1,20 +1,20 @@
|
||||
.@{card-prefix-cls}-small {
|
||||
> .@{card-prefix-cls}-head {
|
||||
min-height: @card-head-height-sm;
|
||||
padding: 0 @card-padding-base-sm;
|
||||
font-size: @card-head-font-size-sm;
|
||||
// .@{card-prefix-cls}-small {
|
||||
// > .@{card-prefix-cls}-head {
|
||||
// min-height: @card-head-height-sm;
|
||||
// padding: 0 @card-padding-base-sm;
|
||||
// font-size: @card-head-font-size-sm;
|
||||
|
||||
> .@{card-prefix-cls}-head-wrapper {
|
||||
> .@{card-prefix-cls}-head-title {
|
||||
padding: @card-head-padding-sm 0;
|
||||
}
|
||||
> .@{card-prefix-cls}-extra {
|
||||
padding: @card-head-padding-sm 0;
|
||||
font-size: @card-head-font-size-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .@{card-prefix-cls}-body {
|
||||
padding: @card-padding-base-sm;
|
||||
}
|
||||
}
|
||||
// > .@{card-prefix-cls}-head-wrapper {
|
||||
// > .@{card-prefix-cls}-head-title {
|
||||
// padding: @card-head-padding-sm 0;
|
||||
// }
|
||||
// > .@{card-prefix-cls}-extra {
|
||||
// padding: @card-head-padding-sm 0;
|
||||
// font-size: @card-head-font-size-sm;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// > .@{card-prefix-cls}-body {
|
||||
// padding: @card-padding-base-sm;
|
||||
// }
|
||||
// }
|
||||
|
@ -3,7 +3,7 @@ import { mount } from 'enzyme';
|
||||
import Carousel from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
import { sleep, render } from '../../../tests/utils';
|
||||
|
||||
describe('Carousel', () => {
|
||||
mountTest(Carousel);
|
||||
@ -99,21 +99,28 @@ describe('Carousel', () => {
|
||||
|
||||
describe('should active when children change', () => {
|
||||
it('should active', () => {
|
||||
const wrapper = mount(<Carousel />);
|
||||
wrapper.setProps({
|
||||
children: <div />,
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.slick-active').length).toBeTruthy();
|
||||
const { rerender, container } = render(<Carousel />);
|
||||
expect(container.querySelector('.slick-active')).toBeFalsy();
|
||||
|
||||
// Update children
|
||||
rerender(
|
||||
<Carousel>
|
||||
<div />
|
||||
</Carousel>,
|
||||
);
|
||||
expect(container.querySelector('.slick-active')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should keep initialSlide', () => {
|
||||
const wrapper = mount(<Carousel initialSlide={1} />);
|
||||
wrapper.setProps({
|
||||
children: [<div key="1" />, <div key="2" />, <div key="3" />],
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.slick-dots li').at(1).hasClass('slick-active')).toBeTruthy();
|
||||
const { rerender, container } = render(<Carousel initialSlide={1} />);
|
||||
rerender(
|
||||
<Carousel initialSlide={1}>
|
||||
<div key="1" />
|
||||
<div key="2" />
|
||||
<div key="3" />
|
||||
</Carousel>,
|
||||
);
|
||||
expect(container.querySelectorAll('.slick-dots li')[1]).toHaveClass('slick-active');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -31,7 +31,17 @@ export interface CarouselRef {
|
||||
}
|
||||
|
||||
const Carousel = React.forwardRef<CarouselRef, CarouselProps>(
|
||||
({ dots = true, arrows = false, draggable = false, dotPosition = 'bottom', ...props }, ref) => {
|
||||
(
|
||||
{
|
||||
dots = true,
|
||||
arrows = false,
|
||||
draggable = false,
|
||||
dotPosition = 'bottom',
|
||||
vertical = dotPosition === 'left' || dotPosition === 'right',
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const slickRef = React.useRef<any>();
|
||||
|
||||
@ -61,6 +71,7 @@ const Carousel = React.forwardRef<CarouselRef, CarouselProps>(
|
||||
}, [props.children]);
|
||||
|
||||
const newProps = {
|
||||
vertical,
|
||||
...props,
|
||||
};
|
||||
|
||||
@ -70,7 +81,6 @@ const Carousel = React.forwardRef<CarouselRef, CarouselProps>(
|
||||
|
||||
const prefixCls = getPrefixCls('carousel', newProps.prefixCls);
|
||||
const dotsClass = 'slick-dots';
|
||||
newProps.vertical = dotPosition === 'left' || dotPosition === 'right';
|
||||
|
||||
const enableDots = !!dots;
|
||||
const dsClass = classNames(
|
||||
|
@ -1,20 +1,15 @@
|
||||
// deps-lint-skip-all
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import {
|
||||
resetComponent,
|
||||
GenerateStyle,
|
||||
genComponentStyleHook,
|
||||
FullToken,
|
||||
mergeToken,
|
||||
} from '../../_util/theme';
|
||||
import { genComponentStyleHook, resetComponent } from '../../_util/theme';
|
||||
import type { GenerateStyle, FullToken } from '../../_util/theme';
|
||||
|
||||
interface CarouselToken extends FullToken<'Carousel'> {
|
||||
export interface ComponentToken {
|
||||
carouselDotWidth: CSSObject['width'];
|
||||
carouselDotHeight: CSSObject['height'];
|
||||
carouselDotActiveWidth: CSSObject['width'];
|
||||
}
|
||||
|
||||
const genCarouselStyle: GenerateStyle<CarouselToken, CSSObject> = token => {
|
||||
const genCarouselStyle: GenerateStyle<FullToken<'Carousel'>> = token => {
|
||||
const { componentCls, antCls } = token;
|
||||
|
||||
return {
|
||||
@ -127,7 +122,7 @@ const genCarouselStyle: GenerateStyle<CarouselToken, CSSObject> = token => {
|
||||
// FIXME hardcode in v4
|
||||
width: 20,
|
||||
height: 20,
|
||||
marginTop: '-10px',
|
||||
marginTop: -10,
|
||||
padding: 0,
|
||||
color: 'transparent',
|
||||
fontSize: 0,
|
||||
@ -157,7 +152,7 @@ const genCarouselStyle: GenerateStyle<CarouselToken, CSSObject> = token => {
|
||||
insetInlineStart: -25,
|
||||
|
||||
'&::before': {
|
||||
content: '←',
|
||||
content: '"←"',
|
||||
},
|
||||
},
|
||||
|
||||
@ -166,7 +161,7 @@ const genCarouselStyle: GenerateStyle<CarouselToken, CSSObject> = token => {
|
||||
insetInlineEnd: -25,
|
||||
|
||||
'&::before': {
|
||||
content: '→',
|
||||
content: '"→"',
|
||||
},
|
||||
},
|
||||
|
||||
@ -186,12 +181,12 @@ const genCarouselStyle: GenerateStyle<CarouselToken, CSSObject> = token => {
|
||||
|
||||
'&-bottom': {
|
||||
// FIXME hardcode in v4
|
||||
bottom: '12px',
|
||||
bottom: 12,
|
||||
},
|
||||
|
||||
'&-top': {
|
||||
// FIXME hardcode in v4
|
||||
top: '12px',
|
||||
top: 12,
|
||||
bottom: 'auto',
|
||||
},
|
||||
|
||||
@ -250,7 +245,7 @@ const genCarouselStyle: GenerateStyle<CarouselToken, CSSObject> = token => {
|
||||
};
|
||||
};
|
||||
|
||||
const genCarouselVerticalStyle: GenerateStyle<CarouselToken, CSSObject> = token => {
|
||||
const genCarouselVerticalStyle: GenerateStyle<FullToken<'Carousel'>> = token => {
|
||||
const { componentCls } = token;
|
||||
|
||||
const reverseSizeOfDot = {
|
||||
@ -298,7 +293,7 @@ const genCarouselVerticalStyle: GenerateStyle<CarouselToken, CSSObject> = token
|
||||
};
|
||||
};
|
||||
|
||||
const genCarouselRtlStyle: GenerateStyle<CarouselToken> = token => {
|
||||
const genCarouselRtlStyle: GenerateStyle<FullToken<'Carousel'>> = token => {
|
||||
const { componentCls } = token;
|
||||
|
||||
return [
|
||||
@ -327,16 +322,13 @@ const genCarouselRtlStyle: GenerateStyle<CarouselToken> = token => {
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook('Carousel', token => {
|
||||
const carouselToken = mergeToken<CarouselToken>(token, {
|
||||
export default genComponentStyleHook(
|
||||
'Carousel',
|
||||
token => [genCarouselStyle(token), genCarouselVerticalStyle(token), genCarouselRtlStyle(token)],
|
||||
{
|
||||
// FIXME
|
||||
carouselDotWidth: 16,
|
||||
carouselDotHeight: 3,
|
||||
carouselDotActiveWidth: 24,
|
||||
});
|
||||
return [
|
||||
genCarouselStyle(carouselToken),
|
||||
genCarouselVerticalStyle(carouselToken),
|
||||
genCarouselRtlStyle(carouselToken),
|
||||
];
|
||||
});
|
||||
},
|
||||
);
|
||||
|
@ -34,7 +34,7 @@ exports[`renders ./components/cascader/demo/basic.md extend context correctly 1`
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -182,7 +182,7 @@ exports[`renders ./components/cascader/demo/change-on-select.md extend context c
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -332,7 +332,7 @@ exports[`renders ./components/cascader/demo/custom-dropdown.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div>
|
||||
@ -507,7 +507,7 @@ exports[`renders ./components/cascader/demo/custom-render.md extend context corr
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -660,7 +660,7 @@ exports[`renders ./components/cascader/demo/custom-trigger.md extend context cor
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -785,7 +785,7 @@ exports[`renders ./components/cascader/demo/default-value.md extend context corr
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -959,7 +959,7 @@ exports[`renders ./components/cascader/demo/disabled-option.md extend context co
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1109,7 +1109,7 @@ exports[`renders ./components/cascader/demo/fields-name.md extend context correc
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1257,7 +1257,7 @@ exports[`renders ./components/cascader/demo/hover.md extend context correctly 1`
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1405,7 +1405,7 @@ exports[`renders ./components/cascader/demo/lazy.md extend context correctly 1`]
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1570,7 +1570,7 @@ exports[`renders ./components/cascader/demo/multiple.md extend context correctly
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1792,7 +1792,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1940,7 +1940,7 @@ exports[`renders ./components/cascader/demo/search.md extend context correctly 1
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -2119,7 +2119,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -2310,7 +2310,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -2474,7 +2474,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -2621,7 +2621,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -2768,7 +2768,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -2928,7 +2928,7 @@ exports[`renders ./components/cascader/demo/status.md extend context correctly 1
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -3080,7 +3080,7 @@ exports[`renders ./components/cascader/demo/status.md extend context correctly 1
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -3192,7 +3192,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -3341,7 +3341,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -3472,7 +3472,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -3621,7 +3621,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown"
|
||||
style="opacity:0;pointer-events:none;min-width:auto"
|
||||
style="opacity:0;min-width:auto"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
|
@ -3,7 +3,7 @@
|
||||
exports[`Cascader can be selected 1`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: auto;"
|
||||
style="opacity: 0; min-width: auto;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -135,7 +135,7 @@ exports[`Cascader can be selected 1`] = `
|
||||
exports[`Cascader can be selected 2`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: auto;"
|
||||
style="opacity: 0; min-width: auto;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -285,7 +285,7 @@ exports[`Cascader can be selected 2`] = `
|
||||
exports[`Cascader can be selected 3`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-leave ant-slide-up-leave-start ant-slide-up"
|
||||
style="pointer-events: none; min-width: auto;"
|
||||
style="min-width: auto; pointer-events: none;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -435,7 +435,7 @@ exports[`Cascader can be selected 3`] = `
|
||||
exports[`Cascader can be selected in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-cascader-dropdown-rtl ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: auto;"
|
||||
style="opacity: 0; min-width: auto;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -567,7 +567,7 @@ exports[`Cascader can be selected in RTL direction 1`] = `
|
||||
exports[`Cascader can be selected in RTL direction 2`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-cascader-dropdown-rtl ant-slide-up-leave ant-slide-up-leave-start ant-slide-up"
|
||||
style="pointer-events: none; min-width: auto;"
|
||||
style="min-width: auto; pointer-events: none;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -717,7 +717,7 @@ exports[`Cascader can be selected in RTL direction 2`] = `
|
||||
exports[`Cascader can be selected in RTL direction 3`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-cascader-dropdown-rtl ant-slide-up-leave ant-slide-up-leave-start ant-slide-up"
|
||||
style="pointer-events: none; min-width: auto;"
|
||||
style="min-width: auto; pointer-events: none;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -914,7 +914,7 @@ exports[`Cascader legacy props should support showCheckedStrategy child 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: auto;"
|
||||
style="opacity: 0; min-width: auto;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1068,7 +1068,7 @@ exports[`Cascader legacy props should support showCheckedStrategy parent 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: auto;"
|
||||
style="opacity: 0; min-width: auto;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1175,7 +1175,7 @@ exports[`Cascader legacy props should support showCheckedStrategy parent 1`] = `
|
||||
exports[`Cascader popup correctly with defaultValue 1`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: auto;"
|
||||
style="opacity: 0; min-width: auto;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1359,7 +1359,7 @@ exports[`Cascader popup correctly with defaultValue RTL 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-cascader-dropdown-rtl ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: auto;"
|
||||
style="opacity: 0; min-width: auto;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1622,7 +1622,7 @@ exports[`Cascader rtl render component should be rendered correctly in RTL direc
|
||||
exports[`Cascader should highlight keyword and filter when search in Cascader 1`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: 0;"
|
||||
style="opacity: 0; min-width: 0;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1682,7 +1682,7 @@ exports[`Cascader should highlight keyword and filter when search in Cascader 1`
|
||||
exports[`Cascader should highlight keyword and filter when search in Cascader with same field name of label and value 1`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: 0;"
|
||||
style="opacity: 0; min-width: 0;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1747,7 +1747,7 @@ exports[`Cascader should highlight keyword and filter when search in Cascader wi
|
||||
exports[`Cascader should render not found content 1`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-select-dropdown-empty ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: 0;"
|
||||
style="opacity: 0; min-width: 0;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -1823,7 +1823,7 @@ exports[`Cascader should render not found content 1`] = `
|
||||
exports[`Cascader should show not found content when options.length is 0 1`] = `
|
||||
<div
|
||||
class="ant-select-dropdown ant-cascader-dropdown ant-select-dropdown-empty ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
|
||||
style="opacity: 0; pointer-events: none; min-width: 0;"
|
||||
style="opacity: 0; min-width: 0;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
|
@ -66,5 +66,5 @@ const App = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default () => <App />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -29,6 +29,7 @@
|
||||
// }
|
||||
|
||||
// &-menu {
|
||||
// flex-grow: 1;
|
||||
// min-width: 111px;
|
||||
// height: 180px;
|
||||
// margin: 0;
|
||||
|
@ -21,7 +21,7 @@ export interface ComponentToken {
|
||||
type CascaderToken = FullToken<'Cascader'>;
|
||||
|
||||
// =============================== Base ===============================
|
||||
const genBaseStyle: GenerateStyle<CascaderToken> = (token, hashId) => {
|
||||
const genBaseStyle: GenerateStyle<CascaderToken> = token => {
|
||||
const { prefixCls, componentCls } = token;
|
||||
const cascaderMenuItemCls = `${componentCls}-menu-item`;
|
||||
const iconCls = `
|
||||
@ -49,7 +49,7 @@ const genBaseStyle: GenerateStyle<CascaderToken> = (token, hashId) => {
|
||||
{
|
||||
[`${componentCls}-dropdown`]: [
|
||||
// ==================== Checkbox ====================
|
||||
getCheckboxStyle(`${prefixCls}-checkbox`, token, hashId!),
|
||||
getCheckboxStyle(`${prefixCls}-checkbox`, token),
|
||||
{
|
||||
[componentCls]: {
|
||||
// ================== Checkbox ==================
|
||||
@ -81,6 +81,7 @@ const genBaseStyle: GenerateStyle<CascaderToken> = (token, hashId) => {
|
||||
|
||||
// >>> Menu
|
||||
'&-menu': {
|
||||
flexGrow: 1,
|
||||
minWidth: token.controlItemWidth,
|
||||
height: token.dropdownHeight,
|
||||
margin: `-${token.paddingXS}px 0`,
|
||||
@ -157,12 +158,8 @@ const genBaseStyle: GenerateStyle<CascaderToken> = (token, hashId) => {
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook(
|
||||
'Cascader',
|
||||
(token, { hashId }) => [genBaseStyle(token, hashId)],
|
||||
{
|
||||
controlWidth: 184,
|
||||
controlItemWidth: 111,
|
||||
dropdownHeight: 180,
|
||||
},
|
||||
);
|
||||
export default genComponentStyleHook('Cascader', token => [genBaseStyle(token)], {
|
||||
controlWidth: 184,
|
||||
controlItemWidth: 111,
|
||||
dropdownHeight: 180,
|
||||
});
|
||||
|
@ -25,7 +25,7 @@ exports[`CheckboxGroup passes prefixCls down to checkbox 1`] = `
|
||||
</label>
|
||||
<label
|
||||
class="my-checkbox-wrapper my-checkbox-group-item"
|
||||
style="font-size:12px"
|
||||
style="font-size: 12px;"
|
||||
>
|
||||
<span
|
||||
class="my-checkbox"
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
import Checkbox from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import { resetWarned } from '../../_util/devWarning';
|
||||
@ -15,12 +15,14 @@ describe('Checkbox', () => {
|
||||
const onMouseEnter = jest.fn();
|
||||
const onMouseLeave = jest.fn();
|
||||
|
||||
const wrapper = mount(<Checkbox onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />);
|
||||
const { container } = render(
|
||||
<Checkbox onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />,
|
||||
);
|
||||
|
||||
wrapper.find('label').simulate('mouseenter');
|
||||
fireEvent.mouseEnter(container.querySelector('label'));
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
|
||||
wrapper.find('label').simulate('mouseleave');
|
||||
fireEvent.mouseLeave(container.querySelector('label'));
|
||||
expect(onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@ -28,7 +30,7 @@ describe('Checkbox', () => {
|
||||
resetWarned();
|
||||
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
mount(<Checkbox value />);
|
||||
render(<Checkbox value />);
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Checkbox] `value` is not a valid prop, do you mean `checked`?',
|
||||
);
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { useState } from 'react';
|
||||
import { mount, render } from 'enzyme';
|
||||
import Collapse from '../../collapse';
|
||||
import Table from '../../table';
|
||||
import Checkbox from '../index';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
import Input from '../../input';
|
||||
|
||||
describe('CheckboxGroup', () => {
|
||||
@ -13,16 +13,16 @@ describe('CheckboxGroup', () => {
|
||||
|
||||
it('should work basically', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Checkbox.Group options={['Apple', 'Pear', 'Orange']} onChange={onChange} />,
|
||||
);
|
||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
|
||||
expect(onChange).toHaveBeenCalledWith(['Apple']);
|
||||
wrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
|
||||
expect(onChange).toHaveBeenCalledWith(['Apple', 'Pear']);
|
||||
wrapper.find('.ant-checkbox-input').at(2).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[2]);
|
||||
expect(onChange).toHaveBeenCalledWith(['Apple', 'Pear', 'Orange']);
|
||||
wrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
|
||||
expect(onChange).toHaveBeenCalledWith(['Apple', 'Orange']);
|
||||
});
|
||||
|
||||
@ -34,12 +34,12 @@ describe('CheckboxGroup', () => {
|
||||
{ label: 'Pear', value: 'Pear' },
|
||||
];
|
||||
|
||||
const groupWrapper = mount(
|
||||
const { container } = render(
|
||||
<Checkbox.Group options={options} onChange={onChangeGroup} disabled />,
|
||||
);
|
||||
groupWrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
|
||||
expect(onChangeGroup).not.toHaveBeenCalled();
|
||||
groupWrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
|
||||
expect(onChangeGroup).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@ -51,17 +51,17 @@ describe('CheckboxGroup', () => {
|
||||
{ label: 'Orange', value: 'Orange', disabled: true },
|
||||
];
|
||||
|
||||
const groupWrapper = mount(<Checkbox.Group options={options} onChange={onChangeGroup} />);
|
||||
groupWrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
const { container } = render(<Checkbox.Group options={options} onChange={onChangeGroup} />);
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
|
||||
expect(onChangeGroup).toHaveBeenCalledWith(['Apple']);
|
||||
groupWrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
|
||||
expect(onChangeGroup).toHaveBeenCalledWith(['Apple']);
|
||||
});
|
||||
|
||||
it('all children should have a name property', () => {
|
||||
const wrapper = mount(<Checkbox.Group name="checkboxgroup" options={['Yes', 'No']} />);
|
||||
wrapper.find('input[type="checkbox"]').forEach(el => {
|
||||
expect(el.props().name).toEqual('checkboxgroup');
|
||||
const { container } = render(<Checkbox.Group name="checkboxgroup" options={['Yes', 'No']} />);
|
||||
[...container.querySelectorAll('input[type="checkbox"]')].forEach(el => {
|
||||
expect(el.getAttribute('name')).toEqual('checkboxgroup');
|
||||
});
|
||||
});
|
||||
|
||||
@ -71,9 +71,9 @@ describe('CheckboxGroup', () => {
|
||||
{ label: 'Orange', value: 'Orange', style: { fontSize: 12 } },
|
||||
];
|
||||
|
||||
const wrapper = render(<Checkbox.Group prefixCls="my-checkbox" options={options} />);
|
||||
const { container } = render(<Checkbox.Group prefixCls="my-checkbox" options={options} />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should be controlled by value', () => {
|
||||
@ -81,23 +81,22 @@ describe('CheckboxGroup', () => {
|
||||
{ label: 'Apple', value: 'Apple' },
|
||||
{ label: 'Orange', value: 'Orange' },
|
||||
];
|
||||
|
||||
const wrapper = mount(<Checkbox.Group options={options} />);
|
||||
expect(wrapper.find('.ant-checkbox-checked').length).toBe(0);
|
||||
wrapper.setProps({ value: ['Apple'] });
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-checkbox-checked').length).toBe(1);
|
||||
const renderCheckbox = props => <Checkbox.Group {...props} />;
|
||||
const { container, rerender } = render(renderCheckbox({ options }));
|
||||
expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(0);
|
||||
rerender(renderCheckbox({ options, value: 'Apple' }));
|
||||
expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(1);
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/12642
|
||||
it('should trigger onChange in sub Checkbox', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Checkbox.Group>
|
||||
<Checkbox value="my" onChange={onChange} />
|
||||
</Checkbox.Group>,
|
||||
);
|
||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
expect(onChange.mock.calls[0][0].target.value).toEqual('my');
|
||||
});
|
||||
@ -105,40 +104,44 @@ describe('CheckboxGroup', () => {
|
||||
// https://github.com/ant-design/ant-design/issues/16376
|
||||
it('onChange should filter removed value', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container, rerender } = render(
|
||||
<Checkbox.Group defaultValue={[1]} onChange={onChange}>
|
||||
<Checkbox key={1} value={1} />
|
||||
<Checkbox key={2} value={2} />
|
||||
</Checkbox.Group>,
|
||||
);
|
||||
|
||||
wrapper.setProps({
|
||||
children: [<Checkbox key={2} value={2} />],
|
||||
});
|
||||
|
||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
rerender(
|
||||
<Checkbox.Group defaultValue={[1]} onChange={onChange}>
|
||||
<Checkbox key={2} value={2} />
|
||||
</Checkbox.Group>,
|
||||
);
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith([2]);
|
||||
});
|
||||
|
||||
it('checkbox should register value again after value changed', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container, rerender } = render(
|
||||
<Checkbox.Group defaultValue={[1]} onChange={onChange}>
|
||||
<Checkbox key={1} value={1} />
|
||||
</Checkbox.Group>,
|
||||
);
|
||||
|
||||
wrapper.setProps({
|
||||
children: [<Checkbox key={1} value={2} />],
|
||||
});
|
||||
expect(wrapper.find('.ant-checkbox-input').at(0).prop('checked')).toBe(false);
|
||||
rerender(
|
||||
<Checkbox.Group defaultValue={[1]} onChange={onChange}>
|
||||
<Checkbox key={1} value={2} />
|
||||
</Checkbox.Group>,
|
||||
);
|
||||
|
||||
expect(container.querySelector('.ant-checkbox-input')).toHaveAttribute('checked');
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/17297
|
||||
it('onChange should keep the order of the original values', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Checkbox.Group onChange={onChange}>
|
||||
<Checkbox key={1} value={1} />
|
||||
<Checkbox key={2} value={2} />
|
||||
@ -146,20 +149,19 @@ describe('CheckboxGroup', () => {
|
||||
<Checkbox key={4} value={4} />
|
||||
</Checkbox.Group>,
|
||||
);
|
||||
|
||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
|
||||
expect(onChange).toHaveBeenCalledWith([1]);
|
||||
wrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
|
||||
expect(onChange).toHaveBeenCalledWith([1, 2]);
|
||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
|
||||
expect(onChange).toHaveBeenCalledWith([2]);
|
||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
|
||||
expect(onChange).toHaveBeenCalledWith([1, 2]);
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/21134
|
||||
it('should work when checkbox is wrapped by other components', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Checkbox.Group>
|
||||
<Collapse bordered={false}>
|
||||
<Collapse.Panel header="test panel">
|
||||
@ -170,28 +172,31 @@ describe('CheckboxGroup', () => {
|
||||
</Collapse>
|
||||
</Checkbox.Group>,
|
||||
);
|
||||
wrapper.find('.ant-collapse-item').at(0).find('.ant-collapse-header').simulate('click');
|
||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
expect(wrapper.find('.ant-checkbox-checked').length).toBe(1);
|
||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
expect(wrapper.find('.ant-checkbox-checked').length).toBe(0);
|
||||
|
||||
fireEvent.click(
|
||||
container.querySelector('.ant-collapse-item').querySelector('.ant-collapse-header'),
|
||||
);
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(1);
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(0);
|
||||
});
|
||||
|
||||
it('skipGroup', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Checkbox.Group onChange={onChange}>
|
||||
<Checkbox value={1} />
|
||||
<Checkbox value={2} skipGroup />
|
||||
</Checkbox.Group>,
|
||||
);
|
||||
wrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Table rowSelection', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Checkbox.Group onChange={onChange}>
|
||||
<Table
|
||||
dataSource={[{ key: 1, value: '1' }]}
|
||||
@ -200,27 +205,32 @@ describe('CheckboxGroup', () => {
|
||||
/>
|
||||
</Checkbox.Group>,
|
||||
);
|
||||
wrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
||||
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should get div ref', () => {
|
||||
mount(
|
||||
const refCalls = [];
|
||||
render(
|
||||
<Checkbox.Group
|
||||
options={['Apple', 'Pear', 'Orange']}
|
||||
ref={node => {
|
||||
expect(node.nodeName).toBe('DIV');
|
||||
refCalls.push(node);
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
const [mountCall] = refCalls;
|
||||
expect(mountCall.nodeName).toBe('DIV');
|
||||
});
|
||||
|
||||
it('should support number option', () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const wrapper = mount(<Checkbox.Group options={[1, 'Pear', 'Orange']} onChange={onChange} />);
|
||||
const { container } = render(
|
||||
<Checkbox.Group options={[1, 'Pear', 'Orange']} onChange={onChange} />,
|
||||
);
|
||||
|
||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
expect(onChange).toHaveBeenCalledWith([1]);
|
||||
});
|
||||
|
||||
@ -246,17 +256,13 @@ describe('CheckboxGroup', () => {
|
||||
);
|
||||
};
|
||||
|
||||
const wrapper = mount(<Demo />);
|
||||
|
||||
wrapper.find('.ant-checkbox-input').first().simulate('change');
|
||||
const { container } = render(<Demo />);
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
expect(onChange).toHaveBeenCalledWith([]);
|
||||
wrapper.find('.ant-checkbox-input').first().simulate('change');
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
expect(onChange).toHaveBeenCalledWith(['length1']);
|
||||
wrapper
|
||||
.find('.ant-input')
|
||||
.first()
|
||||
.simulate('change', { target: { value: '' } });
|
||||
wrapper.find('.ant-checkbox-input').first().simulate('change');
|
||||
fireEvent.change(container.querySelector('.ant-input'), { target: { value: '' } });
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
expect(onChange).toHaveBeenCalledWith(['A']);
|
||||
});
|
||||
});
|
||||
|
@ -49,5 +49,5 @@ const App = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default () => <App />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -70,5 +70,5 @@ class App extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default () => <App />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -26,7 +26,7 @@ const antCheckboxEffect = new Keyframes('antCheckboxEffect', {
|
||||
});
|
||||
|
||||
// ============================== Styles ==============================
|
||||
export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token, hashId) => {
|
||||
export const genCheckboxStyle: GenerateStyle<CheckboxToken> = token => {
|
||||
const { checkboxCls } = token;
|
||||
const wrapperCls = `${checkboxCls}-wrapper`;
|
||||
|
||||
@ -197,7 +197,9 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token, hashId) =>
|
||||
border: `${token.controlLineWidth}px ${token.controlLineType} ${token.colorPrimary}`,
|
||||
borderRadius: token.controlRadius,
|
||||
visibility: 'hidden',
|
||||
animation: `${antCheckboxEffect.getName(hashId)} ${token.motionDurationSlow} ease-in-out`,
|
||||
animationName: antCheckboxEffect,
|
||||
animationDuration: token.motionDurationSlow,
|
||||
animationTimingFunction: 'ease-in-out',
|
||||
animationFillMode: 'backwards',
|
||||
content: '""',
|
||||
},
|
||||
@ -241,14 +243,14 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token, hashId) =>
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export function getStyle(prefixCls: string, token: FullToken<'Checkbox'>, hashId: string) {
|
||||
export function getStyle(prefixCls: string, token: FullToken<'Checkbox'>) {
|
||||
const checkboxToken: CheckboxToken = mergeToken<CheckboxToken>(token, {
|
||||
checkboxCls: `.${prefixCls}`,
|
||||
});
|
||||
|
||||
return [genCheckboxStyle(checkboxToken, hashId), antCheckboxEffect];
|
||||
return [genCheckboxStyle(checkboxToken)];
|
||||
}
|
||||
|
||||
export default genComponentStyleHook('Checkbox', (token, { prefixCls, hashId }) => [
|
||||
getStyle(prefixCls, token, hashId),
|
||||
export default genComponentStyleHook('Checkbox', (token, { prefixCls }) => [
|
||||
getStyle(prefixCls, token),
|
||||
]);
|
||||
|
@ -10,6 +10,7 @@ import CollapsePanel, { CollapsibleType } from './CollapsePanel';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import collapseMotion from '../_util/motion';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
import useStyle from './style';
|
||||
|
||||
export type ExpandIconPosition = 'left' | 'right' | undefined;
|
||||
|
||||
@ -52,6 +53,7 @@ const Collapse: CollapseInterface = props => {
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const { prefixCls: customizePrefixCls, className = '', bordered = true, ghost } = props;
|
||||
const prefixCls = getPrefixCls('collapse', customizePrefixCls);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
||||
const getIconPosition = () => {
|
||||
const { expandIconPosition } = props;
|
||||
@ -90,6 +92,7 @@ const Collapse: CollapseInterface = props => {
|
||||
[`${prefixCls}-ghost`]: !!ghost,
|
||||
},
|
||||
className,
|
||||
hashId,
|
||||
);
|
||||
const openMotion: CSSMotionProps = {
|
||||
...collapseMotion,
|
||||
@ -114,7 +117,7 @@ const Collapse: CollapseInterface = props => {
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
return wrapSSR(
|
||||
<RcCollapse
|
||||
openMotion={openMotion}
|
||||
{...props}
|
||||
@ -123,7 +126,7 @@ const Collapse: CollapseInterface = props => {
|
||||
className={collapseClassName}
|
||||
>
|
||||
{getItems()}
|
||||
</RcCollapse>
|
||||
</RcCollapse>,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -19,6 +19,7 @@ export interface CollapsePanelProps {
|
||||
id?: string;
|
||||
extra?: React.ReactNode;
|
||||
collapsible?: CollapsibleType;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const CollapsePanel: React.FC<CollapsePanelProps> = props => {
|
||||
|
@ -814,7 +814,7 @@ Array [
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown"
|
||||
style="opacity:0;pointer-events:none"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
|
@ -51,7 +51,7 @@ export default () => (
|
||||
margin-bottom: 24px;
|
||||
overflow: hidden;
|
||||
background: #f7f7f7;
|
||||
border: 0px;
|
||||
border: 0px !important;
|
||||
border-radius: 2px;
|
||||
}
|
||||
```
|
||||
|
@ -82,5 +82,5 @@ class Demo extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default () => <Demo />;
|
||||
export default Demo;
|
||||
```
|
||||
|
@ -1,162 +1,162 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
// @import '../../style/themes/index';
|
||||
// @import '../../style/mixins/index';
|
||||
|
||||
@collapse-prefix-cls: ~'@{ant-prefix}-collapse';
|
||||
// @collapse-prefix-cls: ~'@{ant-prefix}-collapse';
|
||||
|
||||
.@{collapse-prefix-cls} {
|
||||
.reset-component();
|
||||
// .@{collapse-prefix-cls} {
|
||||
// .reset-component();
|
||||
|
||||
background-color: @collapse-header-bg;
|
||||
border: @border-width-base @border-style-base @border-color-base;
|
||||
border-bottom: 0;
|
||||
border-radius: @collapse-panel-border-radius;
|
||||
// background-color: @collapse-header-bg;
|
||||
// border: @border-width-base @border-style-base @border-color-base;
|
||||
// border-bottom: 0;
|
||||
// border-radius: @collapse-panel-border-radius;
|
||||
|
||||
& > &-item {
|
||||
border-bottom: @border-width-base @border-style-base @border-color-base;
|
||||
// & > &-item {
|
||||
// border-bottom: @border-width-base @border-style-base @border-color-base;
|
||||
|
||||
&:last-child {
|
||||
&,
|
||||
& > .@{collapse-prefix-cls}-header {
|
||||
border-radius: 0 0 @collapse-panel-border-radius @collapse-panel-border-radius;
|
||||
}
|
||||
}
|
||||
// &:last-child {
|
||||
// &,
|
||||
// & > .@{collapse-prefix-cls}-header {
|
||||
// border-radius: 0 0 @collapse-panel-border-radius @collapse-panel-border-radius;
|
||||
// }
|
||||
// }
|
||||
|
||||
> .@{collapse-prefix-cls}-header {
|
||||
position: relative; // Compatible with old version of antd, should remove in next version
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: flex-start;
|
||||
padding: @collapse-header-padding;
|
||||
color: @heading-color;
|
||||
line-height: @line-height-base;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s, visibility 0s;
|
||||
// > .@{collapse-prefix-cls}-header {
|
||||
// position: relative; // Compatible with old version of antd, should remove in next version
|
||||
// display: flex;
|
||||
// flex-wrap: nowrap;
|
||||
// align-items: flex-start;
|
||||
// padding: @collapse-header-padding;
|
||||
// color: @heading-color;
|
||||
// line-height: @line-height-base;
|
||||
// cursor: pointer;
|
||||
// transition: all 0.3s, visibility 0s;
|
||||
|
||||
.@{collapse-prefix-cls}-arrow {
|
||||
display: inline-block;
|
||||
margin-right: @margin-sm;
|
||||
font-size: @font-size-sm;
|
||||
vertical-align: -1px;
|
||||
// .@{collapse-prefix-cls}-arrow {
|
||||
// display: inline-block;
|
||||
// margin-right: @margin-sm;
|
||||
// font-size: @font-size-sm;
|
||||
// vertical-align: -1px;
|
||||
|
||||
& svg {
|
||||
transition: transform 0.24s;
|
||||
}
|
||||
}
|
||||
// & svg {
|
||||
// transition: transform 0.24s;
|
||||
// }
|
||||
// }
|
||||
|
||||
.@{collapse-prefix-cls}-extra {
|
||||
margin-left: auto;
|
||||
}
|
||||
// .@{collapse-prefix-cls}-extra {
|
||||
// margin-left: auto;
|
||||
// }
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
// &:focus {
|
||||
// outline: none;
|
||||
// }
|
||||
// }
|
||||
|
||||
.@{collapse-prefix-cls}-header-collapsible-only {
|
||||
cursor: default;
|
||||
.@{collapse-prefix-cls}-header-text {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
// .@{collapse-prefix-cls}-header-collapsible-only {
|
||||
// cursor: default;
|
||||
// .@{collapse-prefix-cls}-header-text {
|
||||
// cursor: pointer;
|
||||
// }
|
||||
// }
|
||||
|
||||
&.@{collapse-prefix-cls}-no-arrow {
|
||||
> .@{collapse-prefix-cls}-header {
|
||||
padding-left: @padding-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
// &.@{collapse-prefix-cls}-no-arrow {
|
||||
// > .@{collapse-prefix-cls}-header {
|
||||
// padding-left: @padding-sm;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Expand Icon right
|
||||
&-icon-position-right {
|
||||
& > .@{collapse-prefix-cls}-item {
|
||||
> .@{collapse-prefix-cls}-header {
|
||||
position: relative;
|
||||
padding: @collapse-header-padding;
|
||||
padding-right: @collapse-header-padding-extra;
|
||||
// // Expand Icon right
|
||||
// &-icon-position-right {
|
||||
// & > .@{collapse-prefix-cls}-item {
|
||||
// > .@{collapse-prefix-cls}-header {
|
||||
// position: relative;
|
||||
// padding: @collapse-header-padding;
|
||||
// padding-right: @collapse-header-padding-extra;
|
||||
|
||||
.@{collapse-prefix-cls}-arrow {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: @padding-md;
|
||||
left: auto;
|
||||
margin: 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// .@{collapse-prefix-cls}-arrow {
|
||||
// position: absolute;
|
||||
// top: 50%;
|
||||
// right: @padding-md;
|
||||
// left: auto;
|
||||
// margin: 0;
|
||||
// transform: translateY(-50%);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
&-content {
|
||||
color: @text-color;
|
||||
background-color: @collapse-content-bg;
|
||||
border-top: @border-width-base @border-style-base @border-color-base;
|
||||
// &-content {
|
||||
// color: @text-color;
|
||||
// background-color: @collapse-content-bg;
|
||||
// border-top: @border-width-base @border-style-base @border-color-base;
|
||||
|
||||
& > &-box {
|
||||
padding: @collapse-content-padding;
|
||||
}
|
||||
// & > &-box {
|
||||
// padding: @collapse-content-padding;
|
||||
// }
|
||||
|
||||
&-hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
// &-hidden {
|
||||
// display: none;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-item:last-child {
|
||||
> .@{collapse-prefix-cls}-content {
|
||||
border-radius: 0 0 @collapse-panel-border-radius @collapse-panel-border-radius;
|
||||
}
|
||||
}
|
||||
// &-item:last-child {
|
||||
// > .@{collapse-prefix-cls}-content {
|
||||
// border-radius: 0 0 @collapse-panel-border-radius @collapse-panel-border-radius;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-borderless {
|
||||
background-color: @collapse-header-bg;
|
||||
border: 0;
|
||||
}
|
||||
// &-borderless {
|
||||
// background-color: @collapse-header-bg;
|
||||
// border: 0;
|
||||
// }
|
||||
|
||||
&-borderless > &-item {
|
||||
border-bottom: 1px solid @border-color-base;
|
||||
}
|
||||
// &-borderless > &-item {
|
||||
// border-bottom: 1px solid @border-color-base;
|
||||
// }
|
||||
|
||||
&-borderless > &-item:last-child,
|
||||
&-borderless > &-item:last-child &-header {
|
||||
border-radius: 0;
|
||||
}
|
||||
// &-borderless > &-item:last-child,
|
||||
// &-borderless > &-item:last-child &-header {
|
||||
// border-radius: 0;
|
||||
// }
|
||||
|
||||
// hide the last border-bottom in borderless mode
|
||||
&-borderless > &-item:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
// // hide the last border-bottom in borderless mode
|
||||
// &-borderless > &-item:last-child {
|
||||
// border-bottom: 0;
|
||||
// }
|
||||
|
||||
&-borderless > &-item > &-content {
|
||||
background-color: transparent;
|
||||
border-top: 0;
|
||||
}
|
||||
// &-borderless > &-item > &-content {
|
||||
// background-color: transparent;
|
||||
// border-top: 0;
|
||||
// }
|
||||
|
||||
&-borderless > &-item > &-content > &-content-box {
|
||||
padding-top: 4px;
|
||||
}
|
||||
// &-borderless > &-item > &-content > &-content-box {
|
||||
// padding-top: 4px;
|
||||
// }
|
||||
|
||||
&-ghost {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
> .@{collapse-prefix-cls}-item {
|
||||
border-bottom: 0;
|
||||
> .@{collapse-prefix-cls}-content {
|
||||
background-color: transparent;
|
||||
border-top: 0;
|
||||
> .@{collapse-prefix-cls}-content-box {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// &-ghost {
|
||||
// background-color: transparent;
|
||||
// border: 0;
|
||||
// > .@{collapse-prefix-cls}-item {
|
||||
// border-bottom: 0;
|
||||
// > .@{collapse-prefix-cls}-content {
|
||||
// background-color: transparent;
|
||||
// border-top: 0;
|
||||
// > .@{collapse-prefix-cls}-content-box {
|
||||
// padding-top: 12px;
|
||||
// padding-bottom: 12px;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
& &-item-disabled > &-header {
|
||||
&,
|
||||
& > .arrow {
|
||||
color: @disabled-color;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
// & &-item-disabled > &-header {
|
||||
// &,
|
||||
// & > .arrow {
|
||||
// color: @disabled-color;
|
||||
// cursor: not-allowed;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@import './rtl';
|
||||
// @import './rtl';
|
||||
|
@ -1,2 +1,246 @@
|
||||
import '../../style/index.less';
|
||||
import './index.less';
|
||||
// import '../../style/index.less';
|
||||
// import './index.less';
|
||||
|
||||
// deps-lint-skip-all
|
||||
import { CSSInterpolation } from '@ant-design/cssinjs';
|
||||
import {
|
||||
GenerateStyle,
|
||||
resetComponent,
|
||||
genComponentStyleHook,
|
||||
mergeToken,
|
||||
FullToken,
|
||||
} from '../../_util/theme';
|
||||
|
||||
type CollapseToken = FullToken<'Collapse'> & {
|
||||
collapseContentBg: string;
|
||||
collapseContentPadding: number;
|
||||
collapseHeaderBg: string;
|
||||
collapseHeaderPadding: string;
|
||||
collapseHeaderPaddingExtra: number;
|
||||
collapsePanelBorderRadius: number;
|
||||
};
|
||||
|
||||
export const genBaseStyle: GenerateStyle<CollapseToken> = token => {
|
||||
const {
|
||||
componentCls,
|
||||
collapseContentBg,
|
||||
collapseContentPadding,
|
||||
collapseHeaderBg,
|
||||
collapseHeaderPadding,
|
||||
collapseHeaderPaddingExtra,
|
||||
collapsePanelBorderRadius,
|
||||
|
||||
controlLineWidth,
|
||||
controlLineType,
|
||||
colorBorder,
|
||||
colorText,
|
||||
colorTextHeading,
|
||||
colorTextDisabled,
|
||||
lineHeight,
|
||||
marginSM,
|
||||
padding,
|
||||
paddingSM,
|
||||
fontSizeSM,
|
||||
} = token;
|
||||
|
||||
const borderBase = `${controlLineWidth}px ${controlLineType} ${colorBorder}`;
|
||||
|
||||
return {
|
||||
[componentCls]: {
|
||||
...resetComponent(token),
|
||||
backgroundColor: collapseHeaderBg,
|
||||
border: borderBase,
|
||||
borderBottom: 0,
|
||||
borderRadius: `${collapsePanelBorderRadius}px`,
|
||||
|
||||
[`&-rtl`]: {
|
||||
direction: 'rtl',
|
||||
},
|
||||
|
||||
[`& > ${componentCls}-item`]: {
|
||||
borderBottom: borderBase,
|
||||
[`&:last-child`]: {
|
||||
[`
|
||||
&,
|
||||
& > ${componentCls}-header`]: {
|
||||
borderRadius: `0 0 ${collapsePanelBorderRadius}px ${collapsePanelBorderRadius}px`,
|
||||
},
|
||||
},
|
||||
|
||||
[`> ${componentCls}-header`]: {
|
||||
position: 'relative', // Compatible with old version of antd, should remove in next version
|
||||
display: 'flex',
|
||||
flexWrap: 'nowrap',
|
||||
alignItems: 'flex-start',
|
||||
padding: collapseHeaderPadding,
|
||||
color: colorTextHeading,
|
||||
lineHeight,
|
||||
cursor: 'pointer',
|
||||
transition: `all 0.3s, visibility 0s`,
|
||||
|
||||
[`${componentCls}-arrow`]: {
|
||||
display: 'inline-block',
|
||||
marginInlineEnd: marginSM,
|
||||
fontSize: fontSizeSM,
|
||||
// FIXME
|
||||
verticalAlign: '-1px',
|
||||
|
||||
[`${componentCls}-rtl &`]: {},
|
||||
|
||||
[`& svg`]: {
|
||||
// FIXME
|
||||
transition: 'transform 0.24s',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-extra`]: {
|
||||
marginInlineStart: 'auto',
|
||||
},
|
||||
|
||||
[`&:focus`]: {
|
||||
outline: 'none',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-header-collapsible-only`]: {
|
||||
cursor: 'default',
|
||||
|
||||
[`${componentCls}-header-text`]: {
|
||||
cursor: 'pointer',
|
||||
},
|
||||
},
|
||||
|
||||
[`&${componentCls}-no-arrow`]: {
|
||||
[`> ${componentCls}-header`]: {
|
||||
paddingInlineStart: paddingSM,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`&-icon-position-right`]: {
|
||||
[`& > ${componentCls}-item `]: {
|
||||
[`> ${componentCls}-header`]: {
|
||||
position: 'relative',
|
||||
padding: collapseHeaderPadding,
|
||||
paddingInlineEnd: collapseHeaderPaddingExtra,
|
||||
|
||||
[`${componentCls}-arrow`]: {
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
insetInlineEnd: padding,
|
||||
insetInlineStart: 'auto',
|
||||
margin: 0,
|
||||
transform: 'translateY(-50%)',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-content`]: {
|
||||
color: colorText,
|
||||
backgroundColor: collapseContentBg,
|
||||
borderTop: borderBase,
|
||||
|
||||
[`& > ${componentCls}-content-box`]: {
|
||||
padding: collapseContentPadding,
|
||||
},
|
||||
|
||||
[`&-hidden`]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-item:last-child`]: {
|
||||
[`> ${componentCls}-content`]: {
|
||||
borderRadius: `0 0 ${collapsePanelBorderRadius}px ${collapsePanelBorderRadius}px`,
|
||||
},
|
||||
},
|
||||
|
||||
[`& ${componentCls}-item-disabled > ${componentCls}-header`]: {
|
||||
[`
|
||||
&,
|
||||
& > .arrow
|
||||
`]: {
|
||||
color: colorTextDisabled,
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
},
|
||||
|
||||
[`&-ghost`]: {
|
||||
backgroundColor: 'transparent',
|
||||
border: 0,
|
||||
[`> ${componentCls}-item`]: {
|
||||
borderBottom: 0,
|
||||
[`> ${componentCls}-content`]: {
|
||||
backgroundColor: 'transparent',
|
||||
border: 0,
|
||||
[`> ${componentCls}-content-box`]: {
|
||||
// FIXME
|
||||
paddingTop: 12,
|
||||
paddingBottom: 12,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const genBorderlessStyle: GenerateStyle<CollapseToken> = token => {
|
||||
const {
|
||||
componentCls,
|
||||
collapseHeaderBg,
|
||||
|
||||
colorBorder,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-borderless`]: {
|
||||
backgroundColor: collapseHeaderBg,
|
||||
border: 0,
|
||||
|
||||
[`> ${componentCls}-item`]: {
|
||||
borderBottom: `1px solid ${colorBorder}`,
|
||||
},
|
||||
|
||||
[`
|
||||
> ${componentCls}-item:last-child,
|
||||
> ${componentCls}-item:last-child ${componentCls}-header
|
||||
`]: {
|
||||
borderRadius: 0,
|
||||
},
|
||||
|
||||
[`> ${componentCls}-item:last-child`]: {
|
||||
borderBottom: 0,
|
||||
},
|
||||
|
||||
[`> ${componentCls}-item > ${componentCls}-content`]: {
|
||||
backgroundColor: 'transparent',
|
||||
borderTop: 0,
|
||||
},
|
||||
|
||||
[`> ${componentCls}-item > ${componentCls}-content > ${componentCls}-content-box`]: {
|
||||
// FIXME
|
||||
paddingTop: 4,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const genCollapseStyle: GenerateStyle<CollapseToken> = (
|
||||
token: CollapseToken,
|
||||
): CSSInterpolation => [genBaseStyle(token), genBorderlessStyle(token)];
|
||||
|
||||
export default genComponentStyleHook('Collapse', token => {
|
||||
const collapseToken = mergeToken<CollapseToken>(token, {
|
||||
collapseContentBg: token.colorBgComponent,
|
||||
collapseContentPadding: token.padding,
|
||||
collapseHeaderBg: token.colorBgComponentSecondary,
|
||||
collapseHeaderPadding: `${token.paddingSM}px ${token.padding}px`,
|
||||
// FIXME
|
||||
collapseHeaderPaddingExtra: 40,
|
||||
collapsePanelBorderRadius: token.radiusBase,
|
||||
});
|
||||
|
||||
return [genCollapseStyle(collapseToken)];
|
||||
});
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user