mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-09 19:09:21 +08:00
Compare commits
343 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6129d3a1eb | ||
|
|
4dbb81b88e | ||
|
|
00bcdae2ae | ||
|
|
f61b32a0f9 | ||
|
|
ce0505561a | ||
|
|
5e1be364c4 | ||
|
|
e3a7635a2a | ||
|
|
e508ee778d | ||
|
|
4b239d65c0 | ||
|
|
019eeec3ce | ||
|
|
584f9fd907 | ||
|
|
e09ce6284e | ||
|
|
955fa520f1 | ||
|
|
e361b30ded | ||
|
|
dda650cc7b | ||
|
|
6f36f4a877 | ||
|
|
46f8399f99 | ||
|
|
f22c5d999b | ||
|
|
6493db80d4 | ||
|
|
6cea99be9d | ||
|
|
3d62c44325 | ||
|
|
f36576f12d | ||
|
|
902141f554 | ||
|
|
0d90c585fa | ||
|
|
b8fb4c411d | ||
|
|
3ca11e94ce | ||
|
|
076ed1bf9e | ||
|
|
33159218cd | ||
|
|
738ed22871 | ||
|
|
745c2182a5 | ||
|
|
cfff7967b3 | ||
|
|
2d7a950167 | ||
|
|
f263102500 | ||
|
|
d4aca5f343 | ||
|
|
46955f9f59 | ||
|
|
f4ee809e66 | ||
|
|
d0d75a6e54 | ||
|
|
2caa658b6d | ||
|
|
b689c9044c | ||
|
|
6376ce2e68 | ||
|
|
6529d9048f | ||
|
|
2e15bf752e | ||
|
|
fd73d2f126 | ||
|
|
008cf78857 | ||
|
|
edf7805922 | ||
|
|
d5fea40ab5 | ||
|
|
b1caef0723 | ||
|
|
da0afdf4ef | ||
|
|
a51439cbba | ||
|
|
351a4d6677 | ||
|
|
061b457031 | ||
|
|
b83c8636fa | ||
|
|
18e3e42120 | ||
|
|
b0575186ce | ||
|
|
39ed9b3889 | ||
|
|
294144b1ae | ||
|
|
65035cea08 | ||
|
|
639ef9f570 | ||
|
|
9f8eb99807 | ||
|
|
b047add305 | ||
|
|
19ca646ef3 | ||
|
|
68a185a08f | ||
|
|
ad663db7b1 | ||
|
|
03fad9177a | ||
|
|
78ac8a19b2 | ||
|
|
7eede1a0b6 | ||
|
|
a42f77a0f1 | ||
|
|
d7bd6f65bf | ||
|
|
92695c9e95 | ||
|
|
3b64ba4ba4 | ||
|
|
377ad77f17 | ||
|
|
c019ff43d6 | ||
|
|
9d4d6f5402 | ||
|
|
162b6979af | ||
|
|
b95207d58e | ||
|
|
882cec62d6 | ||
|
|
e573ac4e89 | ||
|
|
e915a83326 | ||
|
|
a9b95fe63b | ||
|
|
8e20fe6779 | ||
|
|
d8d48487b0 | ||
|
|
d89cca53b1 | ||
|
|
31fa14a742 | ||
|
|
77c5adbe4d | ||
|
|
bd9b38527e | ||
|
|
00d1276ed2 | ||
|
|
75d84b2041 | ||
|
|
cf360252f7 | ||
|
|
14f9f95864 | ||
|
|
0bf728c3e8 | ||
|
|
f958a1cbc8 | ||
|
|
c353e8bb06 | ||
|
|
49533aafdc | ||
|
|
27bc2d1e02 | ||
|
|
ada81616b5 | ||
|
|
0cdb4c8c86 | ||
|
|
76793143ae | ||
|
|
59a53fbb69 | ||
|
|
c7e1b050ab | ||
|
|
2c9ddcb1b2 | ||
|
|
37c894f1a2 | ||
|
|
059b106ccf | ||
|
|
11bbd725f7 | ||
|
|
e6b8e24828 | ||
|
|
9e9e62911c | ||
|
|
e761538e26 | ||
|
|
9b8e0bb908 | ||
|
|
7c77a764e1 | ||
|
|
527f34fe6d | ||
|
|
163154a4fb | ||
|
|
e3ac222fd3 | ||
|
|
d039e32e6b | ||
|
|
56c42e496b | ||
|
|
81bde547cd | ||
|
|
afe7172974 | ||
|
|
4be9535926 | ||
|
|
cf401f73c8 | ||
|
|
6773020607 | ||
|
|
cfd66fa030 | ||
|
|
6844c413c2 | ||
|
|
9fcd20c6cc | ||
|
|
3712832a03 | ||
|
|
fd9846a145 | ||
|
|
030c545964 | ||
|
|
9b54bd728d | ||
|
|
ef7e7a80d2 | ||
|
|
d5e7187d9d | ||
|
|
b2e92d38eb | ||
|
|
670ec79fa0 | ||
|
|
19da433933 | ||
|
|
f7c34de3ca | ||
|
|
84df944aaf | ||
|
|
98a13a7569 | ||
|
|
89d7101e6e | ||
|
|
ab972ac1eb | ||
|
|
9e96b9e2d5 | ||
|
|
2a3fc818d0 | ||
|
|
5a1ffb7894 | ||
|
|
cea0e45671 | ||
|
|
d13c76d7e4 | ||
|
|
5290421ac9 | ||
|
|
1bf9959062 | ||
|
|
75d7038691 | ||
|
|
4e9fc51dba | ||
|
|
d7949a76ad | ||
|
|
ccd2820ce7 | ||
|
|
b34b956529 | ||
|
|
47b3aa2225 | ||
|
|
84bd53627b | ||
|
|
cb2094265e | ||
|
|
f0a4e211b1 | ||
|
|
84225e4d50 | ||
|
|
94edeaa02f | ||
|
|
c93400d375 | ||
|
|
21bd9444f4 | ||
|
|
0cea6237dc | ||
|
|
a5efa7a81a | ||
|
|
129975f9dc | ||
|
|
bffa58f439 | ||
|
|
4b485d393b | ||
|
|
419004e38a | ||
|
|
b0b619c877 | ||
|
|
670f8f2f1e | ||
|
|
fdbf37a9c0 | ||
|
|
4af818ca8e | ||
|
|
0c2eed6866 | ||
|
|
e0f57e72e0 | ||
|
|
faa75d592c | ||
|
|
77bc48f146 | ||
|
|
67c88571e7 | ||
|
|
03e6b33681 | ||
|
|
973f55babb | ||
|
|
5203d256dd | ||
|
|
c54255a703 | ||
|
|
508401cca4 | ||
|
|
7c260c03a5 | ||
|
|
c13e56ab92 | ||
|
|
cc045bb325 | ||
|
|
6f6430bfee | ||
|
|
688f8a3ab0 | ||
|
|
415848c359 | ||
|
|
1e11c83e74 | ||
|
|
baf001898d | ||
|
|
2932b39c88 | ||
|
|
1f371eee09 | ||
|
|
58ccb40005 | ||
|
|
76466dae9f | ||
|
|
254c17e320 | ||
|
|
ebf9c1fa4a | ||
|
|
8b9a005c1f | ||
|
|
b57d306107 | ||
|
|
b467cc5cbb | ||
|
|
ae8603838a | ||
|
|
1bba2ef65e | ||
|
|
4066f2f624 | ||
|
|
c2437a915d | ||
|
|
a518a2b0b1 | ||
|
|
35a6a887a3 | ||
|
|
b264589b77 | ||
|
|
3629830a85 | ||
|
|
d7288e99a0 | ||
|
|
61378e4605 | ||
|
|
0689982def | ||
|
|
e613861e63 | ||
|
|
f646b6fae8 | ||
|
|
e657fb806f | ||
|
|
6619700893 | ||
|
|
0f93896f0b | ||
|
|
ac50fa147c | ||
|
|
fdbf95aabd | ||
|
|
c69cf4a261 | ||
|
|
476853c320 | ||
|
|
8d0bba4dea | ||
|
|
e197163a78 | ||
|
|
a7b81d52af | ||
|
|
6f1fe30df1 | ||
|
|
fb839eb1d1 | ||
|
|
706f0bbf56 | ||
|
|
50fe770458 | ||
|
|
c40b291415 | ||
|
|
6106aab9d5 | ||
|
|
d6d485b72d | ||
|
|
6ad1b18a47 | ||
|
|
4feb186085 | ||
|
|
baa56b6d85 | ||
|
|
ce78029933 | ||
|
|
8bd10889c6 | ||
|
|
f53d931890 | ||
|
|
b4f38f7a22 | ||
|
|
2120d7dfaa | ||
|
|
a00c06c58b | ||
|
|
5b61c0fac9 | ||
|
|
44cfc351cb | ||
|
|
f64558da89 | ||
|
|
a216d6e4f7 | ||
|
|
bfd5644ff0 | ||
|
|
f546c8b9e3 | ||
|
|
75b090aff3 | ||
|
|
70c6e47cde | ||
|
|
32ee08caa5 | ||
|
|
b87b1283ea | ||
|
|
551763e768 | ||
|
|
b10f4cffd9 | ||
|
|
7f2f814279 | ||
|
|
c955770c40 | ||
|
|
6804fdad1a | ||
|
|
8cb146becd | ||
|
|
6a52cf0303 | ||
|
|
c99ecdac39 | ||
|
|
f45f7353a5 | ||
|
|
316913ca37 | ||
|
|
1bbaa49bef | ||
|
|
aee2e7a5c9 | ||
|
|
4a3af4caef | ||
|
|
471e97ab76 | ||
|
|
2268c7aa88 | ||
|
|
d4874fc0b3 | ||
|
|
8b514406e3 | ||
|
|
1a82efa5ca | ||
|
|
a820046130 | ||
|
|
5f1da59488 | ||
|
|
9924bbf838 | ||
|
|
7de007100d | ||
|
|
04ad7236e4 | ||
|
|
a83143bbbc | ||
|
|
188e5630b3 | ||
|
|
02dccd9643 | ||
|
|
8497e54e39 | ||
|
|
9f633bc002 | ||
|
|
159d42fda8 | ||
|
|
850b670862 | ||
|
|
610807ebf9 | ||
|
|
f90702cd0c | ||
|
|
0cd0ebe7dc | ||
|
|
9559754b5b | ||
|
|
681aab1ef1 | ||
|
|
9f38c46039 | ||
|
|
2afab58ac8 | ||
|
|
9cb3c94204 | ||
|
|
55332f6971 | ||
|
|
e6b1b1a4e7 | ||
|
|
be0c654fff | ||
|
|
2e284aa017 | ||
|
|
4aa1b62659 | ||
|
|
bb4f0da50e | ||
|
|
5d9d45b597 | ||
|
|
4f1605949e | ||
|
|
217723d321 | ||
|
|
586c7f5218 | ||
|
|
fd7c942403 | ||
|
|
c463b2cc35 | ||
|
|
5e5ec80d04 | ||
|
|
b0e528d14c | ||
|
|
9d03db0503 | ||
|
|
41dd9560c9 | ||
|
|
da3f5528f4 | ||
|
|
6093f11cf0 | ||
|
|
68119768cc | ||
|
|
53d7a20939 | ||
|
|
50e33768a9 | ||
|
|
e15be10faf | ||
|
|
b73e84da9b | ||
|
|
34c2fad636 | ||
|
|
90a36eed0b | ||
|
|
f7e00f645e | ||
|
|
63a32422e5 | ||
|
|
31ba421268 | ||
|
|
227233268d | ||
|
|
339246d316 | ||
|
|
08c63d1e23 | ||
|
|
731505813a | ||
|
|
c19685e0ea | ||
|
|
64d151aa81 | ||
|
|
82d709676a | ||
|
|
49f5ed7764 | ||
|
|
fdcbfc909d | ||
|
|
f250b2fa29 | ||
|
|
ce36d3e2fe | ||
|
|
9a6ad0edb9 | ||
|
|
d766472d94 | ||
|
|
80e3dfa9be | ||
|
|
4884e91c49 | ||
|
|
67a482f4e5 | ||
|
|
1cf1a15d50 | ||
|
|
72a846681a | ||
|
|
741ff5c3bb | ||
|
|
6705454b83 | ||
|
|
acb4cb6859 | ||
|
|
fafa3b7e51 | ||
|
|
116af77548 | ||
|
|
3fad93e41b | ||
|
|
4cb70b6f16 | ||
|
|
c5bcf57537 | ||
|
|
3a28f31fca | ||
|
|
747691f600 | ||
|
|
f05f2dd197 | ||
|
|
6668d48c54 | ||
|
|
35e390018c | ||
|
|
081604e253 | ||
|
|
98232382f1 | ||
|
|
b66ab37463 | ||
|
|
e3e183ea39 | ||
|
|
402f3a9afb |
14
.bundle-analyzerrc.json
Normal file
14
.bundle-analyzerrc.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"files": [
|
||||
{
|
||||
"test": "./dist/antd.min.js",
|
||||
"maxSize": "300 kB",
|
||||
"compression": "gzip"
|
||||
},
|
||||
{
|
||||
"test": "./dist/antd.min.css",
|
||||
"maxSize": "65 kB",
|
||||
"compression": "gzip"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -22,10 +22,10 @@ references:
|
||||
ignore: gh-pages
|
||||
- dist:
|
||||
requires:
|
||||
- setup
|
||||
- setup
|
||||
- compile:
|
||||
requires:
|
||||
- setup
|
||||
- setup
|
||||
- lint:
|
||||
requires:
|
||||
- setup
|
||||
@@ -166,7 +166,7 @@ workflows:
|
||||
<<: *workflow
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "0 0 * * *"
|
||||
cron: '0 0 * * *'
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
|
||||
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
node_modules/
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
name: '⚠️ Please use new-issue.ant.design ⚠️'
|
||||
about: The issue which is not created via http://new-issue.ant.design will be closed immediately.
|
||||
labels:
|
||||
---
|
||||
|
||||
The issue which is not created via http://new-issue.ant.design will be closed immediately.
|
||||
|
||||
---
|
||||
|
||||
注意:不是用 http://new-issue.ant.design 创建的 issue 会被立即关闭。
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Create new issue
|
||||
url: http://new-issue.ant.design
|
||||
about: The issue which is not created via http://new-issue.ant.design will be closed immediately.
|
||||
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -4,17 +4,20 @@ First of all, thank you for your contribution! 😄
|
||||
New feature please send pull request to feature branch, and rest to master branch.
|
||||
Pull request will be merged after one of collaborators approve.
|
||||
Please makes sure that these form are filled before submitting your pull request, thank you!
|
||||
-->
|
||||
|
||||
[[中文版模板 / Chinese template](https://github.com/ant-design/ant-design/blob/master/.github/PULL_REQUEST_TEMPLATE/pr_cn.md)]
|
||||
-->
|
||||
|
||||
### 🤔 This is a ...
|
||||
|
||||
- [ ] New feature
|
||||
- [ ] Bug fix
|
||||
- [ ] Site / document update
|
||||
- [ ] Site / documentation update
|
||||
- [ ] Demo update
|
||||
- [ ] Component style update
|
||||
- [ ] TypeScript definition update
|
||||
- [ ] Bundle size optimization
|
||||
- [ ] Perfermance optimization
|
||||
- [ ] Refactoring
|
||||
- [ ] Code style optimization
|
||||
- [ ] Test Case
|
||||
@@ -48,7 +51,7 @@ Describe changes from userside, and list all potential break changes or other ri
|
||||
|
||||
### ☑️ Self Check before Merge
|
||||
|
||||
⚠️ Please check all items below before review. ⚠️
|
||||
⚠️ Please check all items below before review. ⚠️
|
||||
|
||||
- [ ] Doc is updated/provided or not needed
|
||||
- [ ] Demo is updated/provided or not needed
|
||||
|
||||
5
.github/PULL_REQUEST_TEMPLATE/pr_cn.md
vendored
5
.github/PULL_REQUEST_TEMPLATE/pr_cn.md
vendored
@@ -13,8 +13,11 @@
|
||||
- [ ] 新特性提交
|
||||
- [ ] 日常 bug 修复
|
||||
- [ ] 站点、文档改进
|
||||
- [ ] 演示代码改进
|
||||
- [ ] 组件样式改进
|
||||
- [ ] TypeScript 定义更新
|
||||
- [ ] 包体积优化
|
||||
- [ ] 性能优化
|
||||
- [ ] 重构
|
||||
- [ ] 代码风格优化
|
||||
- [ ] 测试用例
|
||||
@@ -48,7 +51,7 @@
|
||||
|
||||
### ☑️ 请求合并前的自查清单
|
||||
|
||||
⚠️ 请自检并全部**勾选全部选项**。⚠️
|
||||
⚠️ 请自检并全部**勾选全部选项**。⚠️
|
||||
|
||||
- [ ] 文档已补充或无须补充
|
||||
- [ ] 代码演示已提供或无须提供
|
||||
|
||||
3
.github/tests_checker.yml
vendored
Normal file
3
.github/tests_checker.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
comment: 'Could you please add tests to make sure this change works as expected?',
|
||||
fileExtensions: [.ts', '.tsx', '.json']
|
||||
testDir: '__tests__'
|
||||
24
.github/workflows/lighthouse-ci.yml
vendored
24
.github/workflows/lighthouse-ci.yml
vendored
@@ -1,19 +1,11 @@
|
||||
name: Lighthouse
|
||||
on: push
|
||||
name: CI
|
||||
on: [push]
|
||||
jobs:
|
||||
lighthouse:
|
||||
lighthouseci:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Audit URLs using Lighthouse
|
||||
uses: treosh/lighthouse-ci-action@v2
|
||||
with:
|
||||
urls: |
|
||||
https://ant.design
|
||||
https://ant.design/docs/react/introduce-cn
|
||||
https://ant.design/components/button-cn
|
||||
- name: Save results
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: lighthouse-results
|
||||
path: '.lighthouseci' # This will save the Lighthouse results as .json files
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
- run: npm install && npm install -g @lhci/cli@0.4.x
|
||||
- run: npm run site
|
||||
- run: lhci autorun --upload.target=temporary-public-storage
|
||||
|
||||
13
.github/workflows/mirror.yml
vendored
13
.github/workflows/mirror.yml
vendored
@@ -5,11 +5,10 @@ on: [push]
|
||||
jobs:
|
||||
to_gitee:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'ant-design/ant-design'
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: pixta-dev/repository-mirroring-action@v1
|
||||
with:
|
||||
target_repo_url:
|
||||
git@gitee.com:ant-design/ant-design.git
|
||||
ssh_private_key:
|
||||
${{ secrets.GITEE_SSH_PRIVATE_KEY }}
|
||||
- uses: actions/checkout@v1
|
||||
- uses: pixta-dev/repository-mirroring-action@v1
|
||||
with:
|
||||
target_repo_url: git@gitee.com:ant-design/ant-design.git
|
||||
ssh_private_key: ${{ secrets.GITEE_SSH_PRIVATE_KEY }}
|
||||
|
||||
9
.github/workflows/rebase.yml
vendored
9
.github/workflows/rebase.yml
vendored
@@ -1,20 +1,17 @@
|
||||
name: Automatic Rebase
|
||||
# https://github.com/marketplace/actions/automatic-rebase
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
name: Automatic Rebase
|
||||
jobs:
|
||||
rebase:
|
||||
name: Rebase
|
||||
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Automatic Rebase
|
||||
uses: cirrus-actions/rebase@1.2
|
||||
uses: cirrus-actions/rebase@1.3
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -58,3 +58,7 @@ site/theme/template/Resources/**/*.jsx
|
||||
site/theme/template/NotFound.jsx
|
||||
scripts/previewEditor/index.html
|
||||
components/version/version.tsx
|
||||
|
||||
# Image snapshot diff
|
||||
__diff_output__/
|
||||
/jest-stare
|
||||
|
||||
24
.jest.image.js
Normal file
24
.jest.image.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
|
||||
|
||||
// jest config for image snapshots
|
||||
module.exports = {
|
||||
setupFiles: ['./tests/setup.js'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
||||
moduleNameMapper,
|
||||
transform: {
|
||||
'\\.tsx?$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
|
||||
'\\.js$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
|
||||
'\\.md$': './node_modules/@ant-design/tools/lib/jest/demoPreprocessor',
|
||||
'\\.(jpg|png|gif|svg)$': './node_modules/@ant-design/tools/lib/jest/imagePreprocessor',
|
||||
},
|
||||
testRegex: 'image\\.test\\.js$',
|
||||
testEnvironment: 'node',
|
||||
transformIgnorePatterns,
|
||||
snapshotSerializers: ['enzyme-to-json/serializer'],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsConfigFile: './tsconfig.test.json',
|
||||
},
|
||||
},
|
||||
reporters: ['default', 'jest-stare'],
|
||||
};
|
||||
2
.jest.js
2
.jest.js
@@ -26,7 +26,7 @@ module.exports = {
|
||||
'^react-dnd-test-backend$': 'react-dnd-test-backend/dist/cjs',
|
||||
'^react-dnd-test-utils$': 'react-dnd-test-utils/dist/cjs',
|
||||
},
|
||||
testPathIgnorePatterns: ['/node_modules/', 'dekko', 'node'],
|
||||
testPathIgnorePatterns: ['/node_modules/', 'dekko', 'node', 'image.test.js'],
|
||||
transform: {
|
||||
'\\.tsx?$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
|
||||
'\\.js$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
|
||||
|
||||
@@ -16,9 +16,4 @@ module.exports = {
|
||||
testEnvironment: 'node',
|
||||
transformIgnorePatterns,
|
||||
snapshotSerializers: ['enzyme-to-json/serializer'],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsConfigFile: './tsconfig.test.json',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1010,7 +1010,6 @@ zytjs <yitongzhao@163.com>
|
||||
郭延豪(708674) <gyh9457@163.com>
|
||||
愚指导-TZ <yutingzhao1991@sina.com>
|
||||
杨小事er <Uiryzd@163.com>
|
||||
杨小事er <uiryzd@163.com>
|
||||
超能刚哥 <margox@foxmail.com>
|
||||
马金花儿 <o.o@mug.dog>
|
||||
रोहन मल्होत्रा <rohan.malhotra@adwyze.com>
|
||||
|
||||
@@ -15,6 +15,192 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 4.3.2
|
||||
|
||||
`2020-06-06`
|
||||
|
||||
- 🐞 Fix Tag.CheckableTag don't support `onClick`. [#24743](https://github.com/ant-design/ant-design/pull/24743)
|
||||
- 🐞 Fix Drawer support set `getPopupContainer` and `getPrefixCls` by ConfigProvider. [#24727](https://github.com/ant-design/ant-design/pull/24727)
|
||||
- 🐞 Fix Button `loading.delay` repeat trigger when parent compoent re-render. [#24713](https://github.com/ant-design/ant-design/pull/24713)
|
||||
- 🐞 Fix Dropdown menu link color when has `icon`. [#24707](https://github.com/ant-design/ant-design/pull/24707) [#24702](https://github.com/ant-design/ant-design/pull/24702)
|
||||
- Select
|
||||
- 🐞 Fix Select virtual scroll display abnormally in compact mode. [#24706](https://github.com/ant-design/ant-design/pull/24706)
|
||||
- ⚡️ Optimize Select multiple mode performence. [#24785](https://github.com/ant-design/ant-design/pull/24785) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🐞 Fix Calendar trigger `onPanelChange` even when in the same panel. [#24695](https://github.com/ant-design/ant-design/pull/24695)
|
||||
- 🐞 Fix Input component height issue in IE11. [#24673](https://github.com/ant-design/ant-design/pull/24673) [@xiaosongxiaosong](https://github.com/xiaosongxiaosong)
|
||||
- 🐞 Fix Radio typescript error typo. [#24693](https://github.com/ant-design/ant-design/pull/24693) [@hengkx](https://github.com/hengkx)
|
||||
- 🐞 Fix Statistic don't work with Tooltip. [#24782](https://github.com/ant-design/ant-design/pull/24782)
|
||||
- 🐞 Fix TimePicker.RangePicker `bordered={false}` not working when has `className`. [#24781](https://github.com/ant-design/ant-design/pull/24781)
|
||||
- 🐞 Fix List cannot trigger `onChange` in pagination. [#24514](https://github.com/ant-design/ant-design/pull/24514)
|
||||
- 🌐 Localization
|
||||
- 🇮🇱 Add Hebrew localisations for Form. [#24716](https://github.com/ant-design/ant-design/pull/24716) [@israelKusayev](https://github.com/israelKusayev)
|
||||
- 🇰🇷 Add ko_KR localizations for Form. [#24783](https://github.com/ant-design/ant-design/pull/24783) [@Jaewoook](https://github.com/Jaewoook)
|
||||
- 💄 Add less variable `@table-font-size`, `@table-font-size-md` and `@table-font-size-sm` to customize the size of Table text. [#24714](https://github.com/ant-design/ant-design/pull/24714) [@morenyang](https://github.com/morenyang)
|
||||
- RTL
|
||||
- 💄 Optimize Tabs dropdown style in RTL. [#24715](https://github.com/ant-design/ant-design/pull/24715)
|
||||
- 💄 Add `Modal.method()` RTL supports only use hooks. [#24682](https://github.com/ant-design/ant-design/pull/24682)
|
||||
- 💄 Fix Badge offset in RTL. [#24724](https://github.com/ant-design/ant-design/pull/24724)
|
||||
|
||||
## 4.3.1
|
||||
|
||||
`2020-06-02`
|
||||
|
||||
- Tabs
|
||||
- 🐞 Fix Tabs `hideAdd` not working. [#24621](https://github.com/ant-design/ant-design/pull/24621)
|
||||
- 🐞 Fix Tabs dropdown has extra horizontal scrollbar in Firefox. [#24677](https://github.com/ant-design/ant-design/pull/24677)
|
||||
- 🐞 Fix Tabs inkbar border lost when use with `react-sticky`. [#24643](https://github.com/ant-design/ant-design/pull/24643)
|
||||
- 💄 Adjust Tabs `tabBarStyle` style display. [#24620](https://github.com/ant-design/ant-design/pull/24620)
|
||||
- Button
|
||||
- 🐞 Fix Button quick set `loading` from `delay` to `false` will still change to the loading status. [#24678](https://github.com/ant-design/ant-design/pull/24678)
|
||||
- 🐞 Fix the inconsistent style of Text Button in `danger`. [#24622](https://github.com/ant-design/ant-design/pull/24622) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 Fix Table no showing scrollbar inside Row. [#24661](https://github.com/ant-design/ant-design/pull/24661) [@zt123123](https://github.com/zt123123)
|
||||
- 🐞 Fix Drawer get `dropdownMatchSelectWidth` as dom prop warning. [#24651](https://github.com/ant-design/ant-design/pull/24651)
|
||||
- 🐞 Adjust Steps to support React.Fragment with `children`. [#24644](https://github.com/ant-design/ant-design/pull/24644)
|
||||
- 🐞 Fix Upload delete icon cannot be navigate via keyboard. [#24615](https://github.com/ant-design/ant-design/pull/24615) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 Fix multiple Select search input cursor missing issue. [#24631](https://github.com/ant-design/ant-design/pull/24631)
|
||||
- 🐞 Fix Radio.Group using `options` get `Element type is invalid` error. [#24631](https://github.com/ant-design/ant-design/pull/24631)
|
||||
- RTL
|
||||
- 💄 Adjust Notification default placement to `topLeft` in RTL. [#24632](https://github.com/ant-design/ant-design/pull/24632)
|
||||
- TypeScript
|
||||
- 🛠 Export Tabs `TabPaneProps` definition. [#24648](https://github.com/ant-design/ant-design/pull/24648)
|
||||
|
||||
## 4.3.0
|
||||
|
||||
`2020-05-31`
|
||||
|
||||
- 🔥 Rewrite Tabs for better user experience. [#24552](https://github.com/ant-design/ant-design/pull/24552)
|
||||
- 📖 Add components [overview page](https://ant.design/components/overview). [#24491](https://github.com/ant-design/ant-design/pull/24491) [@arvinxx](https://github.com/arvinxx)
|
||||
- 🛠 Optimize dependencies to reduce overall package size. [#24584](https://github.com/ant-design/ant-design/pull/24584)
|
||||
- Button
|
||||
- 🆕 New `type="text"` Button. [#22552](https://github.com/ant-design/ant-design/pull/22552)
|
||||
- 💄 Improve button background variable usage. [#24372](https://github.com/ant-design/ant-design/pull/24372) [@morenyang](https://github.com/morenyang)
|
||||
- Upload
|
||||
- 🆕 `data` could return `Promise` now. [#24546](https://github.com/ant-design/ant-design/pull/24546) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 Support `progress` to customize progress bar. [#24319](https://github.com/ant-design/ant-design/pull/24319) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 Fix progress bar override by accident. [#24339](https://github.com/ant-design/ant-design/pull/24339) [@morenyang](https://github.com/morenyang)
|
||||
- Table
|
||||
- 🆕 Table support `rowSelection.hideSelectAll` to hide selectAll checkbox. [#24592](https://github.com/ant-design/ant-design/pull/24592) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 `ellipsis` support `showTitle` to config `title` show. [#24056](https://github.com/ant-design/ant-design/pull/24056) [@lijinke666](https://github.com/lijinke666)
|
||||
- 🆕 Table `columns` support `shouldCellUpdate`. [#23872](https://github.com/ant-design/ant-design/pull/23872)
|
||||
- Input
|
||||
- 🆕 Input.Passowrd support custom icon. [#23792](https://github.com/ant-design/ant-design/pull/23792)
|
||||
- 🐞 Fix Input.Password still show `value` attribute in DOM after blur it. [#24535](https://github.com/ant-design/ant-design/pull/24535)
|
||||
- 💄 Add less variable `@input-disabled-color`. [#23775](https://github.com/ant-design/ant-design/pull/23775) [@alwaysloseall](https://github.com/alwaysloseall)
|
||||
- Form
|
||||
- 🐞 Fix Form.Item inline `label` collapsed when in narrow space. [#24531](https://github.com/ant-design/ant-design/pull/24531)
|
||||
- 🐞 Fix Form.List field status sync logic and add a nest fields demo. [#24009](https://github.com/ant-design/ant-design/pull/24009)
|
||||
- 🆕 Form support `validateTrigger` to config children fields validate trigger. [#23972](https://github.com/ant-design/ant-design/pull/23972)
|
||||
- Menu
|
||||
- 🆕 Adjust text shows the first character when Menu is collapsed in `inline` mode. [#24330](https://github.com/ant-design/ant-design/pull/24330)
|
||||
- 🆕 Menu.Item support `danger` prop. [#23785](https://github.com/ant-design/ant-design/pull/23785)
|
||||
- Avatar
|
||||
- 🆕 Avatar support `gap` to set the unit distance between left and right sides. [#24357](https://github.com/ant-design/ant-design/pull/24357)
|
||||
- 🐞 Fix Avatar `onError` trigger twice. [#24506](https://github.com/ant-design/ant-design/pull/24506) [@sanonz](https://github.com/sanonz)
|
||||
- Typography
|
||||
- 🆕 Support Typography.Paragraph custom expand style. [#24385](https://github.com/ant-design/ant-design/pull/24385) [@fireairforce](https://github.com/fireairforce)
|
||||
- 🆕 Typography.Text support `keyboard` style. [#24195](https://github.com/ant-design/ant-design/pull/24195)
|
||||
- 🆕 Add Link component. [#24019](https://github.com/ant-design/ant-design/pull/24019)
|
||||
- 🐞 Fix Typography `title` prop support. [#24440](https://github.com/ant-design/ant-design/pull/24440) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 Tooltip support `color` to config background color. [#23155](https://github.com/ant-design/ant-design/pull/23155)
|
||||
- 🆕 Popconfirm can be closed by pressing `ESC` now. [#24420](https://github.com/ant-design/ant-design/pull/24420)
|
||||
- 🆕 Tooltip `destroyTooltipOnHide` support `keepParent` config. [#24362](https://github.com/ant-design/ant-design/pull/24362) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 Notification support to config `prefixCls`. [#24295](https://github.com/ant-design/ant-design/pull/24295) [@tdida](https://github.com/tdida)
|
||||
- 🆕 RangePicker `dateRender` support additional argument to detect is `start` or `end` field. [#24278](https://github.com/ant-design/ant-design/pull/24278)
|
||||
- 🆕 Skeleton add `round` prop to enable paragraph and title show radius. [#24137](https://github.com/ant-design/ant-design/pull/24137) [@xilihuasi](https://github.com/xilihuasi)
|
||||
- 🆕 Transfer support `oneWay` and `pagination`. [#24041](https://github.com/ant-design/ant-design/pull/24041)
|
||||
- 🆕 Message support customize `className` and `style`. [#24024](https://github.com/ant-design/ant-design/pull/24024) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 ConfigProvider support `virtual` and `dropdownMatchSelectWidth`. [#23841](https://github.com/ant-design/ant-design/pull/23841) [@hengkx](https://github.com/hengkx)
|
||||
- 🐞 Fix Breadcrumb icon margin missing when using links. [#24490](https://github.com/ant-design/ant-design/pull/24490) [@EscapeB](https://github.com/EscapeB)
|
||||
- 🐞 Fix Cascader expand icon color when disabled. [#24521](https://github.com/ant-design/ant-design/pull/24521)
|
||||
- 🐞 Fix List warning about `React does not recognize colStyle prop`. [#24568](https://github.com/ant-design/ant-design/pull/24568)
|
||||
- 🐞 Fix Progress with `steps` don't update `percent` expectedly. [#24534](https://github.com/ant-design/ant-design/pull/24534) [@ChuckJonas](https://github.com/ChuckJonas)
|
||||
- 🐞 Fix Steps `subtitle` transition style. [#24593](https://github.com/ant-design/ant-design/pull/24593)
|
||||
- 🐞 Fix Alert close icon `padding` style. [#24471](https://github.com/ant-design/ant-design/pull/24471)
|
||||
- 🐞 Fix Tree `@tree-directory-selected-bg` don't work. [#24468](https://github.com/ant-design/ant-design/pull/24468) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 Fix `@ant-prefix` don't work on some styles. [#24459](https://github.com/ant-design/ant-design/pull/24459) [@morenyang](https://github.com/morenyang)
|
||||
- 💄 Descriptions add less variables `@descriptions-item-trailing-colon` and etc. [#24032](https://github.com/ant-design/ant-design/pull/24032) [@hengkx](https://github.com/hengkx)
|
||||
- 🌐 Localization
|
||||
- 🇮🇪 Add Irish(ga_IE) locale. [#24609](https://github.com/ant-design/ant-design/pull/24609) [@AbhijeetGaware](https://github.com/AbhijeetGaware)
|
||||
- 🇫🇮 Improve Typography `fi_FI` locale. [#24591](https://github.com/ant-design/ant-design/pull/24591) [@sagge](https://github.com/sagge)
|
||||
- 🇧🇷 Improve `pt_BR` locale. [#24518](https://github.com/ant-design/ant-design/pull/24518) [@arturpfb](https://github.com/arturpfb)
|
||||
- 🇬🇧 Improve Form `en_GB` locale. [#24404](https://github.com/ant-design/ant-design/pull/24404) [@morenyang](https://github.com/morenyang)
|
||||
- RTL
|
||||
- 💄 Optimize Tree checkbox style in RTL. [#24563](https://github.com/ant-design/ant-design/pull/24563)
|
||||
- 💄 Optimize Calendar notice content text style in RTL. [#24528](https://github.com/ant-design/ant-design/pull/24528)
|
||||
- 💄 Optimize Table filter dropdown style in RTL. [#24529](https://github.com/ant-design/ant-design/pull/24529)
|
||||
- 💄 Fix Cascader dropdown style in RTL. [#24520](https://github.com/ant-design/ant-design/pull/24520)
|
||||
- TypeScript
|
||||
- 🛠 Form export `RuleObject` and `RuleRender` types. [#24541](https://github.com/ant-design/ant-design/pull/24541) [@sorteam](https://github.com/sorteam)
|
||||
|
||||
## 4.2.5
|
||||
|
||||
`2020-05-25`
|
||||
|
||||
- 🐞 Fix Table selection arrow out of column when `size` is `small/middle`. [#24394](https://github.com/ant-design/ant-design/pull/24394)
|
||||
- 🐞 Fix Input.TextArea clear icon disappears in Input.Group when hover it. [#24360](https://github.com/ant-design/ant-design/pull/24360) [@Mr-jiangzhiguo](https://github.com/Mr-jiangzhiguo)
|
||||
- 🐞 Fixed an issue where the `RowSelection.onChange` will still be cached when the Table removes entries in `dataSource`. [#24338](https://github.com/ant-design/ant-design/pull/24338)
|
||||
- 🐞 Adjust `useNotification` api instance to be same instance for each render. [#24337](https://github.com/ant-design/ant-design/pull/24337)
|
||||
- 🐞 Fix Button `loading` transition animation missing and Modal `confirmLoading` not being reset. [#24328](https://github.com/ant-design/ant-design/pull/24328)
|
||||
- 🐞 Fix Drawer cover background elements when it is not visible. [#24290](https://github.com/ant-design/ant-design/pull/24290)
|
||||
- 🐞 Fix Cascader/Select/Table/TreeSelect text color when data empty. [#24279](https://github.com/ant-design/ant-design/pull/24279)
|
||||
- 💄 Fix InputNumber operation button arrow is not centered. [#24266](https://github.com/ant-design/ant-design/pull/24266)
|
||||
- 🐞 Fix Table with empty array `filteredValue` still highlight the filtered icon. [#24263](https://github.com/ant-design/ant-design/pull/24263)
|
||||
- 🐞 Fix Cascader not support `number[]` value. [#24247](https://github.com/ant-design/ant-design/pull/24247)
|
||||
- ⌨️ Fix Switch `autoFocus` trigger when `disabled` removed. Adjust style to avoid switch shaking. Remove blur logic when `onMouseUp` to improve acessibility. [#24254](https://github.com/ant-design/ant-design/pull/24254)
|
||||
- 💄 Add Menu default `text-align` style. [#24253](https://github.com/ant-design/ant-design/pull/24253)
|
||||
- 🛠 Refactor List code. [#24280](https://github.com/ant-design/ant-design/pull/24280) [@hengkx](https://github.com/hengkx)
|
||||
- 🛠 Modify the Alert with hooks to support strict mode. [#24236](https://github.com/ant-design/ant-design/pull/24236) [@hengkx](https://github.com/hengkx)
|
||||
- 🐞Fix Card perfermance bug when use with `react-split`. [#24425](https://github.com/ant-design/ant-design/pull/24425)
|
||||
- TypeScript
|
||||
- 🛠Cascader ts definition update. [#24393](https://github.com/ant-design/ant-design/pull/24393) [@zhangyu1818](https://github.com/zhangyu1818)
|
||||
- 🐞 Fix TS error of `Could not find a declaration rc-upload`. [#24325](https://github.com/ant-design/ant-design/pull/24325)
|
||||
- 🛠 Add children type to BackTop. [#24235](https://github.com/ant-design/ant-design/pull/24235)
|
||||
|
||||
## 4.2.4
|
||||
|
||||
`2020-05-18`
|
||||
|
||||
- 🐞 Revert Switch patch to fix handle position style issue with `unCheckedChildren`. [#24242](https://github.com/ant-design/ant-design/pull/24242)
|
||||
- 💄 Adjust Upload icon default color to red in error status. [#24160](https://github.com/ant-design/ant-design/pull/24160)
|
||||
- 💄 Adjust Dropdown arrow position a little higher. [#24215](https://github.com/ant-design/ant-design/pull/24215)
|
||||
- 🌐 Form `defaultValidateMessages` support `ru_RU`. [#24219](https://github.com/ant-design/ant-design/pull/24219) [@aivinog1](https://github.com/aivinog1)
|
||||
|
||||
## 4.2.3
|
||||
|
||||
`2020-05-16`
|
||||
|
||||
- 🐞 Refactor `rc-progress` to resolve `h3g is not defined` error in `<script src="antd.min.js" />`. [#24127](https://github.com/ant-design/ant-design/pull/24127)
|
||||
- 📖 Rewrote [Use in create-react-app](https://ant.design/docs/react/use-with-create-react-app). [#24184](https://github.com/ant-design/ant-design/pull/24184)
|
||||
- Drawer
|
||||
- 🐞 Fix Drawer `getContainer={false}` height overflow issue. [#24082](https://github.com/ant-design/ant-design/pull/24082)
|
||||
- 🐞 Fix Drawer `mask={false}` animation not working. [#24082](https://github.com/ant-design/ant-design/pull/24082)
|
||||
- BackTop
|
||||
- 🛠 Refactor BackTop with hooks. [#23575](https://github.com/ant-design/ant-design/pull/23575)
|
||||
- 🐞 Fix BackTop not working in iframe of Chrome. [#24194](https://github.com/ant-design/ant-design/pull/24194)
|
||||
- DatePicker
|
||||
- 🐞 Fix DatePicker with `showToday` not working with `disabledDate`. [#24190](https://github.com/ant-design/ant-design/pull/24190)
|
||||
- 🐞 Fix DatePicker `renderExtraFooter` with long content exceed content width. [#24145](https://github.com/ant-design/ant-design/pull/24145)
|
||||
- Button
|
||||
- 🐞 Fix small Button align issue when customize theme. [#24097](https://github.com/ant-design/ant-design/pull/24097)
|
||||
- 🐞 Fix Button children not working with Tooltip. [#24095](https://github.com/ant-design/ant-design/pull/24095)
|
||||
- 🛠 Refactor Tooltip with hooks. [#23699](https://github.com/ant-design/ant-design/pull/23699)
|
||||
- 🐞 Avoid `disabled` Upload.Dragger being triggered by clicking Form `label`. [#24202](https://github.com/ant-design/ant-design/pull/24202)
|
||||
- 🐞 Fix Select selected option not interactive (such as `title` not working). [#24170](https://github.com/ant-design/ant-design/pull/24170)
|
||||
- 🐞 Fix Switch shake in Safari and iOS Chrome. [#24122](https://github.com/ant-design/ant-design/pull/24122) [@lexlexa](https://github.com/lexlexa)
|
||||
- 🐞 Carousel upgrade to `react-slick@0.26.1` to resolve some problems. [#24067](https://github.com/ant-design/ant-design/pull/24067)
|
||||
- 🐞 Cascader will display `defaultValue` instead of empty string when no matched options. [#24058](https://github.com/ant-design/ant-design/pull/24058) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🌎 Improve `zh_TW` localisations. [#24065](https://github.com/ant-design/ant-design/pull/24065) [@wx1322](https://github.com/wx1322)
|
||||
- 🐞 Fix Table `onChange` pagination type. [#24114](https://github.com/ant-design/ant-design/pull/24114) [@sorteam](https://github.com/sorteam)
|
||||
- 💄 Add less variable `@card-head-extra-color`. [#24189](https://github.com/ant-design/ant-design/pull/24189)
|
||||
- 💄 Adjust Pagination simple mode background to transparent. [#24152](https://github.com/ant-design/ant-design/pull/24152)
|
||||
- 💄 Fix dark Menu link color. [#24110](https://github.com/ant-design/ant-design/pull/24110)
|
||||
- RTL
|
||||
- 💄 Fix Dropdown.Button default menu placement in RTL. [#24150](https://github.com/ant-design/ant-design/pull/24150)
|
||||
- 💄 Fix Menu `border` in RTL. [#24101](https://github.com/ant-design/ant-design/pull/24101)
|
||||
- 💄 Optimize Select multiple tag style in RTL. [#24112](https://github.com/ant-design/ant-design/pull/24112)
|
||||
- 💄 Optimize Typography `expand` style in RTL. [#24084](https://github.com/ant-design/ant-design/pull/24084)
|
||||
- 💄 Optimize Pagination slash style in RTL. [#24154](https://github.com/ant-design/ant-design/pull/24154)
|
||||
|
||||
## 4.2.2
|
||||
|
||||
`2020-05-11`
|
||||
@@ -52,8 +238,8 @@ timeline: true
|
||||
- 🐞 Fix Slider `marks` selected problem when dragging. [#23773](https://github.com/ant-design/ant-design/pull/23773)
|
||||
- 🛠 Timeline refactors with React Hooks. [#23631](https://github.com/ant-design/ant-design/pull/23631) [@hengkx](https://github.com/hengkx)
|
||||
- 🌎 Localization
|
||||
- 🌐 Add Farsi `fa_IR` default locale template localisations. [#23926](https://github.com/ant-design/ant-design/pull/23926) [@NarimanMov](https://github.com/NarimanMov)
|
||||
- 🌐 Add default `en` default locale template localisations for Form. [#23859](https://github.com/ant-design/ant-design/pull/23859) [@mjfwebb](https://github.com/mjfwebb)
|
||||
- 🇮🇷 Add Farsi `fa_IR` default locale template localisations. [#23926](https://github.com/ant-design/ant-design/pull/23926) [@NarimanMov](https://github.com/NarimanMov)
|
||||
- 🇺🇸 Add default `en` default locale template localisations for Form. [#23859](https://github.com/ant-design/ant-design/pull/23859) [@mjfwebb](https://github.com/mjfwebb)
|
||||
- 📦 Reduce bundle size
|
||||
- 🗑 Reduce bundle size via removing `react-lifecycles-compat`. [#23969](https://github.com/ant-design/ant-design/pull/23969)
|
||||
- 🛠 Reduce bundle size via excluding `package.json` from source code. [#23957](https://github.com/ant-design/ant-design/pull/23957)
|
||||
|
||||
@@ -15,6 +15,192 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 4.3.2
|
||||
|
||||
`2020-06-06`
|
||||
|
||||
- 🐞 修复 Tag.CheckableTag 不支持 `onClick` 和 `stopPropagation` 的问题。[#24743](https://github.com/ant-design/ant-design/pull/24743)
|
||||
- 🐞 修复 Drawer 支持通过 ConfigProvider 来全局设置 `getPrefixCls` 和 `getPopupContainer`。[#24727](https://github.com/ant-design/ant-design/pull/24727)
|
||||
- 🐞 修复 Button 在父组件重新渲染时 `loading.delay` 会重复触发的问题。[#24713](https://github.com/ant-design/ant-design/pull/24713)
|
||||
- 🐞 修复 Dropdown 带图标 `icon` 菜单项的链接色彩。[#24707](https://github.com/ant-design/ant-design/pull/24707) [#24702](https://github.com/ant-design/ant-design/pull/24702)
|
||||
- Select
|
||||
- 🐞 修复 Select 在紧凑模式下表现不正常。[#24706](https://github.com/ant-design/ant-design/pull/24706)
|
||||
- ⚡️ 优化 Select 多选模式的性能。[#24785](https://github.com/ant-design/ant-design/pull/24785) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🐞 修复 Calendar 在同一个面板下选择日期也会触发 `onPanelChange` 的问题。[#24695](https://github.com/ant-design/ant-design/pull/24695)
|
||||
- 🐞 修复 Input 组件在 IE11 中高度异常问题。[#24673](https://github.com/ant-design/ant-design/pull/24673) [@xiaosongxiaosong](https://github.com/xiaosongxiaosong)
|
||||
- 🐞 修复 Radio 的 TypeScript 定义错误。[#24693](https://github.com/ant-design/ant-design/pull/24693) [@hengkx](https://github.com/hengkx)
|
||||
- 🐞 修复 Statistic 不能包裹 Tooltip 的问题。[#24782](https://github.com/ant-design/ant-design/pull/24782)
|
||||
- 🐞 修复 TimePicker.RangePicker 指定 `className` 后无边框样式失效的问题。[#24781](https://github.com/ant-design/ant-design/pull/24781)
|
||||
- 🐞 修复 List 翻页时 `onChange` 不触发的问题。[#24514](https://github.com/ant-design/ant-design/pull/24514)
|
||||
- 🌐 国际化
|
||||
- 🇮🇱 Form 校验文案增加希伯来语(以色列)。[#24716](https://github.com/ant-design/ant-design/pull/24716) [@israelKusayev](https://github.com/israelKusayev)
|
||||
- 🇰🇷 Form 校验文案增加韩文。[#24783](https://github.com/ant-design/ant-design/pull/24783) [@Jaewoook](https://github.com/Jaewoook)
|
||||
- 💄 新增 less 变量 `@table-font-size`,`@table-font-size-md` 和 `@table-font-size-sm`,用于自定义 Table 文字大小。[#24714](https://github.com/ant-design/ant-design/pull/24714) [@morenyang](https://github.com/morenyang)
|
||||
- RTL
|
||||
- 💄 优化 Tabs 标签下拉框在 RTL 模式下样式。[#24715](https://github.com/ant-design/ant-design/pull/24715)
|
||||
- 💄 增加 `Modal.method()` RTL 模式支持,仅限 hooks 用法。[#24682](https://github.com/ant-design/ant-design/pull/24682)
|
||||
- 💄 修复 Badge RTL 模式位置偏移量设置。[#24724](https://github.com/ant-design/ant-design/pull/24724)
|
||||
|
||||
## 4.3.1
|
||||
|
||||
`2020-06-02`
|
||||
|
||||
- Tabs
|
||||
- 🐞 修复 Tabs `hideAdd` 无效的问题。[#24621](https://github.com/ant-design/ant-design/pull/24621)
|
||||
- 🐞 修复 Tabs 下拉菜单内在 Firefox 下出现水平滚动条。[#24677](https://github.com/ant-design/ant-design/pull/24677)
|
||||
- 🐞 修复 Tabs 配合 `react-sticky` 使用时下划线遗失问题。[#24643](https://github.com/ant-design/ant-design/pull/24643)
|
||||
- 💄 调整 Tabs `tabBarStyle` 的展示样式。[#24620](https://github.com/ant-design/ant-design/pull/24620)
|
||||
- Button
|
||||
- 🐞 修复 Button 将 `loading` 从 `delay` 快速切换至 `false` 时仍然会变成加载状态的问题。[#24678](https://github.com/ant-design/ant-design/pull/24678)
|
||||
- 🐞 修复 Text Button 在 `danger` 时样式不一致的问题。[#24622](https://github.com/ant-design/ant-design/pull/24622) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 修复 Table 包裹在 Row 中时无法展现横向滚动条的问题。[#24661](https://github.com/ant-design/ant-design/pull/24661) [@zt123123](https://github.com/zt123123)
|
||||
- 🐞 修复 Drawer 会报 dom 节点设置 `dropdownMatchSelectWidth` 的警告信息。[#24651](https://github.com/ant-design/ant-design/pull/24651)
|
||||
- 🐞 调整 Steps 现支持 `children` 下使用 React.Fragment。[#24644](https://github.com/ant-design/ant-design/pull/24644)
|
||||
- 🐞 解决 Upload 删除图标键盘无法导航操作的问题。[#24615](https://github.com/ant-design/ant-design/pull/24615) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 修复多选 Select 输入框的光标展示问题。[#24631](https://github.com/ant-design/ant-design/pull/24631)
|
||||
- 🐞 修复 Radio.Group 设置 `options` 报错的问题。[#24631](https://github.com/ant-design/ant-design/pull/24631)
|
||||
- RTL
|
||||
- 💄 调整 Notification RTL 模式下默认弹窗位置为左上。[#24632](https://github.com/ant-design/ant-design/pull/24632)
|
||||
- TypeScript
|
||||
- 🛠 导出 Tabs `TabPaneProps` 定义。[#24648](https://github.com/ant-design/ant-design/pull/24648)
|
||||
|
||||
## 4.3.0
|
||||
|
||||
`2020-05-31`
|
||||
|
||||
- 🔥 重做 Tabs 以提升多标签在不同环境下的用户体验。[#24552](https://github.com/ant-design/ant-design/pull/24552)
|
||||
- 📖 新增组件[总览页面](https://ant.design/components/overview-cn)。[#24491](https://github.com/ant-design/ant-design/pull/24491) [@arvinxx](https://github.com/arvinxx)
|
||||
- 🛠 增加大量功能,同时减少了包体积(相比 `4.2.5` 减少了 2KB)。[#24584](https://github.com/ant-design/ant-design/pull/24584)
|
||||
- Button
|
||||
- 🆕 新增文本类型按钮 `type="text"`。[#22552](https://github.com/ant-design/ant-design/pull/22552)
|
||||
- 💄 优化 Button 背景 less 变量的影响范围。[#24372](https://github.com/ant-design/ant-design/pull/24372) [@morenyang](https://github.com/morenyang)
|
||||
- Upload
|
||||
- 🆕 `data` 属性支持返回 `Promise`。[#24546](https://github.com/ant-design/ant-design/pull/24546) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 添加 `progress` 属性以支持自定义进度条。[#24319](https://github.com/ant-design/ant-design/pull/24319) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 修复进度条类型会被意外覆盖的问题。[#24339](https://github.com/ant-design/ant-design/pull/24339) [@morenyang](https://github.com/morenyang)
|
||||
- Table
|
||||
- 🆕 Table 新增 `rowSelection.hideSelectAll` 用于隐藏全选框。[#24592](https://github.com/ant-design/ant-design/pull/24592) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 `ellipsis` 支持 `showTitle` 以关闭自动设置 `title` 属性。[#24056](https://github.com/ant-design/ant-design/pull/24056) [@lijinke666](https://github.com/lijinke666)
|
||||
- 🆕 Table `columns` 支持 `shouldCellUpdate` 属性。[#23872](https://github.com/ant-design/ant-design/pull/23872)
|
||||
- Input
|
||||
- 🆕 Input.Passowrd 支持自定义图标。[#23792](https://github.com/ant-design/ant-design/pull/23792)
|
||||
- 🐞 修复 Input.Password 一个明文显示 `value` 的问题。[#24535](https://github.com/ant-design/ant-design/pull/24535)
|
||||
- 💄 添加 `@input-disabled-color` less 变量。[#23775](https://github.com/ant-design/ant-design/pull/23775) [@alwaysloseall](https://github.com/alwaysloseall)
|
||||
- Form
|
||||
- 🆕 Form 添加 `validateTrigger` 支持全局设置子字段校验时机。[#23972](https://github.com/ant-design/ant-design/pull/23972)
|
||||
- 🐞 修复 Form.Item 内联样式下 `label` 在狭窄空间被挤压的问题。[#24531](https://github.com/ant-design/ant-design/pull/24531)
|
||||
- 🐞 修复 Form.List 字段状态同步逻辑并添加嵌套字段示例。[#24009](https://github.com/ant-design/ant-design/pull/24009)
|
||||
- Menu
|
||||
- 🆕 调整 Menu `inline` 模式下未设置 `icon` 的菜单收起时文字显示第一个字符。[#24330](https://github.com/ant-design/ant-design/pull/24330)
|
||||
- 🆕 Menu.Item 支持 `danger` 属性。[#23785](https://github.com/ant-design/ant-design/pull/23785)
|
||||
- Avatar
|
||||
- 🆕 Avatar 新增 `gap` 来设置字符类型距离左右两侧边界单位像素。[#24357](https://github.com/ant-design/ant-design/pull/24357)
|
||||
- 🐞 修复 Avatar `onError` 会触发两次的问题。[#24506](https://github.com/ant-design/ant-design/pull/24506) [@sanonz](https://github.com/sanonz)
|
||||
- Typography
|
||||
- 🆕 Typography.Paragraph 支持自定义展开样式。[#24385](https://github.com/ant-design/ant-design/pull/24385) [@fireairforce](https://github.com/fireairforce)
|
||||
- 🆕 Typography.Text 支持 `keyboard` 样式。[#24195](https://github.com/ant-design/ant-design/pull/24195)
|
||||
- 🆕 添加 Link 组件。[#24019](https://github.com/ant-design/ant-design/pull/24019)
|
||||
- 🐞 修复 Typography 不支持 `title` 属性的问题。[#24440](https://github.com/ant-design/ant-design/pull/24440) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 Tooltip 支持配置背景颜色。[#23155](https://github.com/ant-design/ant-design/pull/23155)
|
||||
- 🆕 Popconfirm 支持按 `ESC` 关闭。[#24420](https://github.com/ant-design/ant-design/pull/24420)
|
||||
- 🆕 Tooltip `destroyTooltipOnHide` 支持 `keepParent` 配置。[#24362](https://github.com/ant-design/ant-design/pull/24362) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 Notification 支持全局配置 `prefixCls`。[#24295](https://github.com/ant-design/ant-design/pull/24295) [@tdida](https://github.com/tdida)
|
||||
- 🆕 RangePicker `dateRender` 支持额外参数来判断是 `start` 还是 `end` 字段。[#24278](https://github.com/ant-design/ant-design/pull/24278)
|
||||
- 🆕 Skeleton 添加 `round` 属性,允许段落和标题显示圆角。[#24137](https://github.com/ant-design/ant-design/pull/24137) [@xilihuasi](https://github.com/xilihuasi)
|
||||
- 🆕 Transfer 支持 `oneWay` 配置单向选择以及 `pagination` 配置分页。[#24041](https://github.com/ant-design/ant-design/pull/24041)
|
||||
- 🆕 Message 支持自定义样式通过使用`className`和`style`。[#24024](https://github.com/ant-design/ant-design/pull/24024) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🆕 ConfigProvider 支持 `virtual` 和 `dropdownMatchSelectWidth` 配置。[#23841](https://github.com/ant-design/ant-design/pull/23841) [@hengkx](https://github.com/hengkx)
|
||||
- 🐞 修复 Cascader 下拉框中扩展按钮在禁用时的颜色。[#24521](https://github.com/ant-design/ant-design/pull/24521)
|
||||
- 🐞 修复 Alert 关闭按钮 `padding` 样式。[#24471](https://github.com/ant-design/ant-design/pull/24471)
|
||||
- 🐞 修复 Tree `@tree-directory-selected-bg` 变量不生效的问题。[#24468](https://github.com/ant-design/ant-design/pull/24468) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 修复 `@ant-prefix` 变量在部分样式里不生效的问题。[#24459](https://github.com/ant-design/ant-design/pull/24459) [@morenyang](https://github.com/morenyang)
|
||||
- 🐞 修复 Steps `subtitle` hover 渐变过渡。[#24593](https://github.com/ant-design/ant-design/pull/24593)
|
||||
- 🐞 修复 List 报 `React does not recognize colStyle prop` 的问题。[#24568](https://github.com/ant-design/ant-design/pull/24568)
|
||||
- 🐞 修复步骤 Progress `percent` 样式未正确更新的问题。[#24534](https://github.com/ant-design/ant-design/pull/24534) [@ChuckJonas](https://github.com/ChuckJonas)
|
||||
- 🐞 修复 Breadcrumb 内使用链接时图标间距丢失的问题。[#24490](https://github.com/ant-design/ant-design/pull/24490) [@EscapeB](https://github.com/EscapeB)
|
||||
- 💄 Descriptions 新增 `@descriptions-item-trailing-colon` 等 less 变量。[#24032](https://github.com/ant-design/ant-design/pull/24032) [@hengkx](https://github.com/hengkx)
|
||||
- 🌐 国际化
|
||||
- 🇮🇪 新增爱尔兰语言包。[#24609](https://github.com/ant-design/ant-design/pull/24609) [@AbhijeetGaware](https://github.com/AbhijeetGaware)
|
||||
- 🇫🇮 改进 Typography `fi_FI` 国际化。[#24591](https://github.com/ant-design/ant-design/pull/24591) [@sagge](https://github.com/sagge)
|
||||
- 🇧🇷 改进 `pt_BR` 国际化。[#24518](https://github.com/ant-design/ant-design/pull/24518) [@arturpfb](https://github.com/arturpfb)
|
||||
- 🇬🇧 改进 Form `en_GB` 国际化。[#24404](https://github.com/ant-design/ant-design/pull/24404) [@morenyang](https://github.com/morenyang)
|
||||
- RTL
|
||||
- 💄 优化 Tree RTL 模式下选项框样式。[#24563](https://github.com/ant-design/ant-design/pull/24563)
|
||||
- 💄 优化 Calendar 通知事项文字在 RTL 模式下的样式。[#24528](https://github.com/ant-design/ant-design/pull/24528)
|
||||
- 💄 优化 Table 筛选下拉框在 RTL 模式下样式。[#24529](https://github.com/ant-design/ant-design/pull/24529)
|
||||
- 💄 优化 Cascader RTL 模式下拉框的样式。[#24520](https://github.com/ant-design/ant-design/pull/24520)
|
||||
- TypeScript
|
||||
- 🛠 Form 导出 `RuleObject` 与 `RuleRender` 定义。[#24541](https://github.com/ant-design/ant-design/pull/24541) [@sorteam](https://github.com/sorteam)
|
||||
|
||||
## 4.2.5
|
||||
|
||||
`2020-05-25`
|
||||
|
||||
- 🐞 修复 Table 在 `dataSource` 移除条目时,`rowSelection.onChange` 仍然会缓存的问题。[#24338](https://github.com/ant-design/ant-design/pull/24338)
|
||||
- 🐞 修复 Table 的选中箭头在 `size=small/middle` 时超出的问题。[#24394](https://github.com/ant-design/ant-design/pull/24394)
|
||||
- 🐞 修复 Input.Group 内 Input.TextArea `hover` 时清除图标消失的问题。[#24360](https://github.com/ant-design/ant-design/pull/24360) [@Mr-jiangzhiguo](https://github.com/Mr-jiangzhiguo)
|
||||
- 🐞 修复 Notificiation 使用 `useNotificiation` 时无限 render 的行为。[#24337](https://github.com/ant-design/ant-design/pull/24337)
|
||||
- 🐞 修复 Button `loading` 切换动画丢失和 Modal `confirmLoading` 按钮未复位的问题。[#24328](https://github.com/ant-design/ant-design/pull/24328)
|
||||
- 🐞 修复 Drawer 关闭后依然会遮挡页面元素的问题。[#24290](https://github.com/ant-design/ant-design/pull/24290)
|
||||
- 🐞 修复 Cascader/Select/Table/TreeSelect 空数据时字体的颜色。[#24279](https://github.com/ant-design/ant-design/pull/24279)
|
||||
- 💄 优化 InputNumber 操作按钮居中样式。[#24266](https://github.com/ant-design/ant-design/pull/24266)
|
||||
- 🐞 修复 Table 在 `filteredValue` 使用空数组时仍然会高亮过滤图标的问题。[#24263](https://github.com/ant-design/ant-design/pull/24263)
|
||||
- 🐞 修复 Cascader 不支持 `number[]` 类型 `value` 的问题。[#24247](https://github.com/ant-design/ant-design/pull/24247)
|
||||
- ⌨️ 修复 Switch `autoFocus` 在 `disabled` 移除后会触发的问题,调整样式以避免切换时额外的抖动,并移除鼠标点击失焦逻辑以提升无障碍体验。[#24254](https://github.com/ant-design/ant-design/pull/24254)
|
||||
- 💄 增加 Menu 默认 `text-align` 样式定义以修复被外部样式影响的问题。[#24253](https://github.com/ant-design/ant-design/pull/24253)
|
||||
- 🛠 用 hooks 重构 List。[#24280](https://github.com/ant-design/ant-design/pull/24280) [@hengkx](https://github.com/hengkx)
|
||||
- 🛠 用 hooks 重构 Alert 以支持严格模式。[#24236](https://github.com/ant-design/ant-design/pull/24236) [@hengkx](https://github.com/hengkx)
|
||||
- 🐞 修复 Card 和 `react-split` 一起使用时卡顿的问题。[#24425](https://github.com/ant-design/ant-design/pull/24425)
|
||||
- TypeScript
|
||||
- 🛠 优化 Cascader 的 TypeScript 定义。[#24393](https://github.com/ant-design/ant-design/pull/24393) [@zhangyu1818](https://github.com/zhangyu1818)
|
||||
- 🐞 修复 Upload TypeScript 报错:`Could not find a declaration rc-upload` 的问题。[#24325](https://github.com/ant-design/ant-design/pull/24325)
|
||||
- 🛠 BackTop 增加 `children` 定义。[#24235](https://github.com/ant-design/ant-design/pull/24235)
|
||||
|
||||
## 4.2.4
|
||||
|
||||
`2020-05-18`
|
||||
|
||||
- 🐞 回滚 Switch 以修复配置 `unCheckedChildren` 时,控制点位置样式问题。[#24242](https://github.com/ant-design/ant-design/pull/24242)
|
||||
- 💄 调整 Upload 错误状态图标的颜色默认为红色。[#24160](https://github.com/ant-design/ant-design/pull/24160)
|
||||
- 💄 向上微调 Dropdown 箭头位置。[#24215](https://github.com/ant-design/ant-design/pull/24215)
|
||||
- 🌐 Form `defaultValidateMessages` 支持 `ru_RU`。[#24219](https://github.com/ant-design/ant-design/pull/24219) [@aivinog1](https://github.com/aivinog1)
|
||||
|
||||
## 4.2.3
|
||||
|
||||
`2020-05-16`
|
||||
|
||||
- 🐞 重构 `rc-progress` 以解决 `<script src="antd.min.js" />` 会抛出 `h3g is not defined` 的问题。[#24127](https://github.com/ant-design/ant-design/pull/24127)
|
||||
- 📖 重写了 [在 create-react-app 中使用](https://ant.design/docs/react/use-with-create-react-app-cn)。[#24184](https://github.com/ant-design/ant-design/pull/24184)
|
||||
- Drawer
|
||||
- 🐞 修复 Drawer `getContainer={false}` 时的高度问题。[#24082](https://github.com/ant-design/ant-design/pull/24082)
|
||||
- 🐞 修复 Drawer `mask={false}` 时隐藏动画不生效的问题。[#24082](https://github.com/ant-design/ant-design/pull/24082)
|
||||
- BackTop
|
||||
- 🛠 BackTop 使用 hooks 重构。[#23575](https://github.com/ant-design/ant-design/pull/23575)
|
||||
- 🐞 修复 BackTop 在 Chrome 的 iframe 里不生效的问题。[#24194](https://github.com/ant-design/ant-design/pull/24194)
|
||||
- DatePicker
|
||||
- 🐞 修复 DatePicker `disabledDate` 不会作用到 `showToday` 上的问题。[#24190](https://github.com/ant-design/ant-design/pull/24190)
|
||||
- 🐞 修复 DatePicker `renderExtraFooter` 内容过长超出容器宽度的问题。[#24145](https://github.com/ant-design/ant-design/pull/24145)
|
||||
- Button
|
||||
- 🐞 修复 Button 内图标无法使用 Tooltip 的问题。[#24095](https://github.com/ant-design/ant-design/pull/24095)
|
||||
- 🐞 修复定制主题时小号 Button 错位的问题。[#24097](https://github.com/ant-design/ant-design/pull/24097)
|
||||
- 🛠 Tooltip 使用 hooks 重构。[#23699](https://github.com/ant-design/ant-design/pull/23699)
|
||||
- 🐞 修复 Upload.Dragger 禁用时依然会被 Form `label` 触发的问题。[#24202](https://github.com/ant-design/ant-design/pull/24202)
|
||||
- 🐞 修复 Select 回填选项无法进行交互的问题(如 `title` 不生效)。[#24170](https://github.com/ant-design/ant-design/pull/24170)
|
||||
- 🐞 修复 Switch 在 Safari 和 iOS Chrome 上点击时错位的问题。[#24122](https://github.com/ant-design/ant-design/pull/24122) [@lexlexa](https://github.com/lexlexa)
|
||||
- 🐞 Carousel 更新依赖到 `react-slick@0.26.1` 以修正一些问题。[#24067](https://github.com/ant-design/ant-design/pull/24067)
|
||||
- 🐞 Cascader 没有匹配任何选项时展示 `defaultValue` 而不是空字符串。[#24058](https://github.com/ant-design/ant-design/pull/24058) [@Kermit-Xuan](https://github.com/Kermit-Xuan)
|
||||
- 🌎 完善繁体中文国际化。[#24065](https://github.com/ant-design/ant-design/pull/24065) [@wx1322](https://github.com/wx1322)
|
||||
- 🐞 修复 Table `onChange` pagination 参数定义。[#24114](https://github.com/ant-design/ant-design/pull/24114) [@sorteam](https://github.com/sorteam)
|
||||
- 💄 新增 less 变量 `@card-head-extra-color`。[#24189](https://github.com/ant-design/ant-design/pull/24189)
|
||||
- 💄 调整 Pagination 简洁模式下按钮的背景色为透明。[#24152](https://github.com/ant-design/ant-design/pull/24152)
|
||||
- 💄 修复暗色 Menu 内的链接颜色。[#24110](https://github.com/ant-design/ant-design/pull/24110)
|
||||
- RTL
|
||||
- 💄 修复 Dropdown.Button 下拉框在 RTL 模式下默认位置。[#24150](https://github.com/ant-design/ant-design/pull/24150)
|
||||
- 💄 优化 Pagination 分隔符在 RTL 下的样式。[#24154](https://github.com/ant-design/ant-design/pull/24154)
|
||||
- 💄 修复 Menu 在 RTL 下的 `border` 样式。[#24101](https://github.com/ant-design/ant-design/pull/24101)
|
||||
- 💄 优化 Select 多选项在 RTL 模式下样式。[#24112](https://github.com/ant-design/ant-design/pull/24112)
|
||||
- 💄 优化 Typography `expand` 在 RTL 下的样式。[#24084](https://github.com/ant-design/ant-design/pull/24084)
|
||||
|
||||
## 4.2.2
|
||||
|
||||
`2020-05-11`
|
||||
@@ -52,8 +238,8 @@ timeline: true
|
||||
- 🐞 修复 Slider 拖拽中选中 `marks` 文本的问题。[#23773](https://github.com/ant-design/ant-design/pull/23773)
|
||||
- 🛠 Timeline 使用 React Hooks 重构。[#23631](https://github.com/ant-design/ant-design/pull/23631) [@hengkx](https://github.com/hengkx)
|
||||
- 🌎 国际化
|
||||
- 🌐 增加波斯语 `fa_IR` 国际化默认提示模板。[#23926](https://github.com/ant-design/ant-design/pull/23926) [@NarimanMov](https://github.com/NarimanMov)
|
||||
- 🌐 增加 Form `en` 国际化默认提示模板[#23859](https://github.com/ant-design/ant-design/pull/23859) [@mjfwebb](https://github.com/mjfwebb)
|
||||
- 🇮🇷 增加波斯语 `fa_IR` 国际化默认提示模板。[#23926](https://github.com/ant-design/ant-design/pull/23926) [@NarimanMov](https://github.com/NarimanMov)
|
||||
- 🇺🇸 增加 Form `en` 国际化默认提示模板[#23859](https://github.com/ant-design/ant-design/pull/23859) [@mjfwebb](https://github.com/mjfwebb)
|
||||
- 📦 包体积优化
|
||||
- 🗑 移除 `react-lifecycles-compat` 依赖以优化包体积。[#23969](https://github.com/ant-design/ant-design/pull/23969)
|
||||
- 🛠 源码中不再引用 `package.json` 从而优化了一点包体积。[#23957](https://github.com/ant-design/ant-design/pull/23957)
|
||||
|
||||
7
Dockerfile.ui-test
Normal file
7
Dockerfile.ui-test
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM buildkite/puppeteer:latest
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
COPY package.json ./
|
||||
RUN npm install
|
||||
ENV PATH="${PATH}:/app/node_modules/.bin"
|
||||
COPY . .
|
||||
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<a href="http://ant.design">
|
||||
<a href="https://ant.design">
|
||||
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
</a>
|
||||
</p>
|
||||
@@ -10,15 +10,44 @@
|
||||
|
||||
Uma solução empresarial de design e biblioteca UI para React.
|
||||
|
||||
[](https://circleci.com/gh/ant-design/ant-design)  [](https://codecov.io/gh/ant-design/ant-design/branch/master) [](https://www.npmjs.com/package/antd) [](http://npmjs.com/antd)
|
||||
[![CircleCI status][circleci-image]][circleci-url] [![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
|
||||
|
||||
[](https://david-dm.org/ant-design/ant-design) [](https://david-dm.org/ant-design/ant-design?type=dev) [](https://lgtm.com/projects/g/ant-design/ant-design/alerts/) [](https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield) [](https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![FOSSA Status][fossa-image]][fossa-url] [![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
|
||||
[](https://twitter.com/AntDesignUI) [](https://gitter.im/ant-design/ant-design-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![Gitter][gitter-english-image]][gitter-english-url] [![Gitter][gitter-chinese-image]][gitter-chinese-url] [![[SemVer stability]][semver-stability-image]][semver-stability-url]
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/antd
|
||||
[circleci-image]: https://img.shields.io/travis/com/ant-design/ant-design.svg?style=flat-square
|
||||
[circleci-url]: https://travis-ci.com/ant-design/ant-design
|
||||
[github-action-image]: https://github.com/ant-design/ant-design/workflows/test/badge.svg
|
||||
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3Atest
|
||||
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
|
||||
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
|
||||
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
|
||||
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
|
||||
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
|
||||
[david-url]: https://david-dm.org/ant-design/ant-design
|
||||
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/antd
|
||||
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
|
||||
[lgtm-url]: https://lgtm.com/projects/g/ant-design/ant-design/alerts/
|
||||
[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield
|
||||
[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield
|
||||
[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open
|
||||
[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22
|
||||
[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design&style=social
|
||||
[twitter-url]: https://twitter.com/AntDesignUI
|
||||
[gitter-english-image]: https://img.shields.io/gitter/room/ant-design/ant-design-english.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D
|
||||
[gitter-english-url]: https://gitter.im/ant-design/ant-design-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
|
||||
[gitter-chinese-image]: https://img.shields.io/gitter/room/ant-design/ant-design.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D
|
||||
[gitter-chinese-url]: https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
[semver-stability-url]: https://dependabot.com/compatibility-score.html/?dependency-name=antd&package-manager=npm_and_yarn&new-version=latest
|
||||
[semver-stability-image]: https://api.dependabot.com/badges/compatibility_score?dependency-name=antd&package-manager=npm_and_yarn&target-version=latest&version-scheme=semver
|
||||
|
||||
</div>
|
||||
|
||||
[](http://ant.design)
|
||||
[](https://ant.design)
|
||||
|
||||
[English](./README.md) | Português | [简体中文](./README-zh_CN.md)
|
||||
|
||||
@@ -70,21 +99,20 @@ Importe o estilo manualmente:
|
||||
import 'antd/dist/antd.css'; // ou 'antd/dist/antd.less'
|
||||
```
|
||||
|
||||
Ou use [babel-plugin-import](https://ant.design/docs/react/getting-started#Import-on-Demand).
|
||||
|
||||
### TypeScript
|
||||
|
||||
Veja [Uso no Typescript](https://ant.design/docs/react/use-in-typescript).
|
||||
|
||||
## 🌍 Internacionalização
|
||||
|
||||
Veja [i18n](http://ant.design/docs/react/i18n).
|
||||
Veja [i18n](https://ant.design/docs/react/i18n).
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
- [Página inicial](http://ant.design/)
|
||||
- [Componentes](http://ant.design/docs/react/introduce)
|
||||
- [Página inicial](https://ant.design/)
|
||||
- [Componentes](https://ant.design/components/overview)
|
||||
- [Ant Design Pro](http://pro.ant.design/)
|
||||
- [Ant Design Charts](https://charts.ant.design)
|
||||
- [Change Log](CHANGELOG.en-US.md)
|
||||
- [rc-components](http://react-component.github.io/)
|
||||
- [Mobile UI](http://mobile.ant.design)
|
||||
@@ -101,7 +129,7 @@ Veja [i18n](http://ant.design/docs/react/i18n).
|
||||
- [FAQ](https://ant.design/docs/react/faq)
|
||||
- [CodeSandbox Template](https://u.ant.design/codesandbox-repro) para relatório de erros
|
||||
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
|
||||
- [Customize Theme](http://ant.design/docs/react/customize-theme)
|
||||
- [Customize Theme](https://ant.design/docs/react/customize-theme)
|
||||
- [How to Apply for Being A Collaborator](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator)
|
||||
|
||||
## ⌨️ Desenvolvimento
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<a href="http://ant.design">
|
||||
<a href="https://ant.design">
|
||||
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
</a>
|
||||
</p>
|
||||
@@ -10,15 +10,44 @@
|
||||
|
||||
一套企业级 UI 设计语言和 React 组件库。
|
||||
|
||||
[](https://circleci.com/gh/ant-design/ant-design)  [](https://codecov.io/gh/ant-design/ant-design/branch/master) [](https://www.npmjs.com/package/antd) [](http://npmjs.com/antd)
|
||||
[![CircleCI status][circleci-image]][circleci-url] [![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
|
||||
|
||||
[](https://david-dm.org/ant-design/ant-design) [](https://david-dm.org/ant-design/ant-design?type=dev) [](https://lgtm.com/projects/g/ant-design/ant-design/alerts/) [](https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield) [](https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![FOSSA Status][fossa-image]][fossa-url] [![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
|
||||
[](https://twitter.com/AntDesignUI) [](https://gitter.im/ant-design/ant-design-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![Gitter][gitter-english-image]][gitter-english-url] [![Gitter][gitter-chinese-image]][gitter-chinese-url] [![[SemVer stability]][semver-stability-image]][semver-stability-url]
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/antd
|
||||
[circleci-image]: https://img.shields.io/travis/com/ant-design/ant-design.svg?style=flat-square
|
||||
[circleci-url]: https://travis-ci.com/ant-design/ant-design
|
||||
[github-action-image]: https://github.com/ant-design/ant-design/workflows/test/badge.svg
|
||||
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3Atest
|
||||
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
|
||||
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
|
||||
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
|
||||
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
|
||||
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
|
||||
[david-url]: https://david-dm.org/ant-design/ant-design
|
||||
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/antd
|
||||
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
|
||||
[lgtm-url]: https://lgtm.com/projects/g/ant-design/ant-design/alerts/
|
||||
[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield
|
||||
[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield
|
||||
[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open
|
||||
[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22
|
||||
[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design&style=social
|
||||
[twitter-url]: https://twitter.com/AntDesignUI
|
||||
[gitter-english-image]: https://img.shields.io/gitter/room/ant-design/ant-design-english.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D
|
||||
[gitter-english-url]: https://gitter.im/ant-design/ant-design-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
|
||||
[gitter-chinese-image]: https://img.shields.io/gitter/room/ant-design/ant-design.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D
|
||||
[gitter-chinese-url]: https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
[semver-stability-url]: https://dependabot.com/compatibility-score.html/?dependency-name=antd&package-manager=npm_and_yarn&new-version=latest
|
||||
[semver-stability-image]: https://api.dependabot.com/badges/compatibility_score?dependency-name=antd&package-manager=npm_and_yarn&target-version=latest&version-scheme=semver
|
||||
|
||||
</div>
|
||||
|
||||
[](http://ant.design/index-cn)
|
||||
[](https://ant.design/index-cn)
|
||||
|
||||
[English](./README.md) | [Português](./README-pt_BR.md) | 简体中文
|
||||
|
||||
@@ -31,7 +60,7 @@
|
||||
- 🌍 数十个国际化语言支持。
|
||||
- 🎨 深入每个细节的主题定制能力。
|
||||
|
||||
## 🖥 支持环境
|
||||
## 🖥 兼容环境
|
||||
|
||||
- 现代浏览器和 IE11(需要 [polyfills](https://ant.design/docs/react/getting-started-cn#兼容性))。
|
||||
- 支持服务端渲染。
|
||||
@@ -70,8 +99,6 @@ const App = () => (
|
||||
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
```
|
||||
|
||||
你也可以使用 [babel-plugin-import](https://ant.design/docs/react/getting-started-cn#按需加载)。
|
||||
|
||||
### 🌈 定制主题
|
||||
|
||||
参考 [定制主题](https://ant.design/docs/react/customize-theme-cn) 文档。
|
||||
@@ -82,13 +109,14 @@ import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
|
||||
## 🌍 国际化
|
||||
|
||||
参考 [国际化文档](http://ant.design/docs/react/i18n-cn)。
|
||||
参考 [国际化文档](https://ant.design/docs/react/i18n-cn)。
|
||||
|
||||
## 🔗 链接
|
||||
|
||||
- [首页](http://ant.design/)
|
||||
- [组件库](http://ant.design/docs/react/introduce)
|
||||
- [首页](https://ant.design/)
|
||||
- [组件库](https://ant.design/components/overview-cn)
|
||||
- [Ant Design Pro](http://pro.ant.design/)
|
||||
- [Ant Design Charts](https://charts.ant.design)
|
||||
- [更新日志](CHANGELOG.en-US.md)
|
||||
- [React 底层基础组件](http://react-component.github.io/)
|
||||
- [移动端组件](http://mobile.ant.design)
|
||||
@@ -106,7 +134,7 @@ import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
- [常见问题](https://ant.design/docs/react/faq-cn)
|
||||
- [CodeSandbox 模板](https://u.ant.design/codesandbox-repro) for bug reports
|
||||
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
|
||||
- [定制主题](http://ant.design/docs/react/customize-theme-cn)
|
||||
- [定制主题](https://ant.design/docs/react/customize-theme-cn)
|
||||
- [成为社区协作成员](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator)
|
||||
|
||||
## ⌨️ 本地开发
|
||||
|
||||
21
README.md
21
README.md
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<a href="http://ant.design">
|
||||
<a href="https://ant.design">
|
||||
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
</a>
|
||||
</p>
|
||||
@@ -47,7 +47,7 @@ An enterprise-class UI design language and React UI library.
|
||||
|
||||
</div>
|
||||
|
||||
[](http://ant.design)
|
||||
[](https://ant.design)
|
||||
|
||||
English | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md)
|
||||
|
||||
@@ -62,7 +62,7 @@ English | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md)
|
||||
|
||||
## 🖥 Environment Support
|
||||
|
||||
- Modern browsers and Internet Explorer 11 (with [polyfills](https://ant.design/docs/react/getting-started#Compatibility))
|
||||
- Modern browsers and Internet Explorer 11 (with [polyfills](https://stackoverflow.com/questions/57020976/polyfills-in-2019-for-ie11))
|
||||
- Server-side Rendering
|
||||
- [Electron](https://www.electronjs.org/)
|
||||
|
||||
@@ -88,7 +88,7 @@ import { Button, DatePicker } from 'antd';
|
||||
const App = () => (
|
||||
<>
|
||||
<Button type="primary">PRESS ME</Button>
|
||||
<DatePicker />
|
||||
<DatePicker placeholder="select date" />
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -99,21 +99,20 @@ And import style manually:
|
||||
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
```
|
||||
|
||||
Or use [babel-plugin-import](https://ant.design/docs/react/getting-started#Import-on-Demand).
|
||||
|
||||
### TypeScript
|
||||
|
||||
See [Use in TypeScript](https://ant.design/docs/react/use-in-typescript).
|
||||
`antd` is written in TypeScript with complete definitions, check [Use in TypeScript](https://ant.design/docs/react/use-in-typescript) to getting started.
|
||||
|
||||
## 🌍 Internationalization
|
||||
|
||||
See [i18n](http://ant.design/docs/react/i18n).
|
||||
Dozens of languages supported in `antd`, see [i18n](https://ant.design/docs/react/i18n).
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
- [Home page](http://ant.design/)
|
||||
- [Components](https://ant.design/components/button/)
|
||||
- [Home page](https://ant.design/)
|
||||
- [Components](https://ant.design/components/overview)
|
||||
- [Ant Design Pro](http://pro.ant.design/)
|
||||
- [Ant Design Charts](https://charts.ant.design)
|
||||
- [Change Log](CHANGELOG.en-US.md)
|
||||
- [rc-components](http://react-component.github.io/)
|
||||
- [Mobile UI](http://mobile.ant.design)
|
||||
@@ -130,7 +129,7 @@ See [i18n](http://ant.design/docs/react/i18n).
|
||||
- [FAQ](https://ant.design/docs/react/faq)
|
||||
- [CodeSandbox Template](https://u.ant.design/codesandbox-repro) for bug reports
|
||||
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
|
||||
- [Customize Theme](http://ant.design/docs/react/customize-theme)
|
||||
- [Customize Theme](https://ant.design/docs/react/customize-theme)
|
||||
- [How to Apply for Being A Collaborator](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator)
|
||||
|
||||
## ⌨️ Development
|
||||
|
||||
@@ -12,50 +12,106 @@ pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
|
||||
stages:
|
||||
- stage: site
|
||||
jobs:
|
||||
- job: Build_Site
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.13.1'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js "[](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
- script: npm run site
|
||||
displayName: 'Build sites'
|
||||
- script: ls -al _site/
|
||||
displayName: 'List build'
|
||||
- script: |
|
||||
export DEPLOY_DOMAIN=https://preview-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
|
||||
echo "Deploy to $DEPLOY_DOMAIN"
|
||||
npx surge --project ./_site --domain $DEPLOY_DOMAIN
|
||||
displayName: 'Deploy Site'
|
||||
- script: |
|
||||
export DEPLOY_DOMAIN=https://preview-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
|
||||
node ./scripts/azure-github-comment.js "[<img width="306" src="https://user-images.githubusercontent.com/5378891/72400743-23dbb200-3785-11ea-9d13-1a2d92743846.png">]($DEPLOY_DOMAIN)"
|
||||
displayName: 'Update comment on github'
|
||||
- job: Build_Site_Failed
|
||||
dependsOn: Build_Site
|
||||
condition: failed()
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.13.1'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js "[<img width="534" src="https://user-images.githubusercontent.com/5378891/75333447-1e63a280-58c1-11ea-975d-235367fd1522.png">](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
- stage: site
|
||||
jobs:
|
||||
- job: Build_Site
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.13.1'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js "[](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
- script: npm run site
|
||||
displayName: 'Build sites'
|
||||
- script: ls -al _site/
|
||||
displayName: 'List build'
|
||||
- script: |
|
||||
export DEPLOY_DOMAIN=https://preview-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
|
||||
echo "Deploy to $DEPLOY_DOMAIN"
|
||||
npx surge --project ./_site --domain $DEPLOY_DOMAIN
|
||||
displayName: 'Deploy Site'
|
||||
- script: |
|
||||
export DEPLOY_DOMAIN=https://preview-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
|
||||
node ./scripts/azure-github-comment.js "[<img width="306" src="https://user-images.githubusercontent.com/5378891/72400743-23dbb200-3785-11ea-9d13-1a2d92743846.png">]($DEPLOY_DOMAIN)"
|
||||
displayName: 'Update comment on github'
|
||||
- job: Build_Site_Failed
|
||||
dependsOn: Build_Site
|
||||
condition: failed()
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.13.1'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js "[<img width="534" src="https://user-images.githubusercontent.com/5378891/75333447-1e63a280-58c1-11ea-975d-235367fd1522.png">](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
- stage: ui
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- job: UI_Test
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.16.3'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js -ui "[](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
- script: npm run test-image
|
||||
displayName: 'UI Test'
|
||||
- task: PublishPipelineArtifact@1
|
||||
inputs:
|
||||
targetPath: $(System.DefaultWorkingDirectory)/jest-stare
|
||||
artifactName: jestStare
|
||||
condition: failed()
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js -ui "[<img width="306" src="https://user-images.githubusercontent.com/14831261/82744259-6e5ee200-9da8-11ea-8479-685f6e280b77.jpg">](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Update comment on github'
|
||||
- job: UI_Test_Failed
|
||||
dependsOn: UI_Test
|
||||
condition: failed()
|
||||
steps:
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '12.13.1'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
artifact: jestStare
|
||||
path: './jest-stare'
|
||||
- script: ls -al ./jest-stare
|
||||
displayName: 'List report'
|
||||
- script: |
|
||||
export DEPLOY_DOMAIN=https://ui-test-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
|
||||
echo "Deploy to $DEPLOY_DOMAIN"
|
||||
npx surge --project ./jest-stare --domain $DEPLOY_DOMAIN
|
||||
displayName: 'Deploy Report Site'
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js -ui "[<img width="306" src="https://user-images.githubusercontent.com/14831261/82744257-6dc64b80-9da8-11ea-80cf-05b2279a5602.jpg">](https://ui-test-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh)"
|
||||
displayName: 'Update comment on github'
|
||||
|
||||
@@ -1,11 +1,57 @@
|
||||
/**
|
||||
* @jest-environment node
|
||||
*/
|
||||
import getScroll from '../getScroll';
|
||||
|
||||
describe('getScroll', () => {
|
||||
it('getScroll return 0 in node envioronment', async () => {
|
||||
it('getScroll target null', async () => {
|
||||
expect(getScroll(null, true)).toBe(0);
|
||||
expect(getScroll(null, false)).toBe(0);
|
||||
});
|
||||
|
||||
it('getScroll window', async () => {
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
window.pageXOffset = x;
|
||||
window.pageYOffset = y;
|
||||
});
|
||||
window.scrollTo(200, 400);
|
||||
expect(getScroll(window, true)).toBe(400);
|
||||
expect(getScroll(window, false)).toBe(200);
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('getScroll document', async () => {
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
document.documentElement.scrollLeft = x;
|
||||
document.documentElement.scrollTop = y;
|
||||
});
|
||||
window.scrollTo(200, 400);
|
||||
expect(getScroll(document, true)).toBe(400);
|
||||
expect(getScroll(document, false)).toBe(200);
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('getScroll div', async () => {
|
||||
const div = document.createElement('div');
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
div.scrollLeft = x;
|
||||
div.scrollTop = y;
|
||||
});
|
||||
window.scrollTo(200, 400);
|
||||
expect(getScroll(div, true)).toBe(400);
|
||||
expect(getScroll(div, false)).toBe(200);
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('getScroll documentElement', async () => {
|
||||
const div = {};
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
div.scrollLeft = null;
|
||||
div.scrollTop = null;
|
||||
div.documentElement = {};
|
||||
div.documentElement.scrollLeft = x;
|
||||
div.documentElement.scrollTop = y;
|
||||
});
|
||||
window.scrollTo(200, 400);
|
||||
expect(getScroll(div, true)).toBe(400);
|
||||
expect(getScroll(div, false)).toBe(200);
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
11
components/_util/__tests__/getScrollNode.test.ts
Normal file
11
components/_util/__tests__/getScrollNode.test.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* @jest-environment node
|
||||
*/
|
||||
import getScroll from '../getScroll';
|
||||
|
||||
describe('getScroll node', () => {
|
||||
it('getScroll return 0 in node environment', async () => {
|
||||
expect(getScroll(null, true)).toBe(0);
|
||||
expect(getScroll(null, false)).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -46,4 +46,21 @@ describe('Test ScrollTo function', () => {
|
||||
await sleep(20);
|
||||
expect(div.scrollTop).toBe(1000);
|
||||
});
|
||||
|
||||
it('test getContainer document - option', async () => {
|
||||
scrollTo(1000, {
|
||||
getContainer: () => document,
|
||||
});
|
||||
await sleep(20);
|
||||
expect(document.documentElement.scrollTop).toBe(1000);
|
||||
});
|
||||
|
||||
it('test duration - option', async () => {
|
||||
scrollTo(1000, {
|
||||
duration: 1100,
|
||||
getContainer: () => document,
|
||||
});
|
||||
await sleep(20);
|
||||
expect(document.documentElement.scrollTop).toBe(1000);
|
||||
});
|
||||
});
|
||||
|
||||
12
components/_util/__tests__/transButton.test.js
Normal file
12
components/_util/__tests__/transButton.test.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import TransButton from '../transButton';
|
||||
|
||||
describe('transButton component', () => {
|
||||
it('disabled should update style', () => {
|
||||
const wrapper = mount(<TransButton disabled />);
|
||||
expect(wrapper.find('div').first().props().style).toEqual(
|
||||
expect.objectContaining({ pointerEvents: 'none' }),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -18,24 +18,42 @@ describe('Wave component', () => {
|
||||
it('isHidden works', () => {
|
||||
const TEST_NODE_ENV = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'development';
|
||||
const wrapper = mount(<Wave><button type="button">button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button">button</button>
|
||||
</Wave>,
|
||||
);
|
||||
expect(wrapper.find('button').getDOMNode().className).toBe('');
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
expect(wrapper.find('button').getDOMNode().hasAttribute('ant-click-animating-without-extra-node')).toBe(false);
|
||||
expect(
|
||||
wrapper.find('button').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe(false);
|
||||
wrapper.unmount();
|
||||
process.env.NODE_ENV = TEST_NODE_ENV;
|
||||
});
|
||||
|
||||
it('isHidden is mocked', () => {
|
||||
const wrapper = mount(<Wave><button type="button">button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button">button</button>
|
||||
</Wave>,
|
||||
);
|
||||
expect(wrapper.find('button').getDOMNode().className).toBe('');
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
expect(wrapper.find('button').getDOMNode().getAttribute('ant-click-animating-without-extra-node')).toBe('false');
|
||||
expect(
|
||||
wrapper.find('button').getDOMNode().getAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe('false');
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it('wave color is grey', async () => {
|
||||
const wrapper = mount(<Wave><button type="button" style={{ borderColor: 'rgb(0, 0, 0)' }}>button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" style={{ borderColor: 'rgb(0, 0, 0)' }}>
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -44,7 +62,13 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('wave color is not grey', async () => {
|
||||
const wrapper = mount(<Wave><button type="button" style={{ borderColor: 'red' }}>button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" style={{ borderColor: 'red' }}>
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
await sleep(200);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -54,7 +78,11 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('read wave color from border-top-color', async () => {
|
||||
const wrapper = mount(<Wave><div style={{ borderTopColor: 'blue' }}>button</div></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<div style={{ borderTopColor: 'blue' }}>button</div>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('div').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -64,7 +92,11 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('read wave color from background color', async () => {
|
||||
const wrapper = mount(<Wave><div style={{ backgroundColor: 'green' }}>button</div></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<div style={{ backgroundColor: 'green' }}>button</div>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('div').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -74,7 +106,11 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('read wave color from border firstly', async () => {
|
||||
const wrapper = mount(<Wave><div style={{ borderColor: 'yellow', backgroundColor: 'green' }}>button</div></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<div style={{ borderColor: 'yellow', backgroundColor: 'green' }}>button</div>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('div').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -84,7 +120,13 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('hidden element with -leave className', async () => {
|
||||
const wrapper = mount(<Wave><button type="button" className="xx-leave">button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" className="xx-leave">
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@@ -95,7 +137,9 @@ describe('Wave component', () => {
|
||||
it('ConfigProvider csp', async () => {
|
||||
const wrapper = mount(
|
||||
<ConfigProvider csp={{ nonce: 'YourNonceCode' }}>
|
||||
<Wave><button type="button">button</button></Wave>
|
||||
<Wave>
|
||||
<button type="button">button</button>
|
||||
</Wave>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
|
||||
7
components/_util/devWarning.ts
Normal file
7
components/_util/devWarning.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import devWarning, { resetWarned } from 'rc-util/lib/warning';
|
||||
|
||||
export { resetWarned };
|
||||
|
||||
export default (valid: boolean, component: string, message: string): void => {
|
||||
devWarning(valid, `[antd: ${component}] ${message}`);
|
||||
};
|
||||
@@ -1,8 +1,17 @@
|
||||
import * as React from 'react';
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function cloneElement(element: React.ReactNode, ...restArgs: any[]) {
|
||||
if (!React.isValidElement(element)) return element;
|
||||
export const isValidElement = React.isValidElement;
|
||||
|
||||
return React.cloneElement(element, ...restArgs);
|
||||
export function replaceElement(
|
||||
element: React.ReactNode,
|
||||
replacement: React.ReactNode,
|
||||
props: any,
|
||||
): React.ReactNode {
|
||||
if (!isValidElement(element)) return replacement;
|
||||
|
||||
return React.cloneElement(element, typeof props === 'function' ? props() : props);
|
||||
}
|
||||
|
||||
export function cloneElement(element: React.ReactNode, props?: any): React.ReactElement {
|
||||
return replaceElement(element, element, props) as React.ReactElement;
|
||||
}
|
||||
|
||||
@@ -26,15 +26,10 @@ const responsiveObserve = {
|
||||
matchHandlers: {},
|
||||
dispatch(pointMap: ScreenMap) {
|
||||
screens = pointMap;
|
||||
if (subscribers.length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
subscribers.forEach(item => {
|
||||
item.func(screens);
|
||||
});
|
||||
|
||||
return true;
|
||||
return subscribers.length >= 1;
|
||||
},
|
||||
subscribe(func: SubscribeFunc) {
|
||||
if (subscribers.length === 0) {
|
||||
|
||||
@@ -24,8 +24,8 @@ export default function scrollTo(y: number, options: ScrollToOptions = {}) {
|
||||
const nextScrollTop = easeInOutCubic(time > duration ? duration : time, scrollTop, y, duration);
|
||||
if (isWindow(container)) {
|
||||
(container as Window).scrollTo(window.pageXOffset, nextScrollTop);
|
||||
} else if (container instanceof Document) {
|
||||
container.documentElement.scrollTop = nextScrollTop;
|
||||
} else if (container instanceof HTMLDocument || container.constructor.name === 'HTMLDocument') {
|
||||
(container as HTMLDocument).documentElement.scrollTop = nextScrollTop;
|
||||
} else {
|
||||
(container as HTMLElement).scrollTop = nextScrollTop;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ interface TransButtonProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
onClick?: (e?: React.MouseEvent<HTMLDivElement>) => void;
|
||||
noStyle?: boolean;
|
||||
autoFocus?: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const inlineStyle: React.CSSProperties = {
|
||||
@@ -63,7 +64,24 @@ class TransButton extends React.Component<TransButtonProps> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { style, noStyle, ...restProps } = this.props;
|
||||
const { style, noStyle, disabled, ...restProps } = this.props;
|
||||
|
||||
let mergedStyle: React.CSSProperties = {};
|
||||
|
||||
if (!noStyle) {
|
||||
mergedStyle = {
|
||||
...inlineStyle,
|
||||
};
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
mergedStyle.pointerEvents = 'none';
|
||||
}
|
||||
|
||||
mergedStyle = {
|
||||
...mergedStyle,
|
||||
...style,
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -73,7 +91,7 @@ class TransButton extends React.Component<TransButtonProps> {
|
||||
{...restProps}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={this.onKeyUp}
|
||||
style={{ ...(!noStyle ? inlineStyle : null), ...style }}
|
||||
style={mergedStyle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import warning, { resetWarned } from 'rc-util/lib/warning';
|
||||
|
||||
export { resetWarned };
|
||||
|
||||
export default (valid: boolean, component: string, message: string): void => {
|
||||
warning(valid, `[antd: ${component}] ${message}`);
|
||||
};
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import TransitionEvents from '@ant-design/css-animation/lib/Event';
|
||||
import raf from './raf';
|
||||
import { ConfigConsumer, ConfigConsumerProps, CSPConfig } from '../config-provider';
|
||||
import { ConfigConsumer, ConfigConsumerProps, CSPConfig, ConfigContext } from '../config-provider';
|
||||
|
||||
let styleForPesudo: HTMLStyleElement | null;
|
||||
|
||||
@@ -24,6 +24,8 @@ function isNotGrey(color: string) {
|
||||
}
|
||||
|
||||
export default class Wave extends React.Component<{ insertExtraNode?: boolean }> {
|
||||
static contextType = ConfigContext;
|
||||
|
||||
private instance?: {
|
||||
cancel: () => void;
|
||||
};
|
||||
@@ -40,6 +42,8 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
|
||||
private csp?: CSPConfig;
|
||||
|
||||
context: ConfigConsumerProps;
|
||||
|
||||
componentDidMount() {
|
||||
const node = findDOMNode(this) as HTMLElement;
|
||||
if (!node || node.nodeType !== 1) {
|
||||
@@ -66,7 +70,8 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
const { insertExtraNode } = this.props;
|
||||
this.extraNode = document.createElement('div');
|
||||
const { extraNode } = this;
|
||||
extraNode.className = 'ant-click-animating-node';
|
||||
const { getPrefixCls } = this.context;
|
||||
extraNode.className = `${getPrefixCls('')}-click-animating-node`;
|
||||
const attributeName = this.getAttributeName();
|
||||
node.setAttribute(attributeName, 'true');
|
||||
// Not white or transparnt or grey
|
||||
@@ -86,7 +91,9 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
|
||||
extraNode.style.borderColor = waveColor;
|
||||
styleForPesudo.innerHTML = `
|
||||
[ant-click-animating-without-extra-node='true']::after, .ant-click-animating-node {
|
||||
[${getPrefixCls('')}-click-animating-without-extra-node='true']::after, .${getPrefixCls(
|
||||
'',
|
||||
)}-click-animating-node {
|
||||
--antd-wave-shadow-color: ${waveColor};
|
||||
}`;
|
||||
if (!document.body.contains(styleForPesudo)) {
|
||||
@@ -121,8 +128,11 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
};
|
||||
|
||||
getAttributeName() {
|
||||
const { getPrefixCls } = this.context;
|
||||
const { insertExtraNode } = this.props;
|
||||
return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node';
|
||||
return insertExtraNode
|
||||
? `${getPrefixCls('')}-click-animating`
|
||||
: `${getPrefixCls('')}-click-animating-without-extra-node`;
|
||||
}
|
||||
|
||||
bindAnimationEvent = (node: HTMLElement) => {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
category: Components
|
||||
type: Navigation
|
||||
title: Affix
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/tX6-md4H6/Affix.svg
|
||||
---
|
||||
|
||||
Wrap Affix around another component to make it stick the viewport.
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
subtitle: 固钉
|
||||
type: 导航
|
||||
title: Affix
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/tX6-md4H6/Affix.svg
|
||||
---
|
||||
|
||||
将页面元素钉在可视范围。
|
||||
|
||||
@@ -60,8 +60,7 @@ describe('Alert', () => {
|
||||
|
||||
const testIt = process.env.REACT === '15' ? it.skip : it;
|
||||
testIt('ErrorBoundary', () => {
|
||||
// TODO: Change to @ts-expect-error once typescript is at 3.9
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
// eslint-disable-next-line react/jsx-no-undef
|
||||
const ThrowError = () => <NotExisted />;
|
||||
const wrapper = mount(
|
||||
@@ -74,9 +73,10 @@ describe('Alert', () => {
|
||||
});
|
||||
|
||||
it('could be used with Tooltip', async () => {
|
||||
const ref = React.createRef<any>();
|
||||
jest.useRealTimers();
|
||||
const wrapper = mount(
|
||||
<Tooltip title="xxx" mouseEnterDelay={0}>
|
||||
<Tooltip title="xxx" mouseEnterDelay={0} ref={ref}>
|
||||
<Alert
|
||||
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
||||
type="warning"
|
||||
@@ -85,7 +85,7 @@ describe('Alert', () => {
|
||||
);
|
||||
wrapper.find('.ant-alert').simulate('mouseenter');
|
||||
await sleep(0);
|
||||
expect(wrapper.find<Tooltip>(Tooltip).instance().getPopupDomNode()).toBeTruthy();
|
||||
expect(ref.current.getPopupDomNode()).toBeTruthy();
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
category: Components
|
||||
type: Feedback
|
||||
title: Alert
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/8emPa3fjl/Alert.svg
|
||||
---
|
||||
|
||||
Alert component for feedback.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import CloseOutlined from '@ant-design/icons/CloseOutlined';
|
||||
import CheckCircleOutlined from '@ant-design/icons/CheckCircleOutlined';
|
||||
import ExclamationCircleOutlined from '@ant-design/icons/ExclamationCircleOutlined';
|
||||
@@ -12,9 +11,10 @@ import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
|
||||
import Animate from 'rc-animate';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import getDataOrAriaProps from '../_util/getDataOrAriaProps';
|
||||
import ErrorBoundary from './ErrorBoundary';
|
||||
import { replaceElement } from '../_util/reactNode';
|
||||
|
||||
export interface AlertProps {
|
||||
/**
|
||||
@@ -47,11 +47,6 @@ export interface AlertProps {
|
||||
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
||||
}
|
||||
|
||||
export interface AlertState {
|
||||
closing: boolean;
|
||||
closed: boolean;
|
||||
}
|
||||
|
||||
const iconMapFilled = {
|
||||
success: CheckCircleFilled,
|
||||
info: InfoCircleFilled,
|
||||
@@ -66,86 +61,82 @@ const iconMapOutlined = {
|
||||
warning: ExclamationCircleOutlined,
|
||||
};
|
||||
|
||||
export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
static ErrorBoundary = ErrorBoundary;
|
||||
interface AlertInterface extends React.FC<AlertProps> {
|
||||
ErrorBoundary: typeof ErrorBoundary;
|
||||
}
|
||||
|
||||
state = {
|
||||
closing: false,
|
||||
closed: false,
|
||||
};
|
||||
const Alert: AlertInterface = ({
|
||||
description,
|
||||
prefixCls: customizePrefixCls,
|
||||
message,
|
||||
banner,
|
||||
className = '',
|
||||
style,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
onClick,
|
||||
showIcon,
|
||||
closable,
|
||||
closeText,
|
||||
...props
|
||||
}) => {
|
||||
const [closing, setClosing] = React.useState(false);
|
||||
const [closed, setClosed] = React.useState(false);
|
||||
|
||||
handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const ref = React.useRef<HTMLElement>();
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('alert', customizePrefixCls);
|
||||
|
||||
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
const dom = ReactDOM.findDOMNode(this) as HTMLElement;
|
||||
const dom = ref.current as HTMLElement;
|
||||
dom.style.height = `${dom.offsetHeight}px`;
|
||||
// Magic code
|
||||
// 重复一次后才能正确设置 height
|
||||
dom.style.height = `${dom.offsetHeight}px`;
|
||||
|
||||
this.setState({
|
||||
closing: true,
|
||||
});
|
||||
this.props.onClose?.(e);
|
||||
setClosing(true);
|
||||
props.onClose?.(e);
|
||||
};
|
||||
|
||||
animationEnd = () => {
|
||||
this.setState({
|
||||
closing: false,
|
||||
closed: true,
|
||||
});
|
||||
this.props.afterClose?.();
|
||||
const animationEnd = () => {
|
||||
setClosing(false);
|
||||
setClosed(true);
|
||||
props.afterClose?.();
|
||||
};
|
||||
|
||||
getShowIcon() {
|
||||
const { banner, showIcon } = this.props;
|
||||
// banner 模式默认有 Icon
|
||||
return banner && showIcon === undefined ? true : showIcon;
|
||||
}
|
||||
|
||||
getType() {
|
||||
const { banner, type } = this.props;
|
||||
const getType = () => {
|
||||
const { type } = props;
|
||||
if (type !== undefined) {
|
||||
return type;
|
||||
}
|
||||
// banner 模式默认为警告
|
||||
return banner ? 'warning' : 'info';
|
||||
}
|
||||
};
|
||||
|
||||
getClosable() {
|
||||
const { closable, closeText } = this.props;
|
||||
// closeable when closeText is assigned
|
||||
return closeText ? true : closable;
|
||||
}
|
||||
// closeable when closeText is assigned
|
||||
const isClosable = closeText ? true : closable;
|
||||
const type = getType();
|
||||
|
||||
getIconType() {
|
||||
const { description } = this.props;
|
||||
const renderIconNode = () => {
|
||||
const { icon } = props;
|
||||
// use outline icon in alert with description
|
||||
return (description ? iconMapOutlined : iconMapFilled)[this.getType()] || null;
|
||||
}
|
||||
|
||||
renderIconNode({ prefixCls }: { prefixCls: string }) {
|
||||
const { icon } = this.props;
|
||||
const iconType = this.getIconType();
|
||||
const iconType = (description ? iconMapOutlined : iconMapFilled)[type] || null;
|
||||
if (icon) {
|
||||
return React.isValidElement<{ className?: string }>(icon) ? (
|
||||
React.cloneElement(icon, {
|
||||
className: classNames(`${prefixCls}-icon`, {
|
||||
[icon.props.className as string]: icon.props.className,
|
||||
}),
|
||||
})
|
||||
) : (
|
||||
<span className={`${prefixCls}-icon`}>{icon}</span>
|
||||
);
|
||||
return replaceElement(icon, <span className={`${prefixCls}-icon`}>{icon}</span>, () => ({
|
||||
className: classNames(`${prefixCls}-icon`, {
|
||||
[(icon as any).props.className]: (icon as any).props.className,
|
||||
}),
|
||||
}));
|
||||
}
|
||||
return React.createElement(iconType, { className: `${prefixCls}-icon` });
|
||||
}
|
||||
};
|
||||
|
||||
renderCloseIcon({ prefixCls }: { prefixCls: string }) {
|
||||
const { closeText } = this.props;
|
||||
return this.getClosable() ? (
|
||||
const renderCloseIcon = () => {
|
||||
return isClosable ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={this.handleClose}
|
||||
onClick={handleClose}
|
||||
className={`${prefixCls}-close-icon`}
|
||||
tabIndex={0}
|
||||
>
|
||||
@@ -156,74 +147,53 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
)}
|
||||
</button>
|
||||
) : null;
|
||||
}
|
||||
|
||||
renderAlert = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
description,
|
||||
prefixCls: customizePrefixCls,
|
||||
message,
|
||||
banner,
|
||||
className = '',
|
||||
style,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
onClick,
|
||||
} = this.props;
|
||||
const { closing, closed } = this.state;
|
||||
|
||||
const prefixCls = getPrefixCls('alert', customizePrefixCls);
|
||||
|
||||
const isShowIcon = this.getShowIcon();
|
||||
const type = this.getType();
|
||||
const closable = this.getClosable();
|
||||
|
||||
const alertCls = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-${type}`,
|
||||
{
|
||||
[`${prefixCls}-closing`]: closing,
|
||||
[`${prefixCls}-with-description`]: !!description,
|
||||
[`${prefixCls}-no-icon`]: !isShowIcon,
|
||||
[`${prefixCls}-banner`]: !!banner,
|
||||
[`${prefixCls}-closable`]: closable,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
||||
const closeIcon = this.renderCloseIcon({ prefixCls });
|
||||
|
||||
const dataOrAriaProps = getDataOrAriaProps(this.props);
|
||||
|
||||
const iconNode = this.renderIconNode({ prefixCls });
|
||||
|
||||
return closed ? null : (
|
||||
<Animate
|
||||
component=""
|
||||
showProp="data-show"
|
||||
transitionName={`${prefixCls}-slide-up`}
|
||||
onEnd={this.animationEnd}
|
||||
>
|
||||
<div
|
||||
data-show={!closing}
|
||||
className={alertCls}
|
||||
style={style}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={onClick}
|
||||
{...dataOrAriaProps}
|
||||
>
|
||||
{isShowIcon ? iconNode : null}
|
||||
<span className={`${prefixCls}-message`}>{message}</span>
|
||||
<span className={`${prefixCls}-description`}>{description}</span>
|
||||
{closeIcon}
|
||||
</div>
|
||||
</Animate>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderAlert}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
// banner 模式默认有 Icon
|
||||
const isShowIcon = banner && showIcon === undefined ? true : showIcon;
|
||||
|
||||
const alertCls = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-${type}`,
|
||||
{
|
||||
[`${prefixCls}-closing`]: closing,
|
||||
[`${prefixCls}-with-description`]: !!description,
|
||||
[`${prefixCls}-no-icon`]: !isShowIcon,
|
||||
[`${prefixCls}-banner`]: !!banner,
|
||||
[`${prefixCls}-closable`]: isClosable,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
||||
const dataOrAriaProps = getDataOrAriaProps(props);
|
||||
|
||||
return closed ? null : (
|
||||
<Animate
|
||||
component=""
|
||||
showProp="data-show"
|
||||
transitionName={`${prefixCls}-slide-up`}
|
||||
onEnd={animationEnd}
|
||||
>
|
||||
<div
|
||||
ref={ref}
|
||||
data-show={!closing}
|
||||
className={alertCls}
|
||||
style={style}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={onClick}
|
||||
{...dataOrAriaProps}
|
||||
>
|
||||
{isShowIcon ? renderIconNode() : null}
|
||||
<span className={`${prefixCls}-message`}>{message}</span>
|
||||
<span className={`${prefixCls}-description`}>{description}</span>
|
||||
{renderCloseIcon()}
|
||||
</div>
|
||||
</Animate>
|
||||
);
|
||||
};
|
||||
|
||||
Alert.ErrorBoundary = ErrorBoundary;
|
||||
|
||||
export default Alert;
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
subtitle: 警告提示
|
||||
type: 反馈
|
||||
title: Alert
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/8emPa3fjl/Alert.svg
|
||||
---
|
||||
|
||||
警告提示,展现需要关注的信息。
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
&-close-icon {
|
||||
position: absolute;
|
||||
top: 8px + @font-size-base * @line-height-base / 2 - @font-size-base / 2;
|
||||
right: 16px;
|
||||
right: @padding-md;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
font-size: @font-size-sm;
|
||||
@@ -124,8 +124,8 @@
|
||||
|
||||
&-with-description &-close-icon {
|
||||
position: absolute;
|
||||
top: @padding-xs;
|
||||
right: @padding-xs;
|
||||
top: @padding-md;
|
||||
right: @padding-md;
|
||||
font-size: @font-size-base;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
&-icon {
|
||||
.@{alert-prefix-cls}-rtl & {
|
||||
right: 16px;
|
||||
right: @padding-md;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
@@ -39,14 +39,16 @@
|
||||
&-close-icon {
|
||||
.@{alert-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 16px;
|
||||
left: @padding-md;
|
||||
}
|
||||
}
|
||||
|
||||
&-with-description,
|
||||
&-with-description&-closable {
|
||||
.@{alert-prefix-cls}.@{alert-prefix-cls}-rtl& {
|
||||
padding: 15px 64px 15px 15px;
|
||||
padding: @alert-with-description-padding-vertical @alert-with-description-icon-size * 2 +
|
||||
@alert-with-description-padding-vertical @alert-with-description-no-icon-padding-vertical
|
||||
15px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +60,7 @@
|
||||
|
||||
&-with-description &-icon {
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
right: 24px;
|
||||
right: @alert-with-description-icon-size;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
@@ -66,7 +68,7 @@
|
||||
&-with-description &-close-icon {
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
right: auto;
|
||||
left: 16px;
|
||||
left: @padding-md;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
type: Other
|
||||
cols: 2
|
||||
title: Anchor
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/_1-C1JwsC/Anchor.svg
|
||||
---
|
||||
|
||||
Hyperlinks to scroll on one page.
|
||||
|
||||
@@ -4,6 +4,7 @@ subtitle: 锚点
|
||||
cols: 2
|
||||
type: 其他
|
||||
title: Anchor
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/_1-C1JwsC/Anchor.svg
|
||||
---
|
||||
|
||||
用于跳转到页面指定位置。
|
||||
|
||||
@@ -256,6 +256,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
@@ -341,6 +342,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
@@ -534,6 +536,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
@@ -675,6 +678,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
@@ -817,6 +821,7 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
|
||||
@@ -39,6 +39,7 @@ exports[`AutoComplete legacy dataSource should accept react element option 1`] =
|
||||
style="height:0;width:0;overflow:hidden"
|
||||
>
|
||||
<div
|
||||
aria-label="ReactNode"
|
||||
aria-selected="false"
|
||||
id="undefined_list_0"
|
||||
role="option"
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
type: Data Entry
|
||||
cols: 2
|
||||
title: AutoComplete
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/qtJm4yt45/AutoComplete.svg
|
||||
---
|
||||
|
||||
Autocomplete function of input field.
|
||||
|
||||
@@ -12,7 +12,8 @@ import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import Select, { InternalSelectProps, OptionType } from '../select';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
import devWarning from '../_util/devWarning';
|
||||
import { isValidElement } from '../_util/reactNode';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@@ -25,7 +26,10 @@ export interface DataSourceItemObject {
|
||||
export type DataSourceItemType = string | DataSourceItemObject;
|
||||
|
||||
export interface AutoCompleteProps
|
||||
extends Omit<InternalSelectProps<string>, 'inputIcon' | 'loading' | 'mode' | 'optionLabelProp' | 'labelInValue'> {
|
||||
extends Omit<
|
||||
InternalSelectProps<string>,
|
||||
'inputIcon' | 'loading' | 'mode' | 'optionLabelProp' | 'labelInValue'
|
||||
> {
|
||||
dataSource?: DataSourceItemType[];
|
||||
}
|
||||
|
||||
@@ -46,7 +50,7 @@ const AutoComplete: React.RefForwardingComponent<Select, AutoCompleteProps> = (p
|
||||
|
||||
if (
|
||||
childNodes.length === 1 &&
|
||||
React.isValidElement(childNodes[0]) &&
|
||||
isValidElement(childNodes[0]) &&
|
||||
!isSelectOptionOrSelectOptGroup(childNodes[0])
|
||||
) {
|
||||
customizeInput = childNodes[0];
|
||||
@@ -63,7 +67,7 @@ const AutoComplete: React.RefForwardingComponent<Select, AutoCompleteProps> = (p
|
||||
} else {
|
||||
optionChildren = dataSource
|
||||
? dataSource.map(item => {
|
||||
if (React.isValidElement(item)) {
|
||||
if (isValidElement(item)) {
|
||||
return item;
|
||||
}
|
||||
switch (typeof item) {
|
||||
@@ -90,13 +94,13 @@ const AutoComplete: React.RefForwardingComponent<Select, AutoCompleteProps> = (p
|
||||
|
||||
// ============================ Warning ============================
|
||||
React.useEffect(() => {
|
||||
warning(
|
||||
devWarning(
|
||||
!('dataSource' in props),
|
||||
'AutoComplete',
|
||||
'`dataSource` is deprecated, please use `options` instead.',
|
||||
);
|
||||
|
||||
warning(
|
||||
devWarning(
|
||||
!customizeInput || !('size' in props),
|
||||
'AutoComplete',
|
||||
'You need to control style self instead of setting `size` when using customize input.',
|
||||
|
||||
@@ -4,6 +4,7 @@ subtitle: 自动完成
|
||||
type: 数据录入
|
||||
cols: 2
|
||||
title: AutoComplete
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/qtJm4yt45/AutoComplete.svg
|
||||
---
|
||||
|
||||
输入框自动完成功能。
|
||||
|
||||
@@ -40,19 +40,10 @@ describe('Avatar Render', () => {
|
||||
global.document.body.appendChild(div);
|
||||
|
||||
const wrapper = mount(<Avatar src="http://error.url">Fallback</Avatar>, { attachTo: div });
|
||||
wrapper.instance().setScale = jest.fn(() => {
|
||||
if (wrapper.state().scale === 0.5) {
|
||||
return;
|
||||
}
|
||||
wrapper.instance().setState({ scale: 0.5 });
|
||||
});
|
||||
wrapper.find('img').simulate('error');
|
||||
|
||||
const children = wrapper.find('.ant-avatar-string');
|
||||
expect(children.length).toBe(1);
|
||||
expect(children.text()).toBe('Fallback');
|
||||
expect(wrapper.instance().setScale).toHaveBeenCalled();
|
||||
expect(div.querySelector('.ant-avatar-string').style.transform).toContain('scale(0.5)');
|
||||
|
||||
wrapper.detach();
|
||||
global.document.body.removeChild(div);
|
||||
@@ -136,6 +127,11 @@ describe('Avatar Render', () => {
|
||||
expect(wrapper.state().scale).toBe(0.32);
|
||||
});
|
||||
|
||||
it('should calculate scale of avatar children correctly with gap', () => {
|
||||
const wrapper = mount(<Avatar gap={2}>Avatar</Avatar>);
|
||||
expect(wrapper.state().scale).toBe(0.36);
|
||||
});
|
||||
|
||||
it('should warning when pass a string as icon props', () => {
|
||||
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
mount(<Avatar size={64} icon="aa" />);
|
||||
@@ -146,4 +142,16 @@ describe('Avatar Render', () => {
|
||||
);
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('support size is number', () => {
|
||||
const wrapper = mount(<Avatar size={100}>TestString</Avatar>);
|
||||
expect(wrapper).toMatchRenderedSnapshot();
|
||||
});
|
||||
|
||||
it('support onMouseEnter', () => {
|
||||
const onMouseEnter = jest.fn();
|
||||
const wrapper = mount(<Avatar onMouseEnter={onMouseEnter}>TestString</Avatar>);
|
||||
wrapper.simulate('mouseenter');
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,3 +10,17 @@ exports[`Avatar Render rtl render component should be rendered correctly in RTL
|
||||
/>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Avatar Render support size is number 1`] = `
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
style="width:100px;height:100px;line-height:100px;font-size:18px"
|
||||
>
|
||||
<span
|
||||
class="ant-avatar-string"
|
||||
style="opacity:0"
|
||||
>
|
||||
TestString
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<span
|
||||
class="avatar-item"
|
||||
>
|
||||
@@ -194,7 +194,7 @@ exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
|
||||
</span>
|
||||
</sup>
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span>
|
||||
<span
|
||||
class="ant-badge"
|
||||
@@ -228,12 +228,12 @@ exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
|
||||
data-show="true"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</span>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/avatar/demo/basic.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div>
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-icon"
|
||||
@@ -332,7 +332,7 @@ exports[`renders ./components/avatar/demo/basic.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>,
|
||||
<div>
|
||||
<span
|
||||
class="ant-avatar ant-avatar-square ant-avatar-icon"
|
||||
@@ -431,12 +431,12 @@ exports[`renders ./components/avatar/demo/basic.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/avatar/demo/dynamic.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<span
|
||||
class="ant-avatar ant-avatar-lg ant-avatar-circle"
|
||||
style="background-color:#f56a00;vertical-align:middle"
|
||||
@@ -447,21 +447,30 @@ exports[`renders ./components/avatar/demo/dynamic.md correctly 1`] = `
|
||||
>
|
||||
U
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<button
|
||||
class="ant-btn ant-btn-sm"
|
||||
style="margin:0 16px;vertical-align:middle"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Change
|
||||
ChangeUser
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn ant-btn-sm"
|
||||
style="vertical-align:middle"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
changeGap
|
||||
</span>
|
||||
</button>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
@@ -469,7 +478,7 @@ exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `
|
||||
<span>
|
||||
Toggle Avatar visibility
|
||||
</span>
|
||||
</button>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
@@ -477,7 +486,7 @@ exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `
|
||||
<span>
|
||||
Toggle Avatar size
|
||||
</span>
|
||||
</button>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
@@ -485,9 +494,9 @@ exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `
|
||||
<span>
|
||||
Change Avatar scale
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<br />
|
||||
</button>,
|
||||
<br />,
|
||||
<br />,
|
||||
<div
|
||||
style="text-align:center;transform:scale(1);margin-top:24px"
|
||||
>
|
||||
@@ -533,12 +542,12 @@ exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-icon"
|
||||
>
|
||||
@@ -562,7 +571,7 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
>
|
||||
@@ -572,9 +581,10 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
>
|
||||
U
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
style="width:40px;height:40px;line-height:40px;font-size:18px"
|
||||
>
|
||||
<span
|
||||
class="ant-avatar-string"
|
||||
@@ -582,14 +592,14 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
>
|
||||
USER
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-image"
|
||||
>
|
||||
<img
|
||||
src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
|
||||
/>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
style="color:#f56a00;background-color:#fde3cf"
|
||||
@@ -600,7 +610,7 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
>
|
||||
U
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-icon"
|
||||
style="background-color:#87d068"
|
||||
@@ -625,6 +635,6 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</span>,
|
||||
]
|
||||
`;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Avatar, Badge } from 'antd';
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<span className="avatar-item">
|
||||
<Badge count={1}>
|
||||
<Avatar shape="square" icon={<UserOutlined />} />
|
||||
@@ -29,7 +29,7 @@ ReactDOM.render(
|
||||
<Avatar shape="square" icon={<UserOutlined />} />
|
||||
</Badge>
|
||||
</span>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Avatar } from 'antd';
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<div>
|
||||
<Avatar size={64} icon={<UserOutlined />} />
|
||||
<Avatar size="large" icon={<UserOutlined />} />
|
||||
@@ -31,7 +31,7 @@ ReactDOM.render(
|
||||
<Avatar shape="square" icon={<UserOutlined />} />
|
||||
<Avatar shape="square" size="small" icon={<UserOutlined />} />
|
||||
</div>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
@@ -7,11 +7,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
对于字符型的头像,当字符串较长时,字体大小可以根据头像宽度自动调整。
|
||||
对于字符型的头像,当字符串较长时,字体大小可以根据头像宽度自动调整。也可使用 `gap` 来设置字符距离左右两侧边界单位像素。
|
||||
|
||||
## en-US
|
||||
|
||||
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar.
|
||||
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar. You can also use `gap` to set the unit distance between left and right sides.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
@@ -19,18 +19,24 @@ import { Avatar, Button } from 'antd';
|
||||
|
||||
const UserList = ['U', 'Lucy', 'Tom', 'Edward'];
|
||||
const ColorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
|
||||
const GapList = [4, 3, 2, 1];
|
||||
|
||||
const Autoset: React.FC = () => {
|
||||
const [user, setUser] = useState(UserList[0]);
|
||||
const [color, setColor] = useState(ColorList[0]);
|
||||
const [gap, setGap] = useState(GapList[0]);
|
||||
const changeUser = () => {
|
||||
const index = UserList.indexOf(user);
|
||||
setUser(index < UserList.length - 1 ? UserList[index + 1] : UserList[0]);
|
||||
setColor(index < ColorList.length - 1 ? ColorList[index + 1] : ColorList[0]);
|
||||
};
|
||||
const changeGap = () => {
|
||||
const index = GapList.indexOf(gap);
|
||||
setGap(index < GapList.length - 1 ? GapList[index + 1] : GapList[0]);
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<Avatar style={{ backgroundColor: color, verticalAlign: 'middle' }} size="large">
|
||||
<>
|
||||
<Avatar style={{ backgroundColor: color, verticalAlign: 'middle' }} size="large" gap={gap}>
|
||||
{user}
|
||||
</Avatar>
|
||||
<Button
|
||||
@@ -38,9 +44,12 @@ const Autoset: React.FC = () => {
|
||||
style={{ margin: '0 16px', verticalAlign: 'middle' }}
|
||||
onClick={changeUser}
|
||||
>
|
||||
Change
|
||||
ChangeUser
|
||||
</Button>
|
||||
</div>
|
||||
<Button size="small" style={{ verticalAlign: 'middle' }} onClick={changeGap}>
|
||||
changeGap
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ const App: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<Button onClick={toggle}>Toggle Avatar visibility</Button>
|
||||
<Button onClick={toggleSize}>Toggle Avatar size</Button>
|
||||
<Button onClick={changeScale}>Change Avatar scale</Button>
|
||||
@@ -67,7 +67,7 @@ const App: React.FC = () => {
|
||||
</Avatar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -18,14 +18,14 @@ import { Avatar } from 'antd';
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<Avatar icon={<UserOutlined />} />
|
||||
<Avatar>U</Avatar>
|
||||
<Avatar>USER</Avatar>
|
||||
<Avatar size={40}>USER</Avatar>
|
||||
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
|
||||
<Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>U</Avatar>
|
||||
<Avatar style={{ backgroundColor: '#87d068' }} icon={<UserOutlined />} />
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
category: Components
|
||||
type: Data Display
|
||||
title: Avatar
|
||||
cover: https://gw.alipayobjects.com/zos/antfincdn/aBcnbw68hP/Avatar.svg
|
||||
---
|
||||
|
||||
Avatars can be used to represent people or objects. It supports images, `Icon`s, or letters.
|
||||
@@ -17,3 +18,4 @@ Avatars can be used to represent people or objects. It supports images, `Icon`s,
|
||||
| srcSet | a list of sources to use for different screen resolutions | string | - | |
|
||||
| alt | This attribute defines the alternative text describing the image | string | - | |
|
||||
| onError | handler when img load error, return false to prevent default fallback behavior | () => boolean | - | |
|
||||
| gap | Letter type unit distance between left and right sides | number | 4 | 4.3.0 |
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
import devWarning from '../_util/devWarning';
|
||||
|
||||
export interface AvatarProps {
|
||||
/** Shape of avatar, options:`circle`, `square` */
|
||||
@@ -12,10 +12,12 @@ export interface AvatarProps {
|
||||
* or a custom number size
|
||||
* */
|
||||
size?: 'large' | 'small' | 'default' | number;
|
||||
gap?: number;
|
||||
/** Src of image avatar */
|
||||
src?: string;
|
||||
/** Srcset of image avatar */
|
||||
srcSet?: string;
|
||||
draggable?: boolean;
|
||||
/** icon to be used in avatar */
|
||||
icon?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
@@ -60,10 +62,12 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: AvatarProps) {
|
||||
this.setScale();
|
||||
if (prevProps.src !== this.props.src) {
|
||||
this.setState({ isImgExist: true, scale: 1 });
|
||||
}
|
||||
if (prevProps.children !== this.props.children || prevProps.gap !== this.props.gap) {
|
||||
this.setScale();
|
||||
}
|
||||
}
|
||||
|
||||
setScale = () => {
|
||||
@@ -72,20 +76,22 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
}
|
||||
const childrenWidth = this.avatarChildren.offsetWidth; // offsetWidth avoid affecting be transform scale
|
||||
const nodeWidth = this.avatarNode.offsetWidth;
|
||||
const { gap = 4 } = this.props;
|
||||
// denominator is 0 is no meaning
|
||||
if (
|
||||
childrenWidth === 0 ||
|
||||
nodeWidth === 0 ||
|
||||
(this.lastChildrenWidth === childrenWidth && this.lastNodeWidth === nodeWidth)
|
||||
childrenWidth !== 0 &&
|
||||
nodeWidth !== 0 &&
|
||||
(this.lastChildrenWidth !== childrenWidth || this.lastNodeWidth !== nodeWidth)
|
||||
) {
|
||||
return;
|
||||
this.lastChildrenWidth = childrenWidth;
|
||||
this.lastNodeWidth = nodeWidth;
|
||||
}
|
||||
|
||||
if (gap * 2 < nodeWidth) {
|
||||
this.setState({
|
||||
scale: nodeWidth - gap * 2 < childrenWidth ? (nodeWidth - gap * 2) / childrenWidth : 1,
|
||||
});
|
||||
}
|
||||
this.lastChildrenWidth = childrenWidth;
|
||||
this.lastNodeWidth = nodeWidth;
|
||||
// add 4px gap for each side to get better performance
|
||||
this.setState({
|
||||
scale: nodeWidth - 8 < childrenWidth ? (nodeWidth - 8) / childrenWidth : 1,
|
||||
});
|
||||
};
|
||||
|
||||
handleImgLoadError = () => {
|
||||
@@ -106,10 +112,11 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
icon,
|
||||
className,
|
||||
alt,
|
||||
draggable,
|
||||
...others
|
||||
} = this.props;
|
||||
|
||||
warning(
|
||||
devWarning(
|
||||
!(typeof icon === 'string' && icon.length > 2),
|
||||
'Avatar',
|
||||
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,
|
||||
@@ -142,7 +149,15 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
|
||||
let { children } = this.props;
|
||||
if (src && isImgExist) {
|
||||
children = <img src={src} srcSet={srcSet} onError={this.handleImgLoadError} alt={alt} />;
|
||||
children = (
|
||||
<img
|
||||
src={src}
|
||||
draggable={draggable}
|
||||
srcSet={srcSet}
|
||||
onError={this.handleImgLoadError}
|
||||
alt={alt}
|
||||
/>
|
||||
);
|
||||
} else if (icon) {
|
||||
children = icon;
|
||||
} else {
|
||||
@@ -187,6 +202,12 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// The event is triggered twice from bubbling up the DOM tree.
|
||||
// see https://codesandbox.io/s/kind-snow-9lidz
|
||||
delete others.onError;
|
||||
delete others.gap;
|
||||
|
||||
return (
|
||||
<span
|
||||
{...others}
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
subtitle: 头像
|
||||
type: 数据展示
|
||||
title: Avatar
|
||||
cover: https://gw.alipayobjects.com/zos/antfincdn/aBcnbw68hP/Avatar.svg
|
||||
---
|
||||
|
||||
用来代表用户或事物,支持图片、图标或字符展示。
|
||||
@@ -22,3 +23,4 @@ title: Avatar
|
||||
| srcSet | 设置图片类头像响应式资源地址 | string | - | |
|
||||
| alt | 图像无法显示时的替代文本 | string | - | |
|
||||
| onError | 图片加载失败的事件,返回 false 会关闭组件默认的 fallback 行为 | () => boolean | - | |
|
||||
| gap | 字符类型距离左右两侧边界单位像素 | number | 4 | 4.3.0 |
|
||||
|
||||
@@ -18,9 +18,6 @@ describe('BackTop', () => {
|
||||
});
|
||||
window.scrollTo(0, 400);
|
||||
expect(document.documentElement.scrollTop).toBe(400);
|
||||
// trigger scroll manually
|
||||
wrapper.instance().handleScroll();
|
||||
await sleep();
|
||||
wrapper.find('.ant-back-top').simulate('click');
|
||||
await sleep(500);
|
||||
expect(document.documentElement.scrollTop).toBe(0);
|
||||
@@ -36,34 +33,16 @@ describe('BackTop', () => {
|
||||
});
|
||||
document.dispatchEvent(new Event('scroll'));
|
||||
window.scrollTo(0, 400);
|
||||
// trigger scroll manually
|
||||
wrapper.instance().handleScroll();
|
||||
await sleep();
|
||||
wrapper.find('.ant-back-top').simulate('click');
|
||||
expect(onClick).toHaveBeenCalled();
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('should be able to update target', async () => {
|
||||
const wrapper = mount(<BackTop />);
|
||||
wrapper.instance().handleScroll = jest.fn();
|
||||
const container = document.createElement('div');
|
||||
wrapper.setProps({ target: () => container });
|
||||
expect(wrapper.instance().handleScroll).toHaveBeenLastCalledWith({
|
||||
target: container,
|
||||
});
|
||||
container.dispatchEvent(new Event('scroll'));
|
||||
expect(wrapper.instance().handleScroll).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
currentTarget: container,
|
||||
target: container,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('invalid target', async () => {
|
||||
const onClick = jest.fn();
|
||||
const wrapper = mount(<BackTop onClick={onClick} target={() => ({ documentElement: {} })} />);
|
||||
const wrapper = mount(
|
||||
<BackTop onClick={onClick} visible target={() => ({ documentElement: {} })} />,
|
||||
);
|
||||
wrapper.find('.ant-back-top').simulate('click');
|
||||
expect(onClick).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
category: Components
|
||||
type: Other
|
||||
title: BackTop
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/tJZ5jbTwX/BackTop.svg
|
||||
---
|
||||
|
||||
`BackTop` makes it easy to go back to the top of the page.
|
||||
|
||||
174
components/back-top/index.tsx
Executable file → Normal file
174
components/back-top/index.tsx
Executable file → Normal file
@@ -3,8 +3,9 @@ import Animate from 'rc-animate';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationFrame';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import VerticalAlignTopOutlined from '@ant-design/icons/VerticalAlignTopOutlined';
|
||||
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import getScroll from '../_util/getScroll';
|
||||
import scrollTo from '../_util/scrollTo';
|
||||
|
||||
@@ -13,130 +14,111 @@ export interface BackTopProps {
|
||||
onClick?: React.MouseEventHandler<HTMLElement>;
|
||||
target?: () => HTMLElement | Window | Document;
|
||||
prefixCls?: string;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
visible?: boolean; // Only for test. Don't use it.
|
||||
}
|
||||
|
||||
export default class BackTop extends React.Component<BackTopProps, any> {
|
||||
static defaultProps = {
|
||||
visibilityHeight: 400,
|
||||
const BackTop: React.FC<BackTopProps> = props => {
|
||||
const [visible, setVisible] = React.useState(false);
|
||||
|
||||
const ref = React.createRef<HTMLDivElement>();
|
||||
const scrollEvent = React.useRef<any>();
|
||||
|
||||
const getDefaultTarget = () => {
|
||||
return ref.current && ref.current.ownerDocument ? ref.current.ownerDocument : window;
|
||||
};
|
||||
|
||||
state = {
|
||||
visible: false,
|
||||
};
|
||||
const handleScroll = throttleByAnimationFrame(
|
||||
(e: React.UIEvent<HTMLElement> | { target: any }) => {
|
||||
const { visibilityHeight } = props;
|
||||
const scrollTop = getScroll(e.target, true);
|
||||
setVisible(scrollTop > visibilityHeight!);
|
||||
},
|
||||
);
|
||||
|
||||
scrollEvent: any;
|
||||
|
||||
node: HTMLDivElement;
|
||||
|
||||
componentDidMount() {
|
||||
this.bindScrollEvent();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: BackTopProps) {
|
||||
const { target } = this.props;
|
||||
if (prevProps.target !== target) {
|
||||
this.bindScrollEvent();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.scrollEvent) {
|
||||
this.scrollEvent.remove();
|
||||
}
|
||||
(this.handleScroll as any).cancel();
|
||||
}
|
||||
|
||||
bindScrollEvent() {
|
||||
if (this.scrollEvent) {
|
||||
this.scrollEvent.remove();
|
||||
}
|
||||
const { target } = this.props;
|
||||
const getTarget = target || this.getDefaultTarget;
|
||||
const bindScrollEvent = () => {
|
||||
const { target } = props;
|
||||
const getTarget = target || getDefaultTarget;
|
||||
const container = getTarget();
|
||||
this.scrollEvent = addEventListener(container, 'scroll', (e: React.UIEvent<HTMLElement>) => {
|
||||
this.handleScroll(e);
|
||||
scrollEvent.current = addEventListener(container, 'scroll', (e: React.UIEvent<HTMLElement>) => {
|
||||
handleScroll(e);
|
||||
});
|
||||
this.handleScroll({
|
||||
handleScroll({
|
||||
target: container,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
getVisible() {
|
||||
if ('visible' in this.props) {
|
||||
return this.props.visible;
|
||||
React.useEffect(() => {
|
||||
bindScrollEvent();
|
||||
return () => {
|
||||
if (scrollEvent.current) {
|
||||
scrollEvent.current.remove();
|
||||
}
|
||||
(handleScroll as any).cancel();
|
||||
};
|
||||
}, [props.target]);
|
||||
|
||||
const getVisible = () => {
|
||||
if ('visible' in props) {
|
||||
return props.visible;
|
||||
}
|
||||
return this.state.visible;
|
||||
}
|
||||
|
||||
getDefaultTarget = () => {
|
||||
return this.node && this.node.ownerDocument ? this.node.ownerDocument : window;
|
||||
return visible;
|
||||
};
|
||||
|
||||
saveDivRef = (node: HTMLDivElement) => {
|
||||
this.node = node;
|
||||
};
|
||||
|
||||
scrollToTop = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const { onClick, target } = this.props;
|
||||
const scrollToTop = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const { onClick, target } = props;
|
||||
scrollTo(0, {
|
||||
getContainer: target || this.getDefaultTarget,
|
||||
getContainer: target || getDefaultTarget,
|
||||
});
|
||||
if (typeof onClick === 'function') {
|
||||
onClick(e);
|
||||
}
|
||||
};
|
||||
|
||||
@throttleByAnimationFrameDecorator()
|
||||
handleScroll(e: React.UIEvent<HTMLElement> | { target: any }) {
|
||||
const { visibilityHeight = 0 } = this.props;
|
||||
const scrollTop = getScroll(e.target, true);
|
||||
this.setState({
|
||||
visible: scrollTop > visibilityHeight,
|
||||
});
|
||||
}
|
||||
|
||||
renderChildren({ prefixCls }: { prefixCls: string }) {
|
||||
const { children } = this.props;
|
||||
const renderChildren = ({ prefixCls }: { prefixCls: string }) => {
|
||||
const { children } = props;
|
||||
const defaultElement = (
|
||||
<div className={`${prefixCls}-content`}>
|
||||
<div className={`${prefixCls}-icon`} />
|
||||
<div className={`${prefixCls}-icon`}>
|
||||
<VerticalAlignTopOutlined />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<Animate component="" transitionName="fade">
|
||||
{this.getVisible() ? <div>{children || defaultElement}</div> : null}
|
||||
{getVisible() ? <div>{children || defaultElement}</div> : null}
|
||||
</Animate>
|
||||
);
|
||||
}
|
||||
|
||||
renderBackTop = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, className = '' } = this.props;
|
||||
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
|
||||
const classString = classNames(prefixCls, className, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
// fix https://fb.me/react-unknown-prop
|
||||
const divProps = omit(this.props, [
|
||||
'prefixCls',
|
||||
'className',
|
||||
'children',
|
||||
'visibilityHeight',
|
||||
'target',
|
||||
'visible',
|
||||
]);
|
||||
|
||||
return (
|
||||
<div {...divProps} className={classString} onClick={this.scrollToTop} ref={this.saveDivRef}>
|
||||
{this.renderChildren({ prefixCls })}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderBackTop}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const { prefixCls: customizePrefixCls, className = '' } = props;
|
||||
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
|
||||
const classString = classNames(prefixCls, className, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
// fix https://fb.me/react-unknown-prop
|
||||
const divProps = omit(props, [
|
||||
'prefixCls',
|
||||
'className',
|
||||
'children',
|
||||
'visibilityHeight',
|
||||
'target',
|
||||
'visible',
|
||||
]);
|
||||
|
||||
return (
|
||||
<div {...divProps} className={classString} onClick={scrollToTop} ref={ref}>
|
||||
{renderChildren({ prefixCls })}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
BackTop.defaultProps = {
|
||||
visibilityHeight: 400,
|
||||
};
|
||||
|
||||
export default React.memo(BackTop);
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
type: 其他
|
||||
subtitle: 回到顶部
|
||||
title: BackTop
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/tJZ5jbTwX/BackTop.svg
|
||||
---
|
||||
|
||||
返回页面顶部的操作按钮。
|
||||
|
||||
@@ -37,11 +37,8 @@
|
||||
}
|
||||
|
||||
&-icon {
|
||||
width: 14px;
|
||||
height: 16px;
|
||||
margin: 12px auto;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAoCAYAAACWwljjAAAABGdBTUEAALGPC/xhBQAAAbtJREFUWAntmMtKw0AUhhMvS5cuxILgQlRUpIggIoKIIoigG1eC+AA+jo+i6FIXBfeuXIgoeKVeitVWJX5HWhhDksnUpp3FDPyZk3Nm5nycmZKkXhAEOXSA3lG7muTeRzmfy6HneUvIhnYkQK+Q9NhAA0Opg0vBEhjBKHiyb8iGMyQMOYuK41BcBSypAL+MYXSKjtFAW7EAGEO3qN4uMQbbAkXiSfRQJ1H6a+yhlkKRcAoVFYiweYNjtCVQJJpBz2GCiPt7fBOZQpFgDpUikse5HgnkM4Fi4QX0Fpc5wf9EbLqpUCy4jMoJSXWhFwbMNgWKhVbRhy5jirhs9fy/oFhgHVVTJEs7RLZ8sSEoJm6iz7SZDMbJ+/OKERQTttCXQRLToRUmrKWCYuA2+jbN0MB4OQobYShfdTCgn/sL1K36M7TLrN3n+758aPy2rrpR6+/od5E8tf/A1uLS9aId5T7J3CNYihkQ4D9PiMdMC7mp4rjB9kjFjZp8BlnVHJBuO1yFXIV0FdDF3RlyFdJVQBdv5AxVdIsq8apiZ2PyYO1EVykesGfZEESsCkweyR8MUW+V8uJ1gkYipmpdP1pm2aJVPEGzAAAAAElFTkSuQmCC)
|
||||
~'100%/100%' no-repeat;
|
||||
font-size: 24px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import omit from 'omit.js';
|
||||
import classNames from 'classnames';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
|
||||
function getNumberArray(num: string | number | undefined | null) {
|
||||
return num
|
||||
@@ -50,15 +50,27 @@ export interface ScrollNumberState {
|
||||
count?: string | number | null;
|
||||
}
|
||||
|
||||
const ScrollNumber: React.FC<ScrollNumberProps> = props => {
|
||||
const ScrollNumber: React.FC<ScrollNumberProps> = ({
|
||||
prefixCls: customizePrefixCls,
|
||||
count: customizeCount,
|
||||
className,
|
||||
style,
|
||||
title,
|
||||
component = 'sup',
|
||||
displayComponent,
|
||||
onAnimated = () => {},
|
||||
...restProps
|
||||
}) => {
|
||||
const [animateStarted, setAnimateStarted] = React.useState(true);
|
||||
const [count, setCount] = React.useState(props.count);
|
||||
const [prevCount, setPrevCount] = React.useState(props.count);
|
||||
const [lastCount, setLastCount] = React.useState(props.count);
|
||||
const [count, setCount] = React.useState(customizeCount);
|
||||
const [prevCount, setPrevCount] = React.useState(customizeCount);
|
||||
const [lastCount, setLastCount] = React.useState(customizeCount);
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('scroll-number', customizePrefixCls);
|
||||
|
||||
if (prevCount !== props.count) {
|
||||
if (prevCount !== customizeCount) {
|
||||
setAnimateStarted(true);
|
||||
setPrevCount(props.count);
|
||||
setPrevCount(customizeCount);
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
@@ -69,10 +81,8 @@ const ScrollNumber: React.FC<ScrollNumberProps> = props => {
|
||||
// performing the transition.
|
||||
timeout = setTimeout(() => {
|
||||
setAnimateStarted(false);
|
||||
setCount(props.count);
|
||||
if (props.onAnimated) {
|
||||
props.onAnimated();
|
||||
}
|
||||
setCount(customizeCount);
|
||||
onAnimated();
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
@@ -80,7 +90,7 @@ const ScrollNumber: React.FC<ScrollNumberProps> = props => {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
};
|
||||
}, [animateStarted, count, props.count, props.onAnimated]);
|
||||
}, [animateStarted, customizeCount, onAnimated]);
|
||||
|
||||
const getPositionByNum = (num: number, i: number) => {
|
||||
const currentCount = Math.abs(Number(count));
|
||||
@@ -105,7 +115,7 @@ const ScrollNumber: React.FC<ScrollNumberProps> = props => {
|
||||
return num;
|
||||
};
|
||||
|
||||
const renderCurrentNumber = (prefixCls: string, num: number | string, i: number) => {
|
||||
const renderCurrentNumber = (num: number | string, i: number) => {
|
||||
if (typeof num === 'number') {
|
||||
const position = getPositionByNum(num, i);
|
||||
const removeTransition = animateStarted || getNumberArray(lastCount)[i] === undefined;
|
||||
@@ -132,65 +142,40 @@ const ScrollNumber: React.FC<ScrollNumberProps> = props => {
|
||||
);
|
||||
};
|
||||
|
||||
const renderNumberElement = (prefixCls: string) => {
|
||||
const renderNumberElement = () => {
|
||||
if (count && Number(count) % 1 === 0) {
|
||||
return getNumberArray(count)
|
||||
.map((num, i) => renderCurrentNumber(prefixCls, num, i))
|
||||
.map((num, i) => renderCurrentNumber(num, i))
|
||||
.reverse();
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
const renderScrollNumber = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
style,
|
||||
title,
|
||||
component = 'sup',
|
||||
displayComponent,
|
||||
} = props;
|
||||
// fix https://fb.me/react-unknown-prop
|
||||
const restProps = omit(props, [
|
||||
'count',
|
||||
'onAnimated',
|
||||
'component',
|
||||
'prefixCls',
|
||||
'displayComponent',
|
||||
]);
|
||||
const prefixCls = getPrefixCls('scroll-number', customizePrefixCls);
|
||||
const newProps = {
|
||||
...restProps,
|
||||
className: classNames(prefixCls, className),
|
||||
title: title as string,
|
||||
};
|
||||
|
||||
// allow specify the border
|
||||
// mock border-color by box-shadow for compatible with old usage:
|
||||
// <Badge count={4} style={{ backgroundColor: '#fff', color: '#999', borderColor: '#d9d9d9' }} />
|
||||
if (style && style.borderColor) {
|
||||
newProps.style = {
|
||||
...style,
|
||||
boxShadow: `0 0 0 1px ${style.borderColor} inset`,
|
||||
};
|
||||
}
|
||||
if (displayComponent) {
|
||||
return React.cloneElement(displayComponent, {
|
||||
className: classNames(
|
||||
`${prefixCls}-custom-component`,
|
||||
displayComponent.props && displayComponent.props.className,
|
||||
),
|
||||
});
|
||||
}
|
||||
return React.createElement(component as any, newProps, renderNumberElement(prefixCls));
|
||||
const newProps = {
|
||||
...restProps,
|
||||
style,
|
||||
className: classNames(prefixCls, className),
|
||||
title: title as string,
|
||||
};
|
||||
|
||||
return <ConfigConsumer>{renderScrollNumber}</ConfigConsumer>;
|
||||
};
|
||||
|
||||
ScrollNumber.defaultProps = {
|
||||
count: null,
|
||||
onAnimated() {},
|
||||
// allow specify the border
|
||||
// mock border-color by box-shadow for compatible with old usage:
|
||||
// <Badge count={4} style={{ backgroundColor: '#fff', color: '#999', borderColor: '#d9d9d9' }} />
|
||||
if (style && style.borderColor) {
|
||||
newProps.style = {
|
||||
...style,
|
||||
boxShadow: `0 0 0 1px ${style.borderColor} inset`,
|
||||
};
|
||||
}
|
||||
if (displayComponent) {
|
||||
return cloneElement(displayComponent, {
|
||||
className: classNames(
|
||||
`${prefixCls}-custom-component`,
|
||||
displayComponent.props && displayComponent.props.className,
|
||||
),
|
||||
});
|
||||
}
|
||||
return React.createElement(component as any, newProps, renderNumberElement());
|
||||
};
|
||||
|
||||
export default ScrollNumber;
|
||||
|
||||
@@ -469,11 +469,13 @@ exports[`renders ./components/badge/demo/change.md correctly 1`] = `
|
||||
</span>
|
||||
<button
|
||||
aria-checked="true"
|
||||
checked=""
|
||||
class="ant-switch ant-switch-checked"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-switch-handle"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
@@ -483,12 +485,17 @@ exports[`renders ./components/badge/demo/change.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/badge/demo/colorful.md correctly 1`] = `
|
||||
<div>
|
||||
<h4
|
||||
style="margin-bottom:16px"
|
||||
Array [
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left"
|
||||
role="separator"
|
||||
>
|
||||
Presets:
|
||||
</h4>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Presets
|
||||
</span>
|
||||
</div>,
|
||||
<div>
|
||||
<div>
|
||||
<span
|
||||
@@ -672,12 +679,17 @@ exports[`renders ./components/badge/demo/colorful.md correctly 1`] = `
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<h4
|
||||
style="margin:16px 0"
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left"
|
||||
role="separator"
|
||||
>
|
||||
Custom:
|
||||
</h4>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Custom
|
||||
</span>
|
||||
</div>,
|
||||
<div>
|
||||
<span
|
||||
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
|
||||
@@ -734,8 +746,8 @@ exports[`renders ./components/badge/demo/colorful.md correctly 1`] = `
|
||||
#108ee9
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/badge/demo/dot.md correctly 1`] = `
|
||||
@@ -1485,6 +1497,179 @@ exports[`renders ./components/badge/demo/no-wrapper.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/badge/demo/offset.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-badge"
|
||||
>
|
||||
<a
|
||||
class="head-example"
|
||||
href="#"
|
||||
/>
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true"
|
||||
style="right:-10px;margin-top:10px"
|
||||
title="5"
|
||||
>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%)"
|
||||
>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
9
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit current"
|
||||
>
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
9
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
9
|
||||
</p>
|
||||
</span>
|
||||
</sup>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/badge/demo/overflow.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
|
||||
@@ -17,9 +17,6 @@ exports[`Badge badge should support float number 1`] = `
|
||||
exports[`Badge badge should support float number 2`] = `
|
||||
<Badge
|
||||
count="3.5"
|
||||
dot={false}
|
||||
overflowCount={99}
|
||||
showZero={false}
|
||||
>
|
||||
<span
|
||||
className="ant-badge ant-badge-not-a-wrapper"
|
||||
@@ -51,7 +48,6 @@ exports[`Badge badge should support float number 2`] = `
|
||||
count="3.5"
|
||||
data-show={true}
|
||||
key="scrollNumber"
|
||||
onAnimated={[Function]}
|
||||
prefixCls="ant-scroll-number"
|
||||
title="3.5"
|
||||
>
|
||||
@@ -766,6 +762,181 @@ exports[`Badge rtl render component should be rendered correctly in RTL directio
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Badge rtl render component should be rendered correctly in RTL direction 2`] = `
|
||||
<span
|
||||
class="ant-badge ant-badge-rtl"
|
||||
>
|
||||
<a
|
||||
class="head-example"
|
||||
href="#"
|
||||
>
|
||||
head
|
||||
</a>
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true"
|
||||
style="left:10px;margin-top:10px"
|
||||
title="5"
|
||||
>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%)"
|
||||
>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
9
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit current"
|
||||
>
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
9
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
0
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
1
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
2
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
3
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
4
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
5
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
6
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
7
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
8
|
||||
</p>
|
||||
<p
|
||||
class="ant-scroll-number-only-unit"
|
||||
>
|
||||
9
|
||||
</p>
|
||||
</span>
|
||||
</sup>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Badge should be compatible with borderColor style 1`] = `
|
||||
<span
|
||||
class="ant-badge ant-badge-not-a-wrapper"
|
||||
@@ -938,9 +1109,6 @@ exports[`Badge should be compatible with borderColor style 1`] = `
|
||||
exports[`Badge should render when count is changed 1`] = `
|
||||
<Badge
|
||||
count={10}
|
||||
dot={false}
|
||||
overflowCount={99}
|
||||
showZero={false}
|
||||
>
|
||||
<span
|
||||
className="ant-badge ant-badge-not-a-wrapper"
|
||||
@@ -972,7 +1140,6 @@ exports[`Badge should render when count is changed 1`] = `
|
||||
count={10}
|
||||
data-show={true}
|
||||
key="scrollNumber"
|
||||
onAnimated={[Function]}
|
||||
prefixCls="ant-scroll-number"
|
||||
title={10}
|
||||
>
|
||||
@@ -1185,9 +1352,6 @@ exports[`Badge should render when count is changed 1`] = `
|
||||
exports[`Badge should render when count is changed 2`] = `
|
||||
<Badge
|
||||
count={11}
|
||||
dot={false}
|
||||
overflowCount={99}
|
||||
showZero={false}
|
||||
>
|
||||
<span
|
||||
className="ant-badge ant-badge-not-a-wrapper"
|
||||
@@ -1219,7 +1383,6 @@ exports[`Badge should render when count is changed 2`] = `
|
||||
count={11}
|
||||
data-show={true}
|
||||
key="scrollNumber"
|
||||
onAnimated={[Function]}
|
||||
prefixCls="ant-scroll-number"
|
||||
title={11}
|
||||
>
|
||||
@@ -1625,9 +1788,6 @@ exports[`Badge should render when count is changed 2`] = `
|
||||
exports[`Badge should render when count is changed 3`] = `
|
||||
<Badge
|
||||
count={11}
|
||||
dot={false}
|
||||
overflowCount={99}
|
||||
showZero={false}
|
||||
>
|
||||
<span
|
||||
className="ant-badge ant-badge-not-a-wrapper"
|
||||
@@ -1659,7 +1819,6 @@ exports[`Badge should render when count is changed 3`] = `
|
||||
count={11}
|
||||
data-show={true}
|
||||
key="scrollNumber"
|
||||
onAnimated={[Function]}
|
||||
prefixCls="ant-scroll-number"
|
||||
title={11}
|
||||
>
|
||||
@@ -2064,10 +2223,7 @@ exports[`Badge should render when count is changed 3`] = `
|
||||
|
||||
exports[`Badge should render when count is changed 4`] = `
|
||||
<Badge
|
||||
count={10}
|
||||
dot={false}
|
||||
overflowCount={99}
|
||||
showZero={false}
|
||||
count={111}
|
||||
>
|
||||
<span
|
||||
className="ant-badge ant-badge-not-a-wrapper"
|
||||
@@ -2096,17 +2252,16 @@ exports[`Badge should render when count is changed 4`] = `
|
||||
>
|
||||
<ScrollNumber
|
||||
className="ant-badge-count ant-badge-multiple-words"
|
||||
count={10}
|
||||
count="99+"
|
||||
data-show={true}
|
||||
key="scrollNumber"
|
||||
onAnimated={[Function]}
|
||||
prefixCls="ant-scroll-number"
|
||||
title={10}
|
||||
title={111}
|
||||
>
|
||||
<sup
|
||||
className="ant-scroll-number ant-badge-count ant-badge-multiple-words"
|
||||
data-show={true}
|
||||
title={10}
|
||||
title={111}
|
||||
>
|
||||
<span
|
||||
className="ant-scroll-number-only"
|
||||
@@ -2503,11 +2658,59 @@ exports[`Badge should render when count is changed 4`] = `
|
||||
`;
|
||||
|
||||
exports[`Badge should render when count is changed 5`] = `
|
||||
<Badge
|
||||
count={10}
|
||||
>
|
||||
<span
|
||||
className="ant-badge ant-badge-not-a-wrapper"
|
||||
>
|
||||
<Animate
|
||||
animation={Object {}}
|
||||
component=""
|
||||
componentProps={Object {}}
|
||||
onAppear={[Function]}
|
||||
onEnd={[Function]}
|
||||
onEnter={[Function]}
|
||||
onLeave={[Function]}
|
||||
showProp="data-show"
|
||||
transitionAppear={true}
|
||||
transitionEnter={true}
|
||||
transitionLeave={true}
|
||||
transitionName=""
|
||||
>
|
||||
<AnimateChild
|
||||
animation={Object {}}
|
||||
key="scrollNumber"
|
||||
transitionAppear={true}
|
||||
transitionEnter={true}
|
||||
transitionLeave={true}
|
||||
transitionName=""
|
||||
>
|
||||
<ScrollNumber
|
||||
className="ant-badge-count ant-badge-multiple-words"
|
||||
count={10}
|
||||
data-show={true}
|
||||
key="scrollNumber"
|
||||
prefixCls="ant-scroll-number"
|
||||
title={10}
|
||||
>
|
||||
<sup
|
||||
className="ant-scroll-number ant-badge-count ant-badge-multiple-words"
|
||||
data-show={true}
|
||||
title={10}
|
||||
>
|
||||
99+
|
||||
</sup>
|
||||
</ScrollNumber>
|
||||
</AnimateChild>
|
||||
</Animate>
|
||||
</span>
|
||||
</Badge>
|
||||
`;
|
||||
|
||||
exports[`Badge should render when count is changed 6`] = `
|
||||
<Badge
|
||||
count={9}
|
||||
dot={false}
|
||||
overflowCount={99}
|
||||
showZero={false}
|
||||
>
|
||||
<span
|
||||
className="ant-badge ant-badge-not-a-wrapper"
|
||||
@@ -2539,7 +2742,6 @@ exports[`Badge should render when count is changed 5`] = `
|
||||
count={9}
|
||||
data-show={true}
|
||||
key="scrollNumber"
|
||||
onAnimated={[Function]}
|
||||
prefixCls="ant-scroll-number"
|
||||
title={9}
|
||||
>
|
||||
|
||||
@@ -8,6 +8,13 @@ import rtlTest from '../../../tests/shared/rtlTest';
|
||||
describe('Badge', () => {
|
||||
mountTest(Badge);
|
||||
rtlTest(Badge);
|
||||
rtlTest(() => (
|
||||
<Badge count={5} offset={[10, 10]}>
|
||||
<a href="#" className="head-example">
|
||||
head
|
||||
</a>
|
||||
</Badge>
|
||||
));
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
@@ -38,23 +45,21 @@ describe('Badge', () => {
|
||||
it('should have an overriden title attribute', () => {
|
||||
const badge = mount(<Badge count={10} title="Custom title" />);
|
||||
expect(
|
||||
badge
|
||||
.find('.ant-scroll-number')
|
||||
.getDOMNode()
|
||||
.attributes.getNamedItem('title').value,
|
||||
badge.find('.ant-scroll-number').getDOMNode().attributes.getNamedItem('title').value,
|
||||
).toEqual('Custom title');
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/10626
|
||||
it('should be composable with Tooltip', () => {
|
||||
const ref = React.createRef();
|
||||
const wrapper = mount(
|
||||
<Tooltip title="Fix the error">
|
||||
<Tooltip title="Fix the error" ref={ref}>
|
||||
<Badge status="error" />
|
||||
</Tooltip>,
|
||||
);
|
||||
wrapper.find('Badge').simulate('mouseenter');
|
||||
jest.runAllTimers();
|
||||
expect(wrapper.instance().tooltip.props.visible).toBe(true);
|
||||
expect(ref.current.props.visible).toBe(true);
|
||||
});
|
||||
|
||||
it('should render when count is changed', () => {
|
||||
@@ -68,6 +73,9 @@ describe('Badge', () => {
|
||||
wrapper.setProps({ count: 11 });
|
||||
jest.runAllTimers();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
wrapper.setProps({ count: 111 });
|
||||
jest.runAllTimers();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
wrapper.setProps({ count: 10 });
|
||||
jest.runAllTimers();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
@@ -14,7 +14,7 @@ title:
|
||||
We preset a series of colorful Badge styles for use in different situations. You can also set it to a hex color string for custom color.
|
||||
|
||||
```jsx
|
||||
import { Badge } from 'antd';
|
||||
import { Badge, Divider } from 'antd';
|
||||
|
||||
const colors = [
|
||||
'pink',
|
||||
@@ -33,8 +33,8 @@ const colors = [
|
||||
];
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<h4 style={{ marginBottom: 16 }}>Presets:</h4>
|
||||
<>
|
||||
<Divider orientation="left">Presets</Divider>
|
||||
<div>
|
||||
{colors.map(color => (
|
||||
<div key={color}>
|
||||
@@ -42,7 +42,7 @@ ReactDOM.render(
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<h4 style={{ margin: '16px 0' }}>Custom:</h4>
|
||||
<Divider orientation="left">Custom</Divider>
|
||||
<div>
|
||||
<Badge color="#f50" text="#f50" />
|
||||
<br />
|
||||
@@ -52,7 +52,7 @@ ReactDOM.render(
|
||||
<br />
|
||||
<Badge color="#108ee9" text="#108ee9" />
|
||||
</div>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
27
components/badge/demo/offset.md
Normal file
27
components/badge/demo/offset.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
order: 5
|
||||
title:
|
||||
zh-CN: 自定义位置偏移
|
||||
en-US: Offset
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
设置状态点的位置偏移,格式为 `[left, top]`,表示状态点距默认位置左侧、上方的偏移量。
|
||||
|
||||
## en-US
|
||||
|
||||
Set offset of the badge dot, the format is `[left, top]`, which represents the offset of the status dot from the left and top of the default position.
|
||||
|
||||
```jsx
|
||||
import { Badge } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<>
|
||||
<Badge count={5} offset={[10, 10]}>
|
||||
<a href="#" className="head-example" />
|
||||
</Badge>
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
@@ -2,6 +2,7 @@
|
||||
category: Components
|
||||
type: Data Display
|
||||
title: Badge
|
||||
cover: https://gw.alipayobjects.com/zos/antfincdn/6%26GF9WHwvY/Badge.svg
|
||||
---
|
||||
|
||||
Small numerical value or status descriptor for UI elements.
|
||||
@@ -12,22 +13,12 @@ Badge normally appears in proximity to notifications or user avatars with eye-ca
|
||||
|
||||
## API
|
||||
|
||||
```jsx
|
||||
<Badge count={5}>
|
||||
<a href="#" className="head-example" />
|
||||
</Badge>
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Badge count={5} />
|
||||
```
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| color | Customize Badge dot color | string | - | |
|
||||
| count | Number to show in badge | ReactNode | | |
|
||||
| dot | Whether to display a red dot instead of `count` | boolean | `false` | |
|
||||
| offset | set offset of the badge dot, like`[x, y]` | `[number, number]` | - | |
|
||||
| offset | set offset of the badge dot | `[number, number]` | - | |
|
||||
| overflowCount | Max count to show | number | 99 | |
|
||||
| showZero | Whether to show badge when `count` is zero | boolean | `false` | |
|
||||
| status | Set Badge as a status dot | `success` \| `processing` \| `default` \| `error` \| `warning` | `''` | |
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import * as React from 'react';
|
||||
import Animate from 'rc-animate';
|
||||
import omit from 'omit.js';
|
||||
import classNames from 'classnames';
|
||||
import ScrollNumber from './ScrollNumber';
|
||||
import { PresetColorTypes, PresetColorType, PresetStatusColorType } from '../_util/colors';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import { LiteralUnion } from '../_util/type';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
|
||||
export { ScrollNumberProps } from './ScrollNumber';
|
||||
|
||||
@@ -32,16 +32,33 @@ function isPresetColor(color?: string): boolean {
|
||||
return (PresetColorTypes as any[]).indexOf(color) !== -1;
|
||||
}
|
||||
|
||||
const Badge: React.FC<BadgeProps> = props => {
|
||||
const Badge: React.FC<BadgeProps> = ({
|
||||
prefixCls: customizePrefixCls,
|
||||
scrollNumberPrefixCls: customizeScrollNumberPrefixCls,
|
||||
children,
|
||||
status,
|
||||
text,
|
||||
color,
|
||||
count = null,
|
||||
overflowCount = 99,
|
||||
dot = false,
|
||||
title,
|
||||
offset,
|
||||
style,
|
||||
className,
|
||||
showZero = false,
|
||||
...restProps
|
||||
}) => {
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('badge', customizePrefixCls);
|
||||
|
||||
const getNumberedDisplayCount = () => {
|
||||
const { count, overflowCount } = props;
|
||||
const displayCount =
|
||||
(count as number) > (overflowCount as number) ? `${overflowCount}+` : count;
|
||||
return displayCount as string | number | null;
|
||||
};
|
||||
|
||||
const hasStatus = (): boolean => {
|
||||
const { status, color } = props;
|
||||
return !!status || !!color;
|
||||
};
|
||||
|
||||
@@ -51,7 +68,6 @@ const Badge: React.FC<BadgeProps> = props => {
|
||||
};
|
||||
|
||||
const isDot = () => {
|
||||
const { dot } = props;
|
||||
return (dot && !isZero()) || hasStatus();
|
||||
};
|
||||
|
||||
@@ -64,7 +80,6 @@ const Badge: React.FC<BadgeProps> = props => {
|
||||
};
|
||||
|
||||
const getScrollNumberTitle = () => {
|
||||
const { title, count } = props;
|
||||
if (title) {
|
||||
return title;
|
||||
}
|
||||
@@ -72,7 +87,15 @@ const Badge: React.FC<BadgeProps> = props => {
|
||||
};
|
||||
|
||||
const getStyleWithOffset = () => {
|
||||
const { offset, style } = props;
|
||||
if (direction === 'rtl') {
|
||||
return offset
|
||||
? {
|
||||
left: parseInt(offset[0] as string, 10),
|
||||
marginTop: offset[1],
|
||||
...style,
|
||||
}
|
||||
: style;
|
||||
}
|
||||
return offset
|
||||
? {
|
||||
right: -parseInt(offset[0] as string, 10),
|
||||
@@ -82,35 +105,23 @@ const Badge: React.FC<BadgeProps> = props => {
|
||||
: style;
|
||||
};
|
||||
|
||||
const getBadgeClassName = (prefixCls: string, direction: string = 'ltr') => {
|
||||
const { className, children } = props;
|
||||
return classNames(className, prefixCls, {
|
||||
[`${prefixCls}-status`]: hasStatus(),
|
||||
[`${prefixCls}-not-a-wrapper`]: !children,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
}) as string;
|
||||
};
|
||||
|
||||
const isHidden = () => {
|
||||
const { showZero } = props;
|
||||
const displayCount = getDisplayCount();
|
||||
const isEmpty = displayCount === null || displayCount === undefined || displayCount === '';
|
||||
return (isEmpty || (isZero() && !showZero)) && !isDot();
|
||||
};
|
||||
|
||||
const renderStatusText = (prefixCls: string) => {
|
||||
const { text } = props;
|
||||
const renderStatusText = () => {
|
||||
const hidden = isHidden();
|
||||
return hidden || !text ? null : <span className={`${prefixCls}-status-text`}>{text}</span>;
|
||||
};
|
||||
|
||||
const renderDisplayComponent = () => {
|
||||
const { count } = props;
|
||||
const customNode = count as React.ReactElement<any>;
|
||||
if (!customNode || typeof customNode !== 'object') {
|
||||
return undefined;
|
||||
}
|
||||
return React.cloneElement(customNode, {
|
||||
return cloneElement(customNode, {
|
||||
style: {
|
||||
...getStyleWithOffset(),
|
||||
...(customNode.props && customNode.props.style),
|
||||
@@ -118,18 +129,17 @@ const Badge: React.FC<BadgeProps> = props => {
|
||||
});
|
||||
};
|
||||
|
||||
const renderBadgeNumber = (prefixCls: string, scrollNumberPrefixCls: string) => {
|
||||
const { status, count, color } = props;
|
||||
|
||||
const renderBadgeNumber = () => {
|
||||
const scrollNumberPrefixCls = getPrefixCls('scroll-number', customizeScrollNumberPrefixCls);
|
||||
const displayCount = getDisplayCount();
|
||||
const dot = isDot();
|
||||
const bDot = isDot();
|
||||
const hidden = isHidden();
|
||||
|
||||
const scrollNumberCls = classNames({
|
||||
[`${prefixCls}-dot`]: dot,
|
||||
[`${prefixCls}-count`]: !dot,
|
||||
[`${prefixCls}-dot`]: bDot,
|
||||
[`${prefixCls}-count`]: !bDot,
|
||||
[`${prefixCls}-multiple-words`]:
|
||||
!dot && count && count.toString && count.toString().length > 1,
|
||||
!bDot && count && count.toString && count.toString().length > 1,
|
||||
[`${prefixCls}-status-${status}`]: !!status,
|
||||
[`${prefixCls}-status-${color}`]: isPresetColor(color),
|
||||
});
|
||||
@@ -154,85 +164,50 @@ const Badge: React.FC<BadgeProps> = props => {
|
||||
);
|
||||
};
|
||||
|
||||
const renderBadge = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
scrollNumberPrefixCls: customizeScrollNumberPrefixCls,
|
||||
children,
|
||||
status,
|
||||
text,
|
||||
color,
|
||||
...restProps
|
||||
} = props;
|
||||
const omitArr = [
|
||||
'count',
|
||||
'showZero',
|
||||
'overflowCount',
|
||||
'className',
|
||||
'style',
|
||||
'dot',
|
||||
'offset',
|
||||
'title',
|
||||
];
|
||||
const statusCls = classNames({
|
||||
[`${prefixCls}-status-dot`]: hasStatus(),
|
||||
[`${prefixCls}-status-${status}`]: !!status,
|
||||
[`${prefixCls}-status-${color}`]: isPresetColor(color),
|
||||
});
|
||||
const statusStyle: React.CSSProperties = {};
|
||||
if (color && !isPresetColor(color)) {
|
||||
statusStyle.background = color;
|
||||
}
|
||||
|
||||
const prefixCls = getPrefixCls('badge', customizePrefixCls);
|
||||
const scrollNumberPrefixCls = getPrefixCls('scroll-number', customizeScrollNumberPrefixCls);
|
||||
|
||||
const scrollNumber = renderBadgeNumber(prefixCls, scrollNumberPrefixCls);
|
||||
const statusText = renderStatusText(prefixCls);
|
||||
|
||||
const statusCls = classNames({
|
||||
[`${prefixCls}-status-dot`]: hasStatus(),
|
||||
[`${prefixCls}-status-${status}`]: !!status,
|
||||
[`${prefixCls}-status-${color}`]: isPresetColor(color),
|
||||
});
|
||||
const statusStyle: React.CSSProperties = {};
|
||||
if (color && !isPresetColor(color)) {
|
||||
statusStyle.background = color;
|
||||
}
|
||||
|
||||
// <Badge status="success" />
|
||||
if (!children && hasStatus()) {
|
||||
const styleWithOffset = getStyleWithOffset();
|
||||
const statusTextColor = styleWithOffset && styleWithOffset.color;
|
||||
return (
|
||||
<span
|
||||
{...omit(restProps, omitArr)}
|
||||
className={getBadgeClassName(prefixCls, direction)}
|
||||
style={styleWithOffset}
|
||||
>
|
||||
<span className={statusCls} style={statusStyle} />
|
||||
<span style={{ color: statusTextColor }} className={`${prefixCls}-status-text`}>
|
||||
{text}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
const badgeClassName = classNames(className, prefixCls, {
|
||||
[`${prefixCls}-status`]: hasStatus(),
|
||||
[`${prefixCls}-not-a-wrapper`]: !children,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
// <Badge status="success" />
|
||||
if (!children && hasStatus()) {
|
||||
const styleWithOffset = getStyleWithOffset();
|
||||
const statusTextColor = styleWithOffset && styleWithOffset.color;
|
||||
return (
|
||||
<span {...omit(restProps, omitArr)} className={getBadgeClassName(prefixCls, direction)}>
|
||||
{children}
|
||||
<Animate
|
||||
component=""
|
||||
showProp="data-show"
|
||||
transitionName={children ? `${prefixCls}-zoom` : ''}
|
||||
transitionAppear
|
||||
>
|
||||
{scrollNumber}
|
||||
</Animate>
|
||||
{statusText}
|
||||
<span {...restProps} className={badgeClassName} style={styleWithOffset}>
|
||||
<span className={statusCls} style={statusStyle} />
|
||||
<span style={{ color: statusTextColor }} className={`${prefixCls}-status-text`}>
|
||||
{text}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
return <ConfigConsumer>{renderBadge}</ConfigConsumer>;
|
||||
};
|
||||
|
||||
Badge.defaultProps = {
|
||||
count: null,
|
||||
showZero: false,
|
||||
dot: false,
|
||||
overflowCount: 99,
|
||||
return (
|
||||
<span {...restProps} className={badgeClassName}>
|
||||
{children}
|
||||
<Animate
|
||||
component=""
|
||||
showProp="data-show"
|
||||
transitionName={children ? `${prefixCls}-zoom` : ''}
|
||||
transitionAppear
|
||||
>
|
||||
{renderBadgeNumber()}
|
||||
</Animate>
|
||||
{renderStatusText()}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export default Badge;
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
subtitle: 徽标数
|
||||
type: 数据展示
|
||||
title: Badge
|
||||
cover: https://gw.alipayobjects.com/zos/antfincdn/6%26GF9WHwvY/Badge.svg
|
||||
---
|
||||
|
||||
图标右上角的圆形徽标数字。
|
||||
@@ -13,22 +14,12 @@ title: Badge
|
||||
|
||||
## API
|
||||
|
||||
```jsx
|
||||
<Badge count={5}>
|
||||
<a href="#" className="head-example" />
|
||||
</Badge>
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Badge count={5} />
|
||||
```
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| color | 自定义小圆点的颜色 | string | - | |
|
||||
| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | ReactNode | | |
|
||||
| dot | 不展示数字,只有一个小红点 | boolean | false | |
|
||||
| offset | 设置状态点的位置偏移,格式为 `[x, y]` | `[number, number]` | - | |
|
||||
| offset | 设置状态点的位置偏移 | `[number, number]` | - | |
|
||||
| overflowCount | 展示封顶的数字值 | number | 99 | |
|
||||
| showZero | 当数值为 0 时,是否展示 Badge | boolean | false | |
|
||||
| status | 设置 Badge 为状态点 | `success` \| `processing` \| `default` \| `error` \| `warning` | '' | |
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import toArray from 'rc-util/lib/Children/toArray';
|
||||
import omit from 'omit.js';
|
||||
import BreadcrumbItem from './BreadcrumbItem';
|
||||
import BreadcrumbSeparator from './BreadcrumbSeparator';
|
||||
import Menu from '../menu';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import devWarning from '../_util/devWarning';
|
||||
import { Omit } from '../_util/type';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
|
||||
export interface Route {
|
||||
path: string;
|
||||
@@ -48,41 +48,48 @@ function defaultItemRender(route: Route, params: any, routes: Route[], paths: st
|
||||
return isLastItem ? <span>{name}</span> : <a href={`#/${paths.join('/')}`}>{name}</a>;
|
||||
}
|
||||
|
||||
export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
static Item: typeof BreadcrumbItem;
|
||||
const getPath = (path: string, params: any) => {
|
||||
path = (path || '').replace(/^\//, '');
|
||||
Object.keys(params).forEach(key => {
|
||||
path = path.replace(`:${key}`, params[key]);
|
||||
});
|
||||
return path;
|
||||
};
|
||||
|
||||
static Separator: typeof BreadcrumbSeparator;
|
||||
const addChildPath = (paths: string[], childPath: string = '', params: any) => {
|
||||
const originalPaths = [...paths];
|
||||
const path = getPath(childPath, params);
|
||||
if (path) {
|
||||
originalPaths.push(path);
|
||||
}
|
||||
return originalPaths;
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
separator: '/',
|
||||
};
|
||||
interface BreadcrumbInterface extends React.FC<BreadcrumbProps> {
|
||||
Item: typeof BreadcrumbItem;
|
||||
Separator: typeof BreadcrumbSeparator;
|
||||
}
|
||||
|
||||
getPath = (path: string, params: any) => {
|
||||
path = (path || '').replace(/^\//, '');
|
||||
Object.keys(params).forEach(key => {
|
||||
path = path.replace(`:${key}`, params[key]);
|
||||
});
|
||||
return path;
|
||||
};
|
||||
const Breadcrumb: BreadcrumbInterface = ({
|
||||
prefixCls: customizePrefixCls,
|
||||
separator = '/',
|
||||
style,
|
||||
className,
|
||||
routes,
|
||||
children,
|
||||
itemRender = defaultItemRender,
|
||||
params = {},
|
||||
...restProps
|
||||
}) => {
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
|
||||
addChildPath = (paths: string[], childPath: string = '', params: any) => {
|
||||
const originalPaths = [...paths];
|
||||
const path = this.getPath(childPath, params);
|
||||
if (path) {
|
||||
originalPaths.push(path);
|
||||
}
|
||||
return originalPaths;
|
||||
};
|
||||
|
||||
genForRoutes = ({
|
||||
routes = [],
|
||||
params = {},
|
||||
separator,
|
||||
itemRender = defaultItemRender,
|
||||
}: BreadcrumbProps) => {
|
||||
let crumbs;
|
||||
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
|
||||
if (routes && routes.length > 0) {
|
||||
// generated by route
|
||||
const paths: string[] = [];
|
||||
return routes.map(route => {
|
||||
const path = this.getPath(route.path, params);
|
||||
crumbs = routes.map(route => {
|
||||
const path = getPath(route.path, params);
|
||||
|
||||
if (path) {
|
||||
paths.push(path);
|
||||
@@ -94,7 +101,7 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
<Menu>
|
||||
{route.children.map(child => (
|
||||
<Menu.Item key={child.path || child.breadcrumbName}>
|
||||
{itemRender(child, params, routes, this.addChildPath(paths, child.path, params))}
|
||||
{itemRender(child, params, routes, addChildPath(paths, child.path, params))}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
@@ -107,58 +114,40 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
</BreadcrumbItem>
|
||||
);
|
||||
});
|
||||
};
|
||||
} else if (children) {
|
||||
crumbs = toArray(children).map((element: any, index) => {
|
||||
if (!element) {
|
||||
return element;
|
||||
}
|
||||
|
||||
renderBreadcrumb = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
let crumbs;
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
separator,
|
||||
style,
|
||||
className,
|
||||
routes,
|
||||
children,
|
||||
...restProps
|
||||
} = this.props;
|
||||
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
|
||||
if (routes && routes.length > 0) {
|
||||
// generated by route
|
||||
crumbs = this.genForRoutes(this.props);
|
||||
} else if (children) {
|
||||
crumbs = toArray(children).map((element: any, index) => {
|
||||
if (!element) {
|
||||
return element;
|
||||
}
|
||||
devWarning(
|
||||
element.type &&
|
||||
(element.type.__ANT_BREADCRUMB_ITEM === true ||
|
||||
element.type.__ANT_BREADCRUMB_SEPARATOR === true),
|
||||
'Breadcrumb',
|
||||
"Only accepts Breadcrumb.Item and Breadcrumb.Separator as it's children",
|
||||
);
|
||||
|
||||
warning(
|
||||
element.type &&
|
||||
(element.type.__ANT_BREADCRUMB_ITEM === true ||
|
||||
element.type.__ANT_BREADCRUMB_SEPARATOR === true),
|
||||
'Breadcrumb',
|
||||
"Only accepts Breadcrumb.Item and Breadcrumb.Separator as it's children",
|
||||
);
|
||||
|
||||
return React.cloneElement(element, {
|
||||
separator,
|
||||
key: index, // eslint-disable-line react/no-array-index-key
|
||||
});
|
||||
return cloneElement(element, {
|
||||
separator,
|
||||
key: index,
|
||||
});
|
||||
}
|
||||
const breadcrumbClassName = classNames(className, prefixCls, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
return (
|
||||
<div
|
||||
className={breadcrumbClassName}
|
||||
style={style}
|
||||
{...omit(restProps, ['itemRender', 'linkRender', 'nameRender', 'params'])}
|
||||
>
|
||||
{crumbs}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderBreadcrumb}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
|
||||
const breadcrumbClassName = classNames(className, prefixCls, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={breadcrumbClassName} style={style} {...restProps}>
|
||||
{crumbs}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Breadcrumb.Item = BreadcrumbItem;
|
||||
|
||||
Breadcrumb.Separator = BreadcrumbSeparator;
|
||||
|
||||
export default Breadcrumb;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import DownOutlined from '@ant-design/icons/DownOutlined';
|
||||
import omit from 'omit.js';
|
||||
|
||||
import DropDown, { DropDownProps } from '../dropdown/dropdown';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
|
||||
export interface BreadcrumbItemProps {
|
||||
prefixCls?: string;
|
||||
@@ -13,53 +12,24 @@ export interface BreadcrumbItemProps {
|
||||
dropdownProps?: DropDownProps;
|
||||
onClick?: React.MouseEventHandler<HTMLAnchorElement | HTMLSpanElement>;
|
||||
}
|
||||
|
||||
export default class BreadcrumbItem extends React.Component<BreadcrumbItemProps, any> {
|
||||
static __ANT_BREADCRUMB_ITEM = true;
|
||||
|
||||
static defaultProps = {
|
||||
separator: '/',
|
||||
};
|
||||
|
||||
renderBreadcrumbItem = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, separator, children, ...restProps } = this.props;
|
||||
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
|
||||
let link;
|
||||
if ('href' in this.props) {
|
||||
link = (
|
||||
<a className={`${prefixCls}-link`} {...omit(restProps, ['overlay'])}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
link = (
|
||||
<span className={`${prefixCls}-link`} {...omit(restProps, ['overlay'])}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
// wrap to dropDown
|
||||
link = this.renderBreadcrumbNode(link, prefixCls);
|
||||
if (children) {
|
||||
return (
|
||||
<span>
|
||||
{link}
|
||||
{separator && separator !== '' && (
|
||||
<span className={`${prefixCls}-separator`}>{separator}</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
interface BreadcrumbItemInterface extends React.FC<BreadcrumbItemProps> {
|
||||
__ANT_BREADCRUMB_ITEM: boolean;
|
||||
}
|
||||
const BreadcrumbItem: BreadcrumbItemInterface = ({
|
||||
prefixCls: customizePrefixCls,
|
||||
separator,
|
||||
children,
|
||||
overlay,
|
||||
dropdownProps,
|
||||
...restProps
|
||||
}) => {
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
|
||||
/**
|
||||
* if overlay is have
|
||||
* Wrap a DropDown
|
||||
*/
|
||||
renderBreadcrumbNode = (breadcrumbItem: React.ReactNode, prefixCls: string) => {
|
||||
const { overlay, dropdownProps } = this.props;
|
||||
const renderBreadcrumbNode = (breadcrumbItem: React.ReactNode) => {
|
||||
if (overlay) {
|
||||
return (
|
||||
<DropDown overlay={overlay} placement="bottomCenter" {...dropdownProps}>
|
||||
@@ -73,7 +43,36 @@ export default class BreadcrumbItem extends React.Component<BreadcrumbItemProps,
|
||||
return breadcrumbItem;
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderBreadcrumbItem}</ConfigConsumer>;
|
||||
let link;
|
||||
if ('href' in restProps) {
|
||||
link = (
|
||||
<a className={`${prefixCls}-link`} {...restProps}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
link = (
|
||||
<span className={`${prefixCls}-link`} {...restProps}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// wrap to dropDown
|
||||
link = renderBreadcrumbNode(link);
|
||||
if (children) {
|
||||
return (
|
||||
<span>
|
||||
{link}
|
||||
{separator && separator !== '' && (
|
||||
<span className={`${prefixCls}-separator`}>{separator}</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
BreadcrumbItem.__ANT_BREADCRUMB_ITEM = true;
|
||||
|
||||
export default BreadcrumbItem;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import * as React from 'react';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
|
||||
export default class BreadcrumbSeparator extends React.Component<any> {
|
||||
static __ANT_BREADCRUMB_SEPARATOR = true;
|
||||
|
||||
renderSeparator = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { children } = this.props;
|
||||
const prefixCls = getPrefixCls('breadcrumb');
|
||||
|
||||
return <span className={`${prefixCls}-separator`}>{children || '/'}</span>;
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderSeparator}</ConfigConsumer>;
|
||||
}
|
||||
interface BreadcrumbSeparatorInterface extends React.FC {
|
||||
__ANT_BREADCRUMB_SEPARATOR: boolean;
|
||||
}
|
||||
|
||||
const BreadcrumbSeparator: BreadcrumbSeparatorInterface = ({ children }) => {
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('breadcrumb');
|
||||
|
||||
return <span className={`${prefixCls}-separator`}>{children || '/'}</span>;
|
||||
};
|
||||
|
||||
BreadcrumbSeparator.__ANT_BREADCRUMB_SEPARATOR = true;
|
||||
|
||||
export default BreadcrumbSeparator;
|
||||
|
||||
@@ -111,21 +111,6 @@ describe('Breadcrumb', () => {
|
||||
it('should accept undefined routes', () => {
|
||||
const wrapper = render(<Breadcrumb routes={undefined} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
})
|
||||
|
||||
it('props#linkRender and props#nameRender do not warn anymore', () => {
|
||||
const linkRender = jest.fn();
|
||||
const nameRender = jest.fn();
|
||||
mount(
|
||||
<Breadcrumb linkRender={linkRender} nameRender={nameRender}>
|
||||
<Breadcrumb.Item />
|
||||
<Breadcrumb.Item>xxx</Breadcrumb.Item>
|
||||
</Breadcrumb>,
|
||||
);
|
||||
|
||||
expect(errorSpy.mock.calls.length).toBe(0);
|
||||
expect(linkRender).not.toHaveBeenCalled();
|
||||
expect(nameRender).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should support custom attribute', () => {
|
||||
|
||||
@@ -73,7 +73,6 @@ exports[`react router react router 3 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
separator="/"
|
||||
>
|
||||
<div
|
||||
className="ant-breadcrumb"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
category: Components
|
||||
type: Navigation
|
||||
title: Breadcrumb
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/9Ltop8JwH/Breadcrumb.svg
|
||||
---
|
||||
|
||||
A breadcrumb displays the current location within a hierarchy. It allows going back to states higher up in the hierarchy.
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import Breadcrumb from './Breadcrumb';
|
||||
import BreadcrumbItem from './BreadcrumbItem';
|
||||
import BreadcrumbSeparator from './BreadcrumbSeparator';
|
||||
|
||||
export { BreadcrumbProps } from './Breadcrumb';
|
||||
export { BreadcrumbItemProps } from './BreadcrumbItem';
|
||||
|
||||
Breadcrumb.Item = BreadcrumbItem;
|
||||
Breadcrumb.Separator = BreadcrumbSeparator;
|
||||
export default Breadcrumb;
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
subtitle: 面包屑
|
||||
type: 导航
|
||||
title: Breadcrumb
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/9Ltop8JwH/Breadcrumb.svg
|
||||
---
|
||||
|
||||
显示当前页面在系统层级结构中的位置,并能向上返回。
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
}
|
||||
|
||||
&-link {
|
||||
> .@{iconfont-css-prefix} + span {
|
||||
> .@{iconfont-css-prefix} + span,
|
||||
> .@{iconfont-css-prefix} + a {
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
}
|
||||
|
||||
&-link {
|
||||
> .@{iconfont-css-prefix} + span {
|
||||
> .@{iconfont-css-prefix} + span,
|
||||
> .@{iconfont-css-prefix} + a {
|
||||
.@{breadcrumb-prefix-cls}-rtl & {
|
||||
margin-right: 4px;
|
||||
margin-left: 0;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
@@ -1,40 +1,49 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/button/demo/basic.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Primary
|
||||
Primary Button
|
||||
</span>
|
||||
</button>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Default
|
||||
Default Button
|
||||
</span>
|
||||
</button>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn ant-btn-dashed"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Dashed
|
||||
Dashed Button
|
||||
</span>
|
||||
</button>
|
||||
</button>,
|
||||
<br />,
|
||||
<button
|
||||
class="ant-btn ant-btn-text"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Text Button
|
||||
</span>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn ant-btn-link"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Link
|
||||
Link Button
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</button>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/button/demo/block.md correctly 1`] = `
|
||||
@@ -97,7 +106,15 @@ Array [
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
link
|
||||
Dashed
|
||||
</span>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn ant-btn-text ant-btn-dangerous"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Text
|
||||
</span>
|
||||
</button>,
|
||||
<button
|
||||
@@ -105,7 +122,7 @@ Array [
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
link
|
||||
Link
|
||||
</span>
|
||||
</button>,
|
||||
]
|
||||
@@ -167,6 +184,24 @@ exports[`renders ./components/button/demo/disabled.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-text"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Text
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-text"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Text(disabled)
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-link"
|
||||
type="button"
|
||||
@@ -185,24 +220,6 @@ exports[`renders ./components/button/demo/disabled.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-link ant-btn-dangerous"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Danger Link
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-link ant-btn-dangerous"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Danger Link(disabled)
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-dangerous"
|
||||
type="button"
|
||||
@@ -220,6 +237,42 @@ exports[`renders ./components/button/demo/disabled.md correctly 1`] = `
|
||||
Danger Default(disabled)
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-text ant-btn-dangerous"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Danger Text
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-text ant-btn-dangerous"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Danger Text(disabled)
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-link ant-btn-dangerous"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Danger Link
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-link ant-btn-dangerous"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Danger Link(disabled)
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="site-button-ghost-wrapper"
|
||||
>
|
||||
@@ -269,7 +322,15 @@ exports[`renders ./components/button/demo/ghost.md correctly 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
link
|
||||
Dashed
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-text ant-btn-background-ghost"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Text
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
@@ -277,7 +338,7 @@ exports[`renders ./components/button/demo/ghost.md correctly 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
link
|
||||
Link
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -268,18 +268,6 @@ exports[`Button rtl render component should be rendered correctly in RTL directi
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Button should has click wave effect 1`] = `
|
||||
<button
|
||||
ant-click-animating-without-extra-node="true"
|
||||
class="ant-btn ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
button
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button should merge text if children using variable 1`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
@@ -291,17 +279,6 @@ exports[`Button should merge text if children using variable 1`] = `
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button should not insert space to link button 1`] = `
|
||||
<button
|
||||
class="ant-btn ant-btn-link"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
按钮
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button should not render as link button when href is undefined 1`] = `
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
@@ -367,7 +344,7 @@ exports[`Button should render empty button without errors 1`] = `
|
||||
exports[`Button should support link button 1`] = `
|
||||
<a
|
||||
class="ant-btn"
|
||||
href="http://ant.design"
|
||||
href="https://ant.design"
|
||||
target="_blank"
|
||||
>
|
||||
<span>
|
||||
|
||||
14
components/button/__tests__/image.test.js
Normal file
14
components/button/__tests__/image.test.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import Button from '..';
|
||||
import imageTest from '../../../tests/shared/imageTest';
|
||||
|
||||
describe('Button image', () => {
|
||||
imageTest(
|
||||
<>
|
||||
<Button type="primary">Primary</Button>
|
||||
<Button>Default</Button>
|
||||
<Button type="dashed">Dashed</Button>
|
||||
<Button type="link">Link</Button>
|
||||
</>,
|
||||
);
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { mount, render } from 'enzyme';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import Button from '..';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
@@ -95,8 +96,11 @@ describe('Button', () => {
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/18118
|
||||
it('should not insert space to link button', () => {
|
||||
expect(<Button type="link">按钮</Button>).toMatchRenderedSnapshot();
|
||||
it('should not insert space to link or text button', () => {
|
||||
const wrapper1 = mount(<Button type="link">按钮</Button>);
|
||||
expect(wrapper1.text()).toBe('按钮');
|
||||
const wrapper2 = mount(<Button type="text">按钮</Button>);
|
||||
expect(wrapper2.text()).toBe('按钮');
|
||||
});
|
||||
|
||||
it('should render empty button without errors', () => {
|
||||
@@ -162,6 +166,24 @@ describe('Button', () => {
|
||||
expect(wrapper.hasClass('ant-btn-loading')).toBe(false);
|
||||
});
|
||||
|
||||
it('reset when loading back of delay', () => {
|
||||
jest.useFakeTimers();
|
||||
const wrapper = mount(<Button loading={{ delay: 1000 }} />);
|
||||
wrapper.update();
|
||||
wrapper.setProps({ loading: { delay: 2000 } });
|
||||
wrapper.update();
|
||||
wrapper.setProps({ loading: false });
|
||||
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
expect(wrapper.find('.ant-btn-loading')).toHaveLength(0);
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('should not clickable when button is loading', () => {
|
||||
const onClick = jest.fn();
|
||||
const wrapper = mount(
|
||||
@@ -175,7 +197,7 @@ describe('Button', () => {
|
||||
|
||||
it('should support link button', () => {
|
||||
const wrapper = mount(
|
||||
<Button target="_blank" href="http://ant.design">
|
||||
<Button target="_blank" href="https://ant.design">
|
||||
link button
|
||||
</Button>,
|
||||
);
|
||||
@@ -188,11 +210,31 @@ describe('Button', () => {
|
||||
expect(<Button>{false}</Button>).toMatchRenderedSnapshot();
|
||||
});
|
||||
|
||||
it('should has click wave effect', async () => {
|
||||
it('should have click wave effect', async () => {
|
||||
const wrapper = mount(<Button type="primary">button</Button>);
|
||||
wrapper.find('.ant-btn').getDOMNode<HTMLButtonElement>().click();
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
await sleep(0);
|
||||
expect(
|
||||
wrapper.find('.ant-btn').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should not have click wave effect for link type button', async () => {
|
||||
const wrapper = mount(<Button type="link">button</Button>);
|
||||
wrapper.find('.ant-btn').getDOMNode<HTMLButtonElement>().click();
|
||||
await sleep(0);
|
||||
expect(
|
||||
wrapper.find('.ant-btn').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should not have click wave effect for text type button', async () => {
|
||||
const wrapper = mount(<Button type="link">button</Button>);
|
||||
wrapper.find('.ant-btn').getDOMNode<HTMLButtonElement>().click();
|
||||
await sleep(0);
|
||||
expect(
|
||||
wrapper.find('.ant-btn').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should not render as link button when href is undefined', async () => {
|
||||
@@ -212,7 +254,6 @@ describe('Button', () => {
|
||||
This {'is'} a test {1}
|
||||
</Button>,
|
||||
);
|
||||
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
||||
@@ -7,9 +7,10 @@ import Group from './button-group';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import Wave from '../_util/wave';
|
||||
import { Omit, tuple } from '../_util/type';
|
||||
import warning from '../_util/warning';
|
||||
import devWarning from '../_util/devWarning';
|
||||
import SizeContext, { SizeType } from '../config-provider/SizeContext';
|
||||
import LoadingIcon from './LoadingIcon';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
|
||||
const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/;
|
||||
const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar);
|
||||
@@ -31,7 +32,9 @@ function insertSpace(child: React.ReactChild, needInserted: boolean) {
|
||||
isString(child.type) &&
|
||||
isTwoCNChar(child.props.children)
|
||||
) {
|
||||
return React.cloneElement(child, {}, child.props.children.split('').join(SPACE));
|
||||
return cloneElement(child, {
|
||||
children: child.props.children.split('').join(SPACE),
|
||||
});
|
||||
}
|
||||
if (typeof child === 'string') {
|
||||
if (isTwoCNChar(child)) {
|
||||
@@ -65,7 +68,7 @@ function spaceChildren(children: React.ReactNode, needInserted: boolean) {
|
||||
);
|
||||
}
|
||||
|
||||
const ButtonTypes = tuple('default', 'primary', 'ghost', 'dashed', 'link');
|
||||
const ButtonTypes = tuple('default', 'primary', 'ghost', 'dashed', 'link', 'text');
|
||||
export type ButtonType = typeof ButtonTypes[number];
|
||||
const ButtonShapes = tuple('circle', 'circle-outline', 'round');
|
||||
export type ButtonShape = typeof ButtonShapes[number];
|
||||
@@ -118,17 +121,33 @@ interface CompoundedComponent
|
||||
__ANT_BUTTON: boolean;
|
||||
}
|
||||
|
||||
type Loading = number | boolean;
|
||||
|
||||
const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (props, ref) => {
|
||||
const {
|
||||
loading,
|
||||
prefixCls: customizePrefixCls,
|
||||
type,
|
||||
danger,
|
||||
shape,
|
||||
size: customizeSize,
|
||||
className,
|
||||
children,
|
||||
icon,
|
||||
ghost,
|
||||
block,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const size = React.useContext(SizeContext);
|
||||
const [loading, setLoading] = React.useState(props.loading);
|
||||
const [innerLoading, setLoading] = React.useState<Loading>(!!loading);
|
||||
const [hasTwoCNChar, setHasTwoCNChar] = React.useState(false);
|
||||
const { getPrefixCls, autoInsertSpaceInButton, direction } = React.useContext(ConfigContext);
|
||||
const buttonRef = (ref as any) || React.createRef<HTMLElement>();
|
||||
let delayTimeout: number;
|
||||
const delayTimeoutRef = React.useRef<number>();
|
||||
|
||||
const isNeedInserted = () => {
|
||||
const { icon, children, type } = props;
|
||||
return React.Children.count(children) === 1 && !icon && type !== 'link';
|
||||
return React.Children.count(children) === 1 && !icon && type !== 'link' && type !== 'text';
|
||||
};
|
||||
|
||||
const fixTwoCNChar = () => {
|
||||
@@ -146,18 +165,24 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
}
|
||||
};
|
||||
|
||||
// =============== Update Loading ===============
|
||||
let loadingOrDelay: Loading;
|
||||
if (typeof loading === 'object' && loading.delay) {
|
||||
loadingOrDelay = loading.delay || true;
|
||||
} else {
|
||||
loadingOrDelay = !!loading;
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (props.loading && typeof props.loading !== 'boolean') {
|
||||
clearTimeout(delayTimeout);
|
||||
clearTimeout(delayTimeoutRef.current);
|
||||
if (typeof loadingOrDelay === 'number') {
|
||||
delayTimeoutRef.current = window.setTimeout(() => {
|
||||
setLoading(loadingOrDelay);
|
||||
}, loadingOrDelay);
|
||||
} else {
|
||||
setLoading(loadingOrDelay);
|
||||
}
|
||||
if (props.loading && typeof props.loading !== 'boolean' && props.loading.delay) {
|
||||
delayTimeout = window.setTimeout(() => {
|
||||
setLoading(props.loading);
|
||||
}, props.loading.delay);
|
||||
} else if (props.loading !== loading) {
|
||||
setLoading(props.loading);
|
||||
}
|
||||
}, [props.loading]);
|
||||
}, [loadingOrDelay]);
|
||||
|
||||
React.useEffect(() => {
|
||||
fixTwoCNChar();
|
||||
@@ -165,28 +190,15 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
|
||||
const handleClick = (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement, MouseEvent>) => {
|
||||
const { onClick } = props;
|
||||
if (loading) {
|
||||
if (innerLoading) {
|
||||
return;
|
||||
}
|
||||
if (onClick) {
|
||||
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
|
||||
}
|
||||
};
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
type,
|
||||
danger,
|
||||
shape,
|
||||
size: customizeSize,
|
||||
className,
|
||||
children,
|
||||
icon,
|
||||
ghost,
|
||||
block,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
warning(
|
||||
devWarning(
|
||||
!(typeof icon === 'string' && icon.length > 2),
|
||||
'Button',
|
||||
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,
|
||||
@@ -209,7 +221,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
break;
|
||||
}
|
||||
|
||||
const iconType = loading ? 'loading' : icon;
|
||||
const iconType = innerLoading ? 'loading' : icon;
|
||||
|
||||
const classes = classNames(prefixCls, className, {
|
||||
[`${prefixCls}-${type}`]: type,
|
||||
@@ -217,7 +229,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||
[`${prefixCls}-icon-only`]: !children && children !== 0 && iconType,
|
||||
[`${prefixCls}-background-ghost`]: ghost,
|
||||
[`${prefixCls}-loading`]: loading,
|
||||
[`${prefixCls}-loading`]: innerLoading,
|
||||
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace,
|
||||
[`${prefixCls}-block`]: block,
|
||||
[`${prefixCls}-dangerous`]: !!danger,
|
||||
@@ -225,10 +237,10 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
});
|
||||
|
||||
const iconNode =
|
||||
icon && !loading ? (
|
||||
icon && !innerLoading ? (
|
||||
icon
|
||||
) : (
|
||||
<LoadingIcon existIcon={!!icon} prefixCls={prefixCls} loading={loading} />
|
||||
<LoadingIcon existIcon={!!icon} prefixCls={prefixCls} loading={!!innerLoading} />
|
||||
);
|
||||
|
||||
const kids =
|
||||
@@ -262,7 +274,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
</button>
|
||||
);
|
||||
|
||||
if (type === 'link') {
|
||||
if (type === 'link' || type === 'text') {
|
||||
return buttonNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,14 @@ There are `primary` button, `default` button, `dashed` button and `link` button
|
||||
import { Button } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Button type="primary">Primary</Button>
|
||||
<Button>Default</Button>
|
||||
<Button type="dashed">Dashed</Button>
|
||||
<Button type="link">Link</Button>
|
||||
</div>,
|
||||
<>
|
||||
<Button type="primary">Primary Button</Button>
|
||||
<Button>Default Button</Button>
|
||||
<Button type="dashed">Dashed Button</Button>
|
||||
<br />
|
||||
<Button type="text">Text Button</Button>
|
||||
<Button type="link">Link Button</Button>
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
@@ -23,10 +23,13 @@ ReactDOM.render(
|
||||
</Button>
|
||||
<Button danger>Default</Button>
|
||||
<Button type="dashed" danger>
|
||||
link
|
||||
Dashed
|
||||
</Button>
|
||||
<Button type="text" danger>
|
||||
Text
|
||||
</Button>
|
||||
<Button type="link" danger>
|
||||
link
|
||||
Link
|
||||
</Button>
|
||||
</>,
|
||||
mountNode,
|
||||
|
||||
@@ -31,22 +31,34 @@ ReactDOM.render(
|
||||
Dashed(disabled)
|
||||
</Button>
|
||||
<br />
|
||||
<Button type="text">Text</Button>
|
||||
<Button type="text" disabled>
|
||||
Text(disabled)
|
||||
</Button>
|
||||
<br />
|
||||
<Button type="link">Link</Button>
|
||||
<Button type="link" disabled>
|
||||
Link(disabled)
|
||||
</Button>
|
||||
<br />
|
||||
<Button danger>Danger Default</Button>
|
||||
<Button danger disabled>
|
||||
Danger Default(disabled)
|
||||
</Button>
|
||||
<br />
|
||||
<Button danger type="text">
|
||||
Danger Text
|
||||
</Button>
|
||||
<Button danger type="text" disabled>
|
||||
Danger Text(disabled)
|
||||
</Button>
|
||||
<br />
|
||||
<Button type="link" danger>
|
||||
Danger Link
|
||||
</Button>
|
||||
<Button type="link" danger disabled>
|
||||
Danger Link(disabled)
|
||||
</Button>
|
||||
<br />
|
||||
<Button danger>Danger Default</Button>
|
||||
<Button danger disabled>
|
||||
Danger Default(disabled)
|
||||
</Button>
|
||||
<div className="site-button-ghost-wrapper">
|
||||
<Button ghost>Ghost</Button>
|
||||
<Button ghost disabled>
|
||||
|
||||
@@ -23,10 +23,13 @@ ReactDOM.render(
|
||||
</Button>
|
||||
<Button ghost>Default</Button>
|
||||
<Button type="dashed" ghost>
|
||||
link
|
||||
Dashed
|
||||
</Button>
|
||||
<Button type="text" ghost>
|
||||
Text
|
||||
</Button>
|
||||
<Button type="link" ghost>
|
||||
link
|
||||
Link
|
||||
</Button>
|
||||
</div>,
|
||||
mountNode,
|
||||
|
||||
@@ -23,14 +23,23 @@ class App extends React.Component {
|
||||
};
|
||||
|
||||
enterLoading = index => {
|
||||
const newLoadings = [...this.state.loadings];
|
||||
newLoadings[index] = true;
|
||||
this.setState({
|
||||
loadings: newLoadings,
|
||||
this.setState(({ loadings }) => {
|
||||
const newLoadings = [...loadings];
|
||||
newLoadings[index] = true;
|
||||
|
||||
return {
|
||||
loadings: newLoadings,
|
||||
};
|
||||
});
|
||||
setTimeout(() => {
|
||||
newLoadings[index] = false;
|
||||
this.setState({ loadings: newLoadings });
|
||||
this.setState(({ loadings }) => {
|
||||
const newLoadings = [...loadings];
|
||||
newLoadings[index] = false;
|
||||
|
||||
return {
|
||||
loadings: newLoadings,
|
||||
};
|
||||
});
|
||||
}, 6000);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
category: Components
|
||||
type: General
|
||||
title: Button
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/fNUKzY1sk/Button.svg
|
||||
---
|
||||
|
||||
To trigger an operation.
|
||||
@@ -15,6 +16,7 @@ In Ant Design we provide 4 types of button.
|
||||
- Primary button: indicate the main action, one primary button at most in one section.
|
||||
- Default button: indicate a series of actions without priority.
|
||||
- Dashed button: used for adding action commonly.
|
||||
- Text button: used for the most secondary action.
|
||||
- Link button: used for external links.
|
||||
|
||||
And 4 other properties additionally.
|
||||
@@ -39,7 +41,7 @@ To get a customized button, just set `type`/`shape`/`size`/`loading`/`disabled`.
|
||||
| shape | can be set to `circle`, `round` or omitted | string | - | |
|
||||
| size | set the size of button | `large` \| `middle` \| `small` | | |
|
||||
| target | same as target attribute of a, works when href is specified | string | - | |
|
||||
| type | can be set to `primary` `ghost` `dashed` `link` or omitted (meaning `default`) | string | `default` | |
|
||||
| type | can be set to `primary` `ghost` `dashed` `danger` `link` `text` or omitted (meaning `default`) | string | `default` | |
|
||||
| onClick | set the handler to handle `click` event | (event) => void | - | |
|
||||
| block | option to fit button width to its parent width | boolean | `false` | |
|
||||
| danger | set the danger status of button | boolean | `false` | |
|
||||
|
||||
@@ -3,6 +3,7 @@ category: Components
|
||||
type: 通用
|
||||
title: Button
|
||||
subtitle: 按钮
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/fNUKzY1sk/Button.svg
|
||||
---
|
||||
|
||||
按钮用于开始一个即时操作。
|
||||
@@ -16,7 +17,8 @@ subtitle: 按钮
|
||||
- 主按钮:用于主行动点,一个操作区域只能有一个主按钮。
|
||||
- 默认按钮:用于没有主次之分的一组行动点。
|
||||
- 虚线按钮:常用于添加操作。
|
||||
- 链接按钮:用于次要或外链的行动点。
|
||||
- 文本按钮:用于最次级的行动点。
|
||||
- 链接按钮:用于作为外链的行动点。
|
||||
|
||||
以及四种状态属性与上面配合使用。
|
||||
|
||||
@@ -42,7 +44,7 @@ subtitle: 按钮
|
||||
| shape | 设置按钮形状,可选值为 `circle`、 `round` 或者不设 | string | - | |
|
||||
| size | 设置按钮大小 | `large` \| `middle` \| `small` | 无 | |
|
||||
| target | 相当于 a 链接的 target 属性,href 存在时生效 | string | - | |
|
||||
| type | 设置按钮类型,可选值为 `primary` `dashed` `link` 或者不设 | string | - | |
|
||||
| type | 设置按钮类型 | `primary` \| `ghost` \| `dashed` \| `danger` \| `link` \| `text` | - | |
|
||||
| onClick | 点击按钮时的回调 | (event) => void | - | |
|
||||
| block | 将按钮宽度调整为其父宽度的选项 | boolean | `false` | |
|
||||
| danger | 设置危险按钮 | boolean | `false` | |
|
||||
|
||||
@@ -22,12 +22,11 @@
|
||||
line-height: @line-height-base;
|
||||
.btn;
|
||||
.btn-default;
|
||||
// Make sure that the target of Button's click event always be `button`
|
||||
// Ref: https://github.com/ant-design/ant-design/issues/7034
|
||||
> i,
|
||||
|
||||
// Fix loading button animation
|
||||
// https://github.com/ant-design/ant-design/issues/24323
|
||||
> span {
|
||||
display: inline-block;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&-primary {
|
||||
@@ -80,6 +79,10 @@
|
||||
.btn-link;
|
||||
}
|
||||
|
||||
&-text {
|
||||
.btn-text;
|
||||
}
|
||||
|
||||
&-dangerous {
|
||||
.btn-danger-default;
|
||||
}
|
||||
@@ -92,6 +95,10 @@
|
||||
.btn-danger-link;
|
||||
}
|
||||
|
||||
&-dangerous&-text {
|
||||
.btn-danger-text;
|
||||
}
|
||||
|
||||
&-icon-only {
|
||||
.btn-square(@btn-prefix-cls);
|
||||
vertical-align: -0.5px;
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
}
|
||||
.button-color(@color; @background; @border) {
|
||||
color: @color;
|
||||
background-color: @background;
|
||||
background: @background;
|
||||
border-color: @border; // a inside Button which only work in Chrome
|
||||
// http://stackoverflow.com/a/17253457
|
||||
> a:only-child {
|
||||
@@ -254,7 +254,6 @@
|
||||
.button-size(
|
||||
@btn-height-sm; @btn-padding-horizontal-sm; @btn-font-size-sm; @btn-border-radius-sm
|
||||
);
|
||||
line-height: @btn-height-sm - 2px;
|
||||
}
|
||||
}
|
||||
// primary button style
|
||||
@@ -347,6 +346,9 @@
|
||||
.btn-link() {
|
||||
.button-variant-other(@link-color, transparent, transparent);
|
||||
box-shadow: none;
|
||||
&:hover {
|
||||
background: @btn-link-hover-bg;
|
||||
}
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
@@ -354,6 +356,48 @@
|
||||
}
|
||||
.button-disabled(@disabled-color; transparent; transparent);
|
||||
}
|
||||
// link button style
|
||||
.btn-text() {
|
||||
.button-variant-other(@text-color, transparent, transparent);
|
||||
box-shadow: none;
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: @text-color;
|
||||
background: @btn-text-hover-bg;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @text-color;
|
||||
background: fadein(@btn-text-hover-bg, 1%);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.button-disabled(@disabled-color; transparent; transparent);
|
||||
}
|
||||
.btn-danger-text() {
|
||||
.button-variant-other(@error-color, transparent, transparent);
|
||||
box-shadow: none;
|
||||
&:hover,
|
||||
&:focus {
|
||||
& when (@theme = dark) {
|
||||
.button-color(~`colorPalette('@{error-color}', 7) `; @btn-text-hover-bg; transparent);
|
||||
}
|
||||
& when not (@theme = dark) {
|
||||
.button-color(~`colorPalette('@{error-color}', 5) `; @btn-text-hover-bg; transparent);
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
& when (@theme = dark) {
|
||||
.button-color(~`colorPalette('@{error-color}', 5) `; fadein(@btn-text-hover-bg, 1%); transparent);
|
||||
}
|
||||
& when not (@theme = dark) {
|
||||
.button-color(~`colorPalette('@{error-color}', 7) `; fadein(@btn-text-hover-bg, 1%); transparent);
|
||||
}
|
||||
}
|
||||
.button-disabled(@disabled-color; transparent; transparent);
|
||||
}
|
||||
// round button
|
||||
.btn-round(@btnClassName: btn) {
|
||||
.button-size(@btn-circle-size; @btn-circle-size / 2; @font-size-base; @btn-circle-size);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user