Compare commits

..

3 Commits
4.8.4 ... 2.2.1

Author SHA1 Message Date
afc163
bd8016f236 changelog for 2.2.1 2016-11-02 13:38:37 +08:00
afc163
137de1aebf Fix controlled DatePicker[showTime] not working, close #3665 2016-11-02 13:34:52 +08:00
Benjy Cui
463b9800a4 fix: should check undefined value, close: #3665 2016-11-02 13:34:42 +08:00
2353 changed files with 34819 additions and 614486 deletions

View File

@@ -1,132 +0,0 @@
const fs = require('fs');
const path = require('path');
const defaultVars = require('./scripts/default-vars');
const darkVars = require('./scripts/dark-vars');
const compactVars = require('./scripts/compact-vars');
function generateThemeFileContent(theme) {
return `const { ${theme}ThemeSingle } = require('./theme');\nconst defaultTheme = require('./default-theme');\n
module.exports = {
...defaultTheme,
...${theme}ThemeSingle
}`;
}
// We need compile additional content for antd user
function finalizeCompile() {
if (fs.existsSync(path.join(__dirname, './lib'))) {
// Build a entry less file to dist/antd.less
const componentsPath = path.join(process.cwd(), 'components');
let componentsLessContent = '';
// Build components in one file: lib/style/components.less
fs.readdir(componentsPath, (err, files) => {
files.forEach(file => {
if (fs.existsSync(path.join(componentsPath, file, 'style', 'index.less'))) {
componentsLessContent += `@import "../${path.join(file, 'style', 'index.less')}";\n`;
}
});
fs.writeFileSync(
path.join(process.cwd(), 'lib', 'style', 'components.less'),
componentsLessContent,
);
});
}
}
function buildThemeFile(theme, vars) {
// Build less entry file: dist/antd.${theme}.less
if (theme !== 'default') {
fs.writeFileSync(
path.join(process.cwd(), 'dist', `antd.${theme}.less`),
`@import "../lib/style/${theme}.less";\n@import "../lib/style/components.less";`,
);
// eslint-disable-next-line no-console
console.log(`Built a entry less file to dist/antd.${theme}.less`);
} else {
fs.writeFileSync(
path.join(process.cwd(), 'dist', `default-theme.js`),
`module.exports = ${JSON.stringify(vars, null, 2)};\n`,
);
return;
}
// Build ${theme}.js: dist/${theme}-theme.js, for less-loader
fs.writeFileSync(
path.join(process.cwd(), 'dist', `theme.js`),
`const ${theme}ThemeSingle = ${JSON.stringify(vars, null, 2)};\n`,
{
flag: 'a',
},
);
fs.writeFileSync(
path.join(process.cwd(), 'dist', `${theme}-theme.js`),
generateThemeFileContent(theme),
);
// eslint-disable-next-line no-console
console.log(`Built a ${theme} theme js file to dist/${theme}-theme.js`);
}
function finalizeDist() {
if (fs.existsSync(path.join(__dirname, './dist'))) {
// Build less entry file: dist/antd.less
fs.writeFileSync(
path.join(process.cwd(), 'dist', 'antd.less'),
'@import "../lib/style/index.less";\n@import "../lib/style/components.less";',
);
// eslint-disable-next-line no-console
fs.writeFileSync(
path.join(process.cwd(), 'dist', 'theme.js'),
`const defaultTheme = require('./default-theme.js');\n`,
);
// eslint-disable-next-line no-console
console.log('Built a entry less file to dist/antd.less');
buildThemeFile('default', defaultVars);
buildThemeFile('dark', darkVars);
buildThemeFile('compact', compactVars);
fs.writeFileSync(
path.join(process.cwd(), 'dist', `theme.js`),
`
function getThemeVariables(options = {}) {
let themeVar = {
'hack': \`true;@import "\${require.resolve('antd/lib/style/color/colorPalette.less')}";\`,
...defaultTheme
};
if(options.dark) {
themeVar = {
...themeVar,
...darkThemeSingle
}
}
if(options.compact){
themeVar = {
...themeVar,
...compactThemeSingle
}
}
return themeVar;
}
module.exports = {
darkThemeSingle,
compactThemeSingle,
getThemeVariables
}`,
{
flag: 'a',
},
);
}
}
module.exports = {
compile: {
finalize: finalizeCompile,
},
dist: {
finalize: finalizeDist,
},
generateThemeFileContent,
};

3
.babelrc Normal file
View File

@@ -0,0 +1,3 @@
{
"presets": ["es2015", "react", "stage-0"]
}

View File

@@ -1,173 +0,0 @@
version: 2
references:
container_config: &container_config
docker:
- image: circleci/node:14
working_directory: ~/ant-design
attach_workspace: &attach_workspace
attach_workspace:
at: ~/ant-design
react_16: &react_16
environment:
REACT: 16
workflow: &workflow
jobs:
- setup:
filters:
branches:
ignore: gh-pages
- dist:
requires:
- setup
- compile:
requires:
- setup
- lint:
requires:
- setup
- test_dist:
requires:
- dist
- test_lib:
requires:
- compile
- test_es:
requires:
- compile
- test_dom:
requires:
- setup
- test_node:
requires:
- setup
- check_metadata:
requires:
- setup
jobs:
setup:
<<: *container_config
steps:
- checkout
- run: node -v
- run: npm -v
- run: npm install
- run:
command: |
set +eo
npm ls
true
- persist_to_workspace:
root: ~/ant-design
paths:
- node_modules
- store_artifacts:
path: package-lock.json
dist:
<<: *container_config
steps:
- checkout
- *attach_workspace
- run: npm run dist
- run: node ./tests/dekko/dist.test.js
- run: npm run bundlesize
- persist_to_workspace:
root: ~/ant-design
paths:
- dist
compile:
<<: *container_config
steps:
- checkout
- *attach_workspace
- run: npm run compile
- run: node ./tests/dekko/lib.test.js
- persist_to_workspace:
root: ~/ant-design
paths:
- lib
- es
lint:
<<: *container_config
steps:
- checkout
- *attach_workspace
- run: npm run lint
test_dist:
<<: *container_config
<<: *react_16
steps:
- checkout
- *attach_workspace
- run:
command: npm test -- -w 1
environment:
LIB_DIR: dist
test_lib:
<<: *container_config
<<: *react_16
steps:
- checkout
- *attach_workspace
- run:
command: npm test -- -w 1
environment:
LIB_DIR: lib
test_es:
<<: *container_config
<<: *react_16
steps:
- checkout
- *attach_workspace
- run:
command: npm test -- -w 1
environment:
LIB_DIR: es
test_dom:
<<: *container_config
<<: *react_16
steps:
- checkout
- *attach_workspace
- run: npm test -- -w 1 --coverage
- run: bash <(curl -s https://codecov.io/bash)
test_node:
<<: *container_config
<<: *react_16
steps:
- checkout
- *attach_workspace
- run: npm run test-node -- -w 1
check_metadata:
<<: *container_config
steps:
- checkout
- *attach_workspace
- run: node ./scripts/check-demo.js
workflows:
version: 2
build_test:
<<: *workflow
nightly:
<<: *workflow
triggers:
- schedule:
cron: '0 0 * * *'
filters:
branches:
only:
- master

View File

@@ -1,3 +0,0 @@
{
"sandboxes": ["antd-reproduction-template-6e93z"]
}

View File

@@ -1,26 +0,0 @@
module.exports = {
ignore: [
'**/~*/**',
'**/_*/**',
'**/icon/**',
'**/__tests__/**',
'**/style/**',
'**/locale/**',
'**/*-provider/**',
'**/*.json',
],
modulePattern: [
{
pattern: /ConfigContext.*renderEmpty/ms,
module: '../empty',
},
{
pattern: /ConfigConsumer.*renderEmpty/ms,
module: '../empty',
},
{
pattern: /config-provider\/context.*renderEmpty/ms,
module: '../empty',
},
],
};

View File

@@ -1 +0,0 @@
node_modules/

View File

@@ -1,4 +1,4 @@
# 🎨 editorconfig.org
# editorconfig.org
root = true

View File

@@ -1,30 +0,0 @@
components/**/*.js
components/**/*.jsx
!components/*/__tests__/**/*.js
!components/*/demo/*
!.*.js
# Docs templates
site/theme/template/Color/ColorPicker.jsx
site/theme/template/IconDisplay/*.js
site/theme/template/IconDisplay/*.jsx
site/theme/template/IconDisplay/fields.js
site/theme/template/Home/**/*.jsx
site/theme/template/utils.jsx
site/theme/template/Layout/**/*.jsx
site/theme/template/Layout/Footer.jsx
site/theme/template/Content/Article.jsx
site/theme/template/Content/EditButton.jsx
site/theme/template/Resources/*.jsx
site/theme/template/Resources/**/*.jsx
site/theme/template/NotFound.jsx
typings
es/**/*
lib/**/*
node_modules
_site
dist
coverage
**/*.d.ts
# Scripts
scripts/previewEditor/**/*
jest-stare

View File

@@ -1,136 +1,64 @@
module.exports = {
extends: [
'airbnb',
'prettier',
'plugin:jest/recommended',
'plugin:react/recommended',
'plugin:import/typescript',
'prettier/react',
],
const eslintrc = {
extends: ['eslint-config-airbnb'],
env: {
browser: true,
node: true,
jasmine: true,
mocha: true,
jest: true,
es6: true,
},
settings: {
react: {
version: '16.9',
parser: 'babel-eslint',
parserOptions: {
ecmaVersion: 6,
ecmaFeatures: {
jsx: true,
experimentalObjectRestSpread: true,
},
},
parser: '@typescript-eslint/parser',
plugins: ['markdown', 'react', 'babel', 'jest', '@typescript-eslint', 'react-hooks', 'unicorn'],
// https://github.com/typescript-eslint/typescript-eslint/issues/46#issuecomment-470486034
overrides: [
{
files: ['*.ts', '*.tsx'],
rules: {
'@typescript-eslint/no-unused-vars': [2, { args: 'none' }],
'no-unused-expressions': 'off',
'@typescript-eslint/no-unused-expressions': 2,
},
},
{
files: ['*.md'],
globals: {
React: true,
ReactDOM: true,
mountNode: true,
},
rules: {
indent: 0,
'no-console': 0,
'no-plusplus': 0,
'eol-last': 0,
'no-script-url': 0,
'prefer-rest-params': 0,
'react/no-access-state-in-setstate': 0,
'react/destructuring-assignment': 0,
'react/no-multi-comp': 0,
'jsx-a11y/href-no-hash': 0,
'import/no-extraneous-dependencies': 0,
'jsx-a11y/control-has-associated-label': 0,
},
},
plugins: [
'markdown',
'react',
'babel',
],
rules: {
'react/jsx-one-expression-per-line': 0,
'react/prop-types': 0,
'react/forbid-prop-types': 0,
'react/jsx-indent': 0,
'react/jsx-wrap-multilines': ['error', { declaration: false, assignment: false }],
'react/jsx-filename-extension': 0,
'react/state-in-constructor': 0,
'react/jsx-props-no-spreading': 0,
'react/destructuring-assignment': 0, // TODO: remove later
'react/require-default-props': 0,
'func-names': 0,
'arrow-body-style': 0,
'react/sort-comp': 0,
'react/display-name': 0,
'react/static-property-placement': 0,
'react/no-find-dom-node': 0,
'react/no-unused-prop-types': 0,
'react/default-props-match-prop-types': 0,
'react-hooks/rules-of-hooks': 2, // Checks rules of Hooks
'import/extensions': 0,
'import/no-cycle': 0,
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: [
'site/**',
'tests/**',
'scripts/**',
'**/*.test.js',
'**/__tests__/*',
'*.config.js',
'**/*.md',
],
},
],
'react/prop-types': 0,
'react/jsx-first-prop-new-line': 0,
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx', '.md'] }],
'import/no-unresolved': 0,
'import/no-extraneous-dependencies': 0,
'no-param-reassign': 0,
'no-return-assign': 0,
'max-len': 0,
'consistent-return': 0,
'no-redeclare': 0,
'react/require-extension': 0,
'react/jsx-indent': 0,
'jsx-a11y/no-static-element-interactions': 0,
'jsx-a11y/anchor-has-content': 0,
'jsx-a11y/click-events-have-key-events': 0,
'jsx-a11y/anchor-is-valid': 0,
'jsx-a11y/no-noninteractive-element-interactions': 0,
// label-has-for has been deprecated
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-for.md
'jsx-a11y/label-has-for': 0,
'comma-dangle': ['error', 'always-multiline'],
'consistent-return': 0, // TODO: remove later
'no-param-reassign': 0, // TODO: remove later
'no-underscore-dangle': 0,
// for (let i = 0; i < len; i++)
'no-plusplus': 0,
// https://eslint.org/docs/rules/no-continue
// labeledLoop is conflicted with `eslint . --fix`
'no-continue': 0,
// ban this for Number.isNaN needs polyfill
'no-restricted-globals': 0,
'max-classes-per-file': 0,
'jest/no-test-callback': 0,
'jest/expect-expect': 0,
'jest/no-done-callback': 0,
'jest/valid-title': 0,
'jest/no-conditional-expect': 0,
'unicorn/better-regex': 2,
'unicorn/prefer-trim-start-end': 2,
'unicorn/expiring-todo-comments': 2,
'unicorn/no-abusive-eslint-disable': 2,
// https://github.com/typescript-eslint/typescript-eslint/issues/2540#issuecomment-692866111
'no-use-before-define': 0,
'@typescript-eslint/no-use-before-define': 2,
'no-shadow': 0,
'@typescript-eslint/no-shadow': [2, { ignoreTypeValueShadow: true }],
// https://github.com/typescript-eslint/typescript-eslint/issues/2528#issuecomment-689369395
'no-undef': 0,
},
globals: {
gtag: true,
'react/no-danger': 0,
},
};
if (process.env.RUN_ENV === 'DEMO') {
eslintrc.globals = {
React: true,
ReactDOM: true,
mountNode: true,
};
Object.assign(eslintrc.rules, {
'no-console': 0,
'no-plusplus': 0,
'eol-last': 0,
'prefer-rest-params': 0,
'react/no-multi-comp': 0,
'react/prefer-es6-class': 0,
'jsx-a11y/href-no-hash': 0,
'import/newline-after-import': 0,
});
}
module.exports = eslintrc;

View File

@@ -1,13 +1,56 @@
# Contributing to Ant Design
Want to contribute to Ant Design? There are a few things you need to know.
The following is a set of guidelines for contributing to Ant Design. Please spend several minutes in reading these guidelines before you create an issue or pull request.
We wrote a **[contribution guide](https://ant.design/docs/react/contributing)** to help you get started.
Anyway, these are just guidelines, not rules, use your best judgment and feel free to propose changes to this document in a pull request.
---
# 参与共建
## Do your homework before asking a question
想要给 Ant Design 贡献自己的一份力量?
It's a great idea to read Eric Steven Raymond's [How To Ask Questions The Smart Way](http://www.catb.org/esr/faqs/smart-questions.html) twice before asking a question. But if you are busy now, I recommend to read [Don't post homework questions](http://www.catb.org/esr/faqs/smart-questions.html#homework) first.
我们写了一份 **[贡献指南](https://ant.design/docs/react/contributing-cn)** 来帮助你开始。
The following guidelines are about *How to avoid Homework Questions*.
### 1. Read the documentation.
It sad but true that someone just glance(not read) [Ant Design's documentation](http://ant.design/). Please read the documentation closely. What's more, you can modify and run our demo with [CodePen](http://codepen.io/benjycui/pen/KgPZrE?editors=001). It's helpful to understand our documentation.
Tips: choose the corresponding documentation with versions selector which in the bottom-right corner.
### 2. Make sure that your question is about Ant Design, not React
Someone may think all of the questions that he/she meets in developing are about Ant Design, but it's not true. So, please read [React's documentaion](http://facebook.github.io/react/docs/getting-started.html) or just Google(not Baidu, seriously) your questions with keywork *React* first. If you are sure that your question is about Ant Design, go ahead.
### 3. Read the FAQ and search the issues list of Ant Design
Your questions may be asked and solved by others. So please spend several minutes on searching. Remember [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself), both code and questions.
P.S.
1. [FAQ](https://github.com/ant-design/ant-design/wiki/FAQ)
1. [Issues list](https://github.com/ant-design/ant-design/issues)
## Close your issue if it's solved
It is a good habit which will save maintainers' time. Thank you!
## Providing a demo while reporting a bug
It would be helpful to provide a demo which can re-produce the bug 100%. Please fork this [CodePen](http://codepen.io/benjycui/pen/KgPZrE?editors=001) and re-produce the bug you met. Then, create an issue. The most important thing is: double check before claiming that you have found a bug.
## Tips about Feature Request
If you believe that Ant Design should provide some features, but it does not. You could create an issue to discuss. However, Ant Design is not Swiss Army Knife, there are some features which Ant Design will not support:
1. Request or operate data
## Tips about Pull Request
It's welcomed to pull request. And there are some tips about that:
1. It is a good habit to create a feature request issue to disscuss whether the feature is necessary before you implement it. However, it's unnecessary to create an issue to claim that you found a typo or improved the readability of documentaion, just create a pull request.
1. Run `npm run lint` and fix those errors before committing in order to keep consistent code style.
1. Rebase before creating a PR to keep commit history clear.
1. Add some descriptions and refer relative issues for you PR.

9
.github/FUNDING.yml vendored
View File

@@ -1,9 +0,0 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
open_collective: ant-design
patreon: ant_design
ko_fi: # Replace with a single Ko-fi username
issuehunt: ant-design/ant-design
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
custom: https://www.buymeacoffee.com/antdesign

View File

@@ -1,15 +1,35 @@
<!--
⚠️ ⚠️ ⚠️ IMPORTANT: Please use the following link to create a new issue: ⚠️ ⚠️ ⚠️
http://new-issue.ant.design
If your issue was not created using the app above, it will be closed immediately.
-->
<!-- Issue Template -->
<!--
⚠️ ⚠️ ⚠️ 注意:请使用下面的链接来新建 issue ⚠️ ⚠️ ⚠️
antd 的用法咨询,建议通过以下渠道,官方 issues 目前没有足够精力提供此类咨询服务:
http://new-issue.ant.design
1. [Stack Overflow](http://stackoverflow.com/questions/tagged/antd)
2. [Segment Fault](https://segmentfault.com/t/antd)(中文)
3. [Gitter](https://gitter.im/ant-design/ant-design)
不是用上面的链接创建的 issue 会被立即关闭
如果是报告 bug请按照下列格式书写并务必提供复现步骤否则恕难解决感谢您的支持
-->
#### 发生问题的环境是:
<!-- 务必提供 -->
- antd 版本:
- 操作系统及其版本:
- 浏览器及其版本:
#### 您做了什么?请提供尽可能详细的重现步骤。
<!-- 如:引入 antd 了 Button -->
#### 您期待的结果是:
<!-- 如:像官网一样正常显示 -->
#### 实际上的结果是:
<!-- 如:样式错位了,最好提供截图 -->
#### 可重现的在线演示
<!-- 请修改并 Fork http://codepen.io/benjycui/pen/KgPZrE?editors=001 -->

View File

@@ -1,5 +0,0 @@
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.

View File

@@ -1,61 +1,8 @@
<!--
First of all, thank you for your contribution! 😄
First of all, thanks for your contribution! :-)
New feature please send a pull request to feature branch, and rest to master branch.
Pull requests will be merged after one of the collaborators approve.
Please makes sure that these forms are filled before submitting your pull request, thank you!
-->
Please makes sure these boxes are checked before submitting your PR, 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 / documentation update
- [ ] Demo update
- [ ] Component style update
- [ ] TypeScript definition update
- [ ] Bundle size optimization
- [ ] Performance optimization
- [ ] Enhancement feature
- [ ] Internationalization
- [ ] Refactoring
- [ ] Code style optimization
- [ ] Test Case
- [ ] Branch merge
- [ ] Other (about what?)
### 🔗 Related issue link
<!--
1. Describe the source of requirement, like related issue link.
-->
### 💡 Background and solution
<!--
1. Describe the problem and the scenario.
2. GIF or snapshot should be provided if includes UI/interactive modification.
3. How to fix the problem, and list final API implementation and usage sample if that is a new feature.
-->
### 📝 Changelog
<!--
Describe changes from the user side, and list all potential break changes or other risks.
--->
| Language | Changelog |
| ---------- | --------- |
| 🇺🇸 English | |
| 🇨🇳 Chinese | |
### ☑️ Self Check before Merge
⚠️ Please check all items below before review. ⚠️
- [ ] Doc is updated/provided or not needed
- [ ] Demo is updated/provided or not needed
- [ ] TypeScript definition is updated/provided or not needed
- [ ] Changelog is provided or not needed
* [ ] Make sure you follow antd's [code convention](https://github.com/ant-design/ant-design/wiki/Code-convention-for-antd).
* [ ] Run `npm run lint` and fix those errors before submitting in order to keep consistent code style.
* [ ] Rebase before creating a PR to keep commit history clear.
* [ ] Add some descriptions and refer relative issues for you PR.

View File

@@ -1,61 +0,0 @@
<!--
首先,感谢你的贡献!😄
新特性请提交至 feature 分支,其余可提交至 master 分支。
在维护者审核通过后会合并。
请确保填写以下 pull request 的信息,谢谢!~
-->
[[English Template / 英文模板](https://github.com/ant-design/ant-design/blob/master/.github/PULL_REQUEST_TEMPLATE.md)]
### 🤔 这个变动的性质是?
- [ ] 新特性提交
- [ ] 日常 bug 修复
- [ ] 站点、文档改进
- [ ] 演示代码改进
- [ ] 组件样式/交互改进
- [ ] TypeScript 定义更新
- [ ] 包体积优化
- [ ] 性能优化
- [ ] 功能增强
- [ ] 国际化改进
- [ ] 重构
- [ ] 代码风格优化
- [ ] 测试用例
- [ ] 分支合并
- [ ] 其他改动(是关于什么的改动?)
### 🔗 相关 Issue
<!--
1. 描述相关需求的来源,如相关的 issue 讨论链接。
-->
### 💡 需求背景和解决方案
<!--
1. 要解决的具体问题。
2. 列出最终的 API 实现和用法。
3. 涉及UI/交互变动需要有截图或 GIF。
-->
### 📝 更新日志
<!--
从用户角度描述具体变化,以及可能的 breaking change 和其他风险。
-->
| 语言 | 更新描述 |
| ------- | -------- |
| 🇺🇸 英文 | |
| 🇨🇳 中文 | |
### ☑️ 请求合并前的自查清单
⚠️ 请自检并全部**勾选全部选项**。⚠️
- [ ] 文档已补充或无须补充
- [ ] 代码演示已提供或无须提供
- [ ] TypeScript 定义已补充或无须补充
- [ ] Changelog 已提供或无须提供

10
.github/config.yml vendored
View File

@@ -1,10 +0,0 @@
# Configuration for request-info - https://github.com/behaviorbot/request-info
# *Required* Comment to reply with
requestInfoReplyComment: >
We would appreciate it if you could provide us with more info about this issue/pr!
Please provide a online reproduction by forking this link https://u.ant.design/codesandbox-repro or a minimal GitHub repository.
Issues labeled by Need Reproduce will be closed if no activities in 7 days.
# *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given
requestInfoLabelToAdd: needs-more-info

View File

@@ -1,11 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

14
.github/lock.yml vendored
View File

@@ -1,14 +0,0 @@
# Configuration for lock-threads - https://github.com/dessant/lock-threads
# Number of days of inactivity before a closed issue or pull request is locked
daysUntilLock: 365
# Comment to post before locking. Set to `false` to disable
lockComment: >
This thread has been automatically locked because it has not had recent
activity. Please open a new issue for related bugs and link to relevant
comments in this thread.
# Issues or pull requests with these labels will not be locked
# exemptLabels:
# - no-locking
# Limit to only `issues` or `pulls`
only: issues

View File

@@ -1,3 +0,0 @@
comment: 'Could you please add tests to make sure this change works as expected?',
fileExtensions: [.ts', '.tsx', '.json']
testDir: '__tests__'

View File

@@ -1,7 +0,0 @@
# Configuration for weekly-digest - https://github.com/apps/weekly-digest
publishDay: sun
canPublishIssues: true
canPublishPullRequests: true
canPublishContributors: true
canPublishStargazers: true
canPublishCommits: true

View File

@@ -1,16 +0,0 @@
name: 🧐 Auto Closer
on:
issues:
types: [labeled]
jobs:
close-by-label:
runs-on: ubuntu-latest
if: github.event.label.name == '3.x'
steps:
- name: Comment on issue
uses: peter-evans/close-issue@v1
with:
comment: "Hi @${{ github.event.issue.user.login }},<br />Current branch is off the maintenance period. We may not accept pull request or fix bug with it anymore. This topic will be auto closed.<br /><br />你好 @${{ github.event.issue.user.login }},<br />当前分支已经过了维护期。我们不会再接受对其的相关 PR 与 issue。当前 topic 会被自动关闭。"

View File

@@ -1,46 +0,0 @@
# This workflow checks out code, performs a Codacy security scan
# and integrates the results with the
# GitHub Advanced Security code scanning feature. For more information on
# the Codacy security scan action usage and parameters, see
# https://github.com/codacy/codacy-analysis-cli-action.
# For more information on Codacy Analysis CLI in general, see
# https://github.com/codacy/codacy-analysis-cli.
name: Codacy Security Scan
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
codacy-security-scan:
name: Codacy Security Scan
runs-on: ubuntu-latest
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v2
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@1.1.0
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
verbose: true
output: results.sarif
format: sarif
# Adjust severity of non-security issues
gh-code-scanning-compat: true
# Force 0 exit code to allow SARIF file generation
# This will handover control about PR rejection to the GitHub side
max-allowed-issues: 2147483647
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: results.sarif

View File

@@ -1,54 +0,0 @@
name: "CodeQL"
on:
push:
branches: [master, 0.12-stable, 1.x-stable, 2.x-stable, 3.x-stable, feature, gh-pages]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: '0 13 * * 1'
jobs:
analyse:
name: Analyse
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -1,18 +0,0 @@
name: 📦 Compressed Size
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
env:
CI_JOB_NUMBER: 1
steps:
- uses: actions/checkout@v2
- uses: preactjs/compressed-size-action@v2
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
pattern: "./dist/**/*.min.{js,css}"
build-script: "dist"

View File

@@ -1,30 +0,0 @@
name: Deploy website
on:
release:
types: [published]
branches:
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
- name: install
run: npm install
- name: build
run: npm run predeploy
- name: deploy
uses: peaceiris/actions-gh-pages@v2
env:
ACTIONS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }}
# PERSONAL_TOKEN: ${{ secrets.PERSONAL_TOKEN }}
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PUBLISH_BRANCH: gh-pages
PUBLISH_DIR: ./_site
with:
emptyCommits: false

View File

@@ -1,17 +0,0 @@
name: gitleaks
on: [push,pull_request]
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: '1'
- name: wget
uses: wei/wget@v1
with:
args: -O .gitleaks.toml https://raw.githubusercontent.com/ycjcl868/gitleaks/master/.gitleaks.toml
- name: gitleaks-action
uses: zricethezav/gitleaks-action@master

View File

@@ -1,13 +0,0 @@
name: CI
on: [push]
jobs:
lighthouseci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2-beta
with:
node-version: '14'
- run: npm install && npm install -g @lhci/cli@0.4.x
- run: npm run site
- run: lhci autorun --upload.target=temporary-public-storage

View File

@@ -1,14 +0,0 @@
name: Mirror
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 }}

View File

@@ -1,17 +0,0 @@
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@master
with:
fetch-depth: 0
- name: Automatic Rebase
uses: cirrus-actions/rebase@1.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,13 +0,0 @@
name: 🔄 Sync packages
on:
release:
types: [published]
jobs:
sync_packages:
runs-on: ubuntu-latest
steps:
- name: Sync packages
uses: LexSwed/npm-package-sync@master
with:
registry-to: 'https://npm.pkg.github.com'
token-to: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,210 +0,0 @@
name: test
on: [push, pull_request]
jobs:
setup:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
- name: cache package-lock.json
uses: actions/cache@v2
with:
path: package-temp-dir
key: lock-${{ github.sha }}
- name: create package-lock.json
run: npm i --package-lock-only
- name: hack for singe file
run: |
if [ ! -d "package-temp-dir" ]; then
mkdir package-temp-dir
fi
cp package-lock.json package-temp-dir
- name: cache node_modules
id: node_modules_cache_id
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
- name: install
if: steps.node_modules_cache_id.outputs.cache-hit != 'true'
run: npm ci
compile:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
- name: restore cache from package-lock.json
uses: actions/cache@v2
with:
path: package-temp-dir
key: lock-${{ github.sha }}
- name: restore cache from node_modules
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
- name: cache lib
uses: actions/cache@v2
with:
path: lib
key: lib-${{ github.sha }}
- name: cache es
uses: actions/cache@v2
with:
path: es
key: es-${{ github.sha }}
- name: compile
run: npm run compile
- name: check
run: node ./tests/dekko/lib.test.js
needs: setup
dist:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
- name: restore cache from package-lock.json
uses: actions/cache@v2
with:
path: package-temp-dir
key: lock-${{ github.sha }}
- name: restore cache from node_modules
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
- name: dist
run: npm run dist
env:
NODE_OPTIONS: --max_old_space_size=4096
- name: check
run: node ./tests/dekko/dist.test.js
- name: test
run: npm test
env:
LIB_DIR: dist
needs: setup
lint:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
- name: restore cache from package-lock.json
uses: actions/cache@v2
with:
path: package-temp-dir
key: lock-${{ github.sha }}
- name: restore cache from node_modules
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
- name: lint
run: npm run lint
needs: setup
node:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
- name: restore cache from package-lock.json
uses: actions/cache@v2
with:
path: package-temp-dir
key: lock-${{ github.sha }}
- name: restore cache from node_modules
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
- name: test
run: npm test
needs: setup
lib:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
- name: restore cache from package-lock.json
uses: actions/cache@v2
with:
path: package-temp-dir
key: lock-${{ github.sha }}
- name: restore cache from node_modules
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
- name: restore cache from lib
uses: actions/cache@v2
with:
path: lib
key: lib-${{ github.sha }}
- name: test
run: npm test
env:
LIB_DIR: lib
needs: compile
es:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
- name: restore cache from package-lock.json
uses: actions/cache@v2
with:
path: package-temp-dir
key: lock-${{ github.sha }}
- name: restore cache from node_modules
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
- name: restore cache from es
uses: actions/cache@v2
with:
path: es
key: es-${{ github.sha }}
- name: test
run: npm test
env:
LIB_DIR: es
needs: compile

View File

@@ -1,35 +0,0 @@
name: UI
on:
pull_request_target:
push:
branches:
- master
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: checkout
if: github.event_name == 'pull_request_target'
uses: actions/checkout@master
with:
ref: refs/pull/${{ github.event.pull_request.number }}/head
- name: checkout
if: github.event_name == 'push'
uses: actions/checkout@master
- name: install
run: npm install
- name: test
run: npm run test-image
- name: argos-ci
if: github.event_name == 'pull_request_target'
run: npm run argos -- --token ${{ secrets.ARGOS_TOKEN }} --branch pull/${{ github.event.pull_request.number }}/merge --commit ${{ github.event.pull_request.head.sha }}
- name: argos-ci
if: github.event_name == 'push'
run: npm run argos -- --token ${{ secrets.ARGOS_TOKEN }} --branch ${GITHUB_REF##*/} --commit ${{ github.sha }}

37
.gitignore vendored
View File

@@ -15,7 +15,6 @@ Thumbs.db
*.swp
*.swo
*.log
*.log.*
*.json.gzip
node_modules/
.buildpath
@@ -25,43 +24,9 @@ nohup.out
_site
_data
dist
report.html
/lib
/es
elasticsearch-*
config/base.yaml
/.vscode/
/coverage
yarn.lock
package-lock.json
components/**/*.js
components/**/*.jsx
!components/**/__tests__/**/*.js
!components/**/__tests__/**/*.js.snap
/.history
*.tmp
# Docs templates
site/theme/template/Color/ColorPicker.jsx
site/theme/template/IconDisplay/*.js
site/theme/template/IconDisplay/*.jsx
site/theme/template/IconDisplay/fields.js
site/theme/template/Home/**/*.jsx
site/theme/template/utils.jsx
site/theme/template/Layout/Footer.jsx
site/theme/template/Layout/Header/**/*.jsx
site/theme/template/Layout/SiteContext.jsx
site/theme/template/Content/Article.jsx
site/theme/template/Content/EditButton.jsx
site/theme/template/Resources/*.jsx
site/theme/template/Resources/**/*.jsx
site/theme/template/NotFound.jsx
scripts/previewEditor/index.html
components/version/version.tsx
# Image snapshot diff
__diff_output__/
__image_snapshots__/
/jest-stare
/imageSnapshots
/imageDiffSnapshots
/.vscode/

View File

@@ -1,8 +0,0 @@
ports:
- port: 8001
onOpen: open-preview
tasks:
- before: >
export DEV_HOST=$(gp url 8001)
init: npm install
command: npm start

View File

@@ -1,24 +0,0 @@
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\\.(j|t)s$',
transformIgnorePatterns,
snapshotSerializers: ['enzyme-to-json/serializer'],
globals: {
'ts-jest': {
tsConfigFile: './tsconfig.test.json',
},
},
preset: 'jest-puppeteer',
testTimeout: 10000,
};

View File

@@ -1,55 +0,0 @@
const transformIgnorePatterns = [
'/dist/',
// Ignore modules without es dir.
// Update: @babel/runtime should also be transformed
'node_modules/(?!.*@(babel|ant-design))[^/]+?/(?!(es|node_modules)/)',
];
function getTestRegex(libDir) {
if (libDir === 'dist') {
return 'demo\\.test\\.js$';
}
return '.*\\.test\\.(j|t)sx?$';
}
module.exports = {
verbose: true,
setupFiles: ['./tests/setup.js'],
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'md'],
modulePathIgnorePatterns: ['/_site/'],
moduleNameMapper: {
'^dnd-core$': 'dnd-core/dist/cjs',
'^react-dnd$': 'react-dnd/dist/cjs',
'^react-dnd-html5-backend$': 'react-dnd-html5-backend/dist/cjs',
'^react-dnd-touch-backend$': 'react-dnd-touch-backend/dist/cjs',
'^react-dnd-test-backend$': 'react-dnd-test-backend/dist/cjs',
'^react-dnd-test-utils$': 'react-dnd-test-utils/dist/cjs',
'\\.(css|less)$': 'identity-obj-proxy',
},
testPathIgnorePatterns: ['/node_modules/', 'dekko', 'node', 'image.test.js', 'image.test.ts'],
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: getTestRegex(process.env.LIB_DIR),
collectCoverageFrom: [
'components/**/*.{ts,tsx}',
'!components/*/style/index.tsx',
'!components/style/index.tsx',
'!components/*/locale/index.tsx',
'!components/*/__tests__/type.test.tsx',
'!components/**/*/interface.{ts,tsx}',
'!components/*/__tests__/image.test.{ts,tsx}',
],
transformIgnorePatterns,
snapshotSerializers: ['enzyme-to-json/serializer'],
globals: {
'ts-jest': {
tsConfig: './tsconfig.test.json',
},
},
testURL: 'http://localhost',
};

View File

@@ -1,19 +0,0 @@
const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
// jest config for server render environment
module.exports = {
setupFiles: ['./tests/setup.js'],
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
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: 'demo\\.test\\.(j|t)s$',
testEnvironment: 'node',
transformIgnorePatterns,
snapshotSerializers: ['enzyme-to-json/serializer'],
};

View File

@@ -1,22 +0,0 @@
const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
// jest config for server render environment
module.exports = {
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: 'check-site\\.js$',
testEnvironment: 'node',
transformIgnorePatterns,
snapshotSerializers: ['enzyme-to-json/serializer'],
globals: {
'ts-jest': {
tsConfigFile: './tsconfig.test.json',
},
},
};

21
.lesshintrc Normal file
View File

@@ -0,0 +1,21 @@
{
"propertyOrdering": false,
"hexLength": "short",
"stringQuotes": false,
"decimalZero": false,
"importantRule": false,
"zeroUnit": "no_unit",
"qualifyingElement": false,
"duplicateProperty": false,
"importPath": false,
"finalNewline": false,
"newlineAfterBlock": false,
"maxCharPerLine": false,
"excludedFiles": [
"components/layout/style/mixin.less",
"components/style/core/base.less",
"components/style/core/iconfont.less",
"components/style/core/normalize.less",
"components/style/mixins/compatibility.less"
]
}

View File

@@ -1 +0,0 @@
~*

View File

@@ -1,33 +0,0 @@
**/*.png
**/*.svg
CODEOWNERS
.dockerignore
Dockerfile.ui-test
package.json
.umi
.umi-production
AUTHORS.txt
lib/
es/
dist/
_site/
coverage/
CNAME
LICENSE
yarn.lock
netlify.toml
yarn-error.log
*.sh
*.snap
components/*/*.js
components/*/*.jsx
components/*/*.md
docs/**/*.md
.gitignore
.npmignore
.prettierignore
.DS_Store
.editorconfig
.eslintignore
**/*.yml
components/style/color/*.less

View File

@@ -1,15 +0,0 @@
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"proseWrap": "never",
"arrowParens": "avoid",
"overrides": [
{
"files": ".prettierrc",
"options": {
"parser": "json"
}
}
]
}

View File

@@ -1,9 +0,0 @@
const config = {
plugins: [
'remark-preset-lint-recommended',
['remark-lint-list-item-indent', 'space'],
['remark-lint-no-literal-urls', false],
],
};
module.exports = config;

View File

@@ -1,16 +0,0 @@
{
"extends": [
"stylelint-config-standard",
"stylelint-config-rational-order",
"stylelint-config-prettier"
],
"plugins": ["stylelint-order", "stylelint-declaration-block-no-ignored-properties"],
"rules": {
"comment-empty-line-before": null,
"function-name-case": ["lower", { "ignoreFunctions": ["/colorPalette/"] }],
"no-invalid-double-slash-comments": null,
"no-descending-specificity": null,
"declaration-empty-line-before": null
},
"ignoreFiles": ["components/style/color/{bezierEasing,colorPalette,tinyColor}.less"]
}

View File

@@ -3,21 +3,4 @@ sudo: false
language: node_js
node_js:
- 11
cache:
directories:
- $HOME/.npm
matrix:
fast_finish: true
include:
- env: TEST_TYPE=lint
- env: TEST_TYPE=test:dist
- env: TEST_TYPE=test:lib
- env: TEST_TYPE=test:es
- env: TEST_TYPE=test:dom
- env: TEST_TYPE=test:node
script:
- scripts/travis-script.sh
- "6"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1
CNAME
View File

@@ -1 +0,0 @@
ant.design

View File

@@ -1,12 +0,0 @@
# CODEOWNERS syntax
# A CODEOWNERS file uses a pattern that follows the same rules used in gitignore files.
# The pattern is followed by one or more GitHub usernames or team names using the standard @username or @org/team-name format.
# You can also refer to a user by an email address that has been added to their GitHub account, for example user@example.com.
# no default file owner
#/* @afc163
/components/tree/* @zombieJ
/components/tree-select/* @zombieJ
# ...
# other components

View File

@@ -1,46 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [xingmin.zhu@alipay.com.](mailto:xingmin.zhu@alipay.com.) The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version].
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -1,6 +0,0 @@
FROM buildkite/puppeteer:v3.0.4
RUN mkdir /app
WORKDIR /app
COPY package.json ./
ENV PATH="${PATH}:/app/node_modules/.bin"
COPY . .

View File

@@ -1,6 +1,6 @@
MIT LICENSE
Copyright (c) 2015-present Ant UED, https://xtech.antfin.com/
Copyright (c) 2015-present Alipay.com, https://www.alipay.com/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -1,166 +0,0 @@
<p align="center">
<a href="https://ant.design">
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
</a>
</p>
<h1 align="center">Ant Design</h1>
<div align="center">
Uma solução empresarial de design e biblioteca UI para React.
[![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]
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![FOSSA Status][fossa-image]][fossa-url] [![Issues need help][help-wanted-image]][help-wanted-url]
[![Follow Twitter][twitter-image]][twitter-url] [![Gitter][gitter-english-image]][gitter-english-url] [![Gitter][gitter-chinese-image]][gitter-chinese-url] [![[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>
[![](https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*Yl83RJhUE7kAAAAAAAAAAABkARQnAQ)](https://ant.design)
[English](./README.md) | Português | [简体中文](./README-zh_CN.md)
## ✨ Funcionalidades
- 🌈 Design empresarial de interface para aplicações web.
- 📦 Um conjunto de alta qualidade, componentes React prontos para uso.
- 🛡 Escrito em TypeScript com tipos previsíveis.
- ⚙️ Pacote completo de recursos de design e ferramentas de desenvolvimento.
- 🌍 Suporte de internacionalização para dezenas de idiomas.
- 🎨 Personalização poderosa do tema em todos os detalhes.
## 🖥 Suporte aos ambientes
- Navegadores modernos e Internet Explorer 11 (com [polyfills](https://ant.design/docs/react/getting-started#Compatibility))
- Renderização no lado do servidor (server-side)
- [Electron](https://www.electronjs.org/)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
| --- | --- | --- | --- | --- | --- |
| IE11, Edge | últimas 2 versões | últimas 2 versões | últimas 2 versões | últimas 2 versões | últimas 2 versões |
## 📦 Instalação
```bash
npm install antd
```
```bash
yarn add antd
```
## 🔨 Uso
```jsx
import { Button, DatePicker } from 'antd';
const App = () => (
<>
<Button type="primary">PRESS ME</Button>
<DatePicker />
</>
);
```
Importe o estilo manualmente:
```jsx
import 'antd/dist/antd.css'; // ou 'antd/dist/antd.less'
```
### TypeScript
Veja [Uso no Typescript](https://ant.design/docs/react/use-in-typescript).
## 🌍 Internacionalização
Veja [i18n](https://ant.design/docs/react/i18n).
## 🔗 Links
- [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)
- [Ant Design Icones](https://github.com/ant-design/ant-design-icons)
- [Ant Design Cores](https://github.com/ant-design/ant-design-colors)
- [Ant Design Pro Layout](https://github.com/ant-design/ant-design-pro-layout)
- [Ant Design Pro Blocks](https://github.com/ant-design/pro-blocks)
- [Tema escuro](https://github.com/ant-design/ant-design-dark-theme)
- [Página de aterrissagem](https://landing.ant.design)
- [Motion](https://motion.ant.design)
- [Mercado de páginas](http://scaffold.ant.design)
- [Instruções ao desenvolvedor](https://github.com/ant-design/ant-design/wiki/Development)
- [Versionando as notas de atualização](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B)
- [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](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
Use Gitpod, um ambiente de desenvolvimento online para GitHub.
[![Abrir no Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design)
Ou clone localmente:
```bash
$ git clone git@github.com:ant-design/ant-design.git
$ cd ant-design
$ npm install
$ npm start
```
Abra seu navegador e visite http://127.0.0.1:8001, veja mais em [Desenvolvimento](https://github.com/ant-design/ant-design/wiki/Development).
## 🤝 Contribuição [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
Leia nosso [guia de contribução](https://ant.design/docs/react/contributing) e vamos contruir um melhor antd juntos.
Nós saudamos todas as contribuições. Por favor, leia nosso [CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) primeiro. Você pode submeter todas as ideias como [Pull Requests](https://github.com/ant-design/ant-design/pulls) ou como [GitHub issues](https://github.com/ant-design/ant-design/issues). Se você quiser melhorar o código, verifique [instruções ao desenvolvedor](https://github.com/ant-design/ant-design/wiki/Development) e divirta-se! :)
Se você é um colaborador, por favor siga nossa [Pull Request princípio](https://github.com/ant-design/ant-design/wiki/PR-principle) para criar um Pull Request através do [template do colaborador](https://github.com/ant-design/ant-design/compare?expand=1&template=collaborator.md).
[![Let's fund issues in this repository](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884)
## ❤️ Patrocionadores e Apoiadores [![](https://opencollective.com/ant-design/tiers/sponsors/badge.svg?label=Sponsors&color=brightgreen)](https://opencollective.com/ant-design#support) [![](https://opencollective.com/ant-design/tiers/backers/badge.svg?label=Backers&color=brightgreen)](https://opencollective.com/ant-design#support)
[![](https://opencollective.com/ant-design/tiers/sponsors.svg?avatarHeight=36)](https://opencollective.com/ant-design#support)
[![](https://opencollective.com/ant-design/tiers/backers.svg?avatarHeight=36)](https://opencollective.com/ant-design#support)

View File

@@ -1,179 +1,86 @@
<p align="center">
<a href="https://ant.design">
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
<a href="http://ant.design">
<img width="320" src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg">
</a>
</p>
<h1 align="center">Ant Design</h1>
# Ant Design
[![](https://img.shields.io/travis/ant-design/ant-design.svg?style=flat-square)](https://travis-ci.org/ant-design/ant-design)
[![npm package](https://img.shields.io/npm/v/antd.svg?style=flat-square)](https://www.npmjs.org/package/antd)
[![NPM downloads](http://img.shields.io/npm/dm/antd.svg?style=flat-square)](https://npmjs.org/package/antd)
[![CDNJS](https://img.shields.io/cdnjs/v/antd.svg?style=flat-square)](https://cdnjs.com/libraries/antd)
[![Dependency Status](https://david-dm.org/ant-design/ant-design.svg?style=flat-square)](https://david-dm.org/ant-design/ant-design)
[![Join the chat at https://gitter.im/ant-design/ant-design](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<div align="center">
一套企业级的 UI 设计语言和 React 实现。
一套企业级 UI 设计语言和 React 组件库。
## 特性
[![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]
- 提炼和服务企业级中后台产品的交互语言和视觉风格。
- [React Component](http://react-component.github.io/badgeboard/) 基础上精心封装的高质量 UI 组件。
- 使用 TypeScript 构建,提供完整的类型定义文件。
- 基于 npm + webpack + babel + [dora](https://github.com/dora-js/dora) + [dva](https://github.com/dvajs/dva) 的企业级业务开发框架。
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![FOSSA Status][fossa-image]][fossa-url] [![Issues need help][help-wanted-image]][help-wanted-url]
[![Follow Twitter][twitter-image]][twitter-url] [![Gitter][gitter-english-image]][gitter-english-url] [![Gitter][gitter-chinese-image]][gitter-chinese-url] [![[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/circleci/build/github/ant-design/ant-design/master?style=flat-square
[circleci-url]: https://circleci.com/gh/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
[semver-stability-image]: https://api.dependabot.com/badges/compatibility_score?dependency-name=antd&package-manager=npm_and_yarn&version-scheme=semver
</div>
[![](https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*Ey3wTo-5__QAAAAAAAAAAABkARQnAQ)](https://ant.design/index-cn)
[English](./README.md) | [Português](./README-pt_BR.md) | 简体中文
## ✨ 特性
- 🌈 提炼自企业级中后台产品的交互语言和视觉风格。
- 📦 开箱即用的高质量 React 组件。
- 🛡 使用 TypeScript 开发,提供完整的类型定义文件。
- ⚙️ 全链路开发和设计工具体系。
- 🌍 数十个国际化语言支持。
- 🎨 深入每个细节的主题定制能力。
## 🖥 兼容环境
- 现代浏览器和 IE11需要 [polyfills](https://ant.design/docs/react/getting-started-cn#兼容性))。
- 支持服务端渲染。
- [Electron](https://www.electronjs.org/)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| --- | --- | --- | --- | --- |
| IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 📦 安装
## 安装
```bash
npm install antd --save
npm install antd
```
```bash
yarn add antd
```
## 🔨 示例
## 示例
```jsx
import { Button, DatePicker } from 'antd';
const App = () => (
<>
<Button type="primary">PRESS ME</Button>
<DatePicker />
</>
);
import { DatePicker } from 'antd';
ReactDOM.render(<DatePicker />, mountNode);
```
引入样式:
```jsx
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
```
### 🌈 定制主题
按需加载可通过此写法 `import DatePicker from 'antd/lib/date-picker'` 或使用插件 [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)。
参考 [定制主题](https://ant.design/docs/react/customize-theme-cn) 文档。
### 🛡 TypeScript
## 浏览器支持
参考 [在 TypeScript 中使用](https://ant.design/docs/react/use-in-typescript-cn)
现代浏览器和 IE9 及以上
## 🌍 国际化
> [IE8 issues](https://github.com/xcatliu/react-ie8)
参考 [国际化文档](https://ant.design/docs/react/i18n-cn)。
## TypeScript
## 🔗 链接
tsconfig.json
- [首页](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/)
```
{
"compilerOptions": {
"moduleResolution": "node",
"jsx": "preserve",
"allowSyntheticDefaultImports": true
}
}
```
## 链接
- [首页](http://ant.design/)
- [React 实现](http://ant.design/docs/react/introduce)
- [修改记录](CHANGELOG.zh-CN.md)
- [开发脚手架](https://github.com/ant-design/antd-init/)
- [开发工具文档](http://ant-tool.github.io/)
- [React 基础组件](http://react-component.github.io/)
- [移动端组件](http://mobile.ant.design)
- [Ant Design 图标](https://github.com/ant-design/ant-design-icons)
- [Ant Design 色彩](https://github.com/ant-design/ant-design-colors)
- [Ant Design Pro 布局组件](https://github.com/ant-design/ant-design-pro-layout)
- [Ant Design Pro 区块集](https://github.com/ant-design/pro-blocks)
- [Dark Theme](https://github.com/ant-design/ant-design-dark-theme)
- [首页模板集](https://landing.ant.design)
- [动效](https://motion.ant.design)
- [脚手架市场](http://scaffold.ant.design)
- [设计规范速查手册](https://github.com/ant-design/ant-design/wiki/Ant-Design-%E8%AE%BE%E8%AE%A1%E5%9F%BA%E7%A1%80%E7%AE%80%E7%89%88)
- [开发者说明](https://github.com/ant-design/ant-design/wiki/Development)
- [版本发布规则](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B)
- [常见问题](https://ant.design/docs/react/faq-cn)
- [CodeSandbox 模板](https://u.ant.design/codesandbox-repro) for bug reports
- [React 代码规范](https://github.com/react-component/react-component.github.io/blob/master/docs/zh-cn/component-code-style.md)
- [组件设计原则](https://github.com/react-component/react-component.github.io/blob/master/docs/zh-cn/component-design.md)
- [网站和组件开发说明](https://github.com/ant-design/ant-design/wiki/%E7%BD%91%E7%AB%99%E5%92%8C%E7%BB%84%E4%BB%B6%E5%BC%80%E5%8F%91%E8%AF%B4%E6%98%8E)
- [版本发布手册](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B)
- [社区贡献脚手架和范例](https://github.com/ant-design/ant-design/issues/129)
- [常见问题](https://github.com/ant-design/ant-design/wiki/FAQ)
- [CodePen 模板](http://codepen.io/benjycui/pen/KgPZrE?editors=001)
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
- [定制主题](https://ant.design/docs/react/customize-theme-cn)
- [成为社区协作成员](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator)
## ⌨️ 本地开发
## 如何贡献
你可以使用 Gitpod 进行在线开发:
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design)
或者克隆到本地开发:
```bash
$ git clone git@github.com:ant-design/ant-design.git
$ cd ant-design
$ npm install
$ npm start
```
打开浏览器访问 http://127.0.0.1:8001 ,更多[本地开发文档](https://github.com/ant-design/ant-design/wiki/Development)。
## 🤝 参与共建 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
请参考[贡献指南](https://ant.design/docs/react/contributing-cn).
> 强烈推荐阅读 [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way)、[《如何向开源社区提问题》](https://github.com/seajs/seajs/issues/545) 和 [《如何有效地报告 Bug》](http://www.chiark.greenend.org.uk/%7Esgtatham/bugs-cn.html)、[《如何向开源项目提交无法解答的问题》](https://zhuanlan.zhihu.com/p/25795393),更好的问题更容易获得帮助。
[![Let's fund issues in this repository](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884)
## 👥 社区互助
如果您在使用的过程中碰到问题,可以通过下面几个途径寻求帮助,同时我们也鼓励资深用户通过下面的途径给新人提供帮助。
通过 Stack Overflow 或者 Segment Fault 提问时,建议加上 `antd` 标签。
1. [Stack Overflow](http://stackoverflow.com/questions/tagged/antd)(英文)
2. [Segment Fault](https://segmentfault.com/t/antd)(中文)
3. [![Join the chat at https://gitter.im/ant-design/ant-design](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## ❤️ 赞助者 ![](https://opencollective.com/ant-design/tiers/backers/badge.svg?label=Backers&color=brightgreen) ![](https://opencollective.com/ant-design/tiers/sponsors/badge.svg?label=Sponsors&color=brightgreen)
[![](https://opencollective.com/ant-design/tiers/backers.svg?avatarHeight=36)](https://opencollective.com/ant-design#support)
[![](https://opencollective.com/ant-design/tiers/sponsors.svg?avatarHeight=36)](https://opencollective.com/ant-design#support)
我们欢迎任何形式的贡献,有任何建议或意见您可以进行 [Pull Request](https://github.com/ant-design/ant-design/pulls),或者给我们 [提问](https://github.com/ant-design/ant-design/issues)。

209
README.md
View File

@@ -1,166 +1,111 @@
<p align="center">
<a href="https://ant.design">
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
<a href="http://ant.design">
<img width="320" src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg">
</a>
</p>
<h1 align="center">Ant Design</h1>
# Ant Design
[![](https://img.shields.io/travis/ant-design/ant-design.svg?style=flat-square)](https://travis-ci.org/ant-design/ant-design)
[![npm package](https://img.shields.io/npm/v/antd.svg?style=flat-square)](https://www.npmjs.org/package/antd)
[![NPM downloads](http://img.shields.io/npm/dm/antd.svg?style=flat-square)](https://npmjs.org/package/antd)
[![CDNJS](https://img.shields.io/cdnjs/v/antd.svg?style=flat-square)](https://cdnjs.com/libraries/antd)
[![Dependency Status](https://david-dm.org/ant-design/ant-design.svg?style=flat-square)](https://david-dm.org/ant-design/ant-design)
[![Join the chat at https://gitter.im/ant-design/ant-design](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<div align="center">
An enterprise-class UI design language and React-based implementation.
An enterprise-class UI design language and React UI library.
## Features
[![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]
- An enterprise-class design language and high quality UI.
- Graceful UI components out of the box, base on [React Component](http://react-component.github.io/badgeboard/).
- Writen in TypeScript with complete define types.
- A npm + webpack + babel + [dora](https://github.com/dora-js/dora) + [dva](https://github.com/dvajs/dva) development framework.
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![FOSSA Status][fossa-image]][fossa-url] [![Issues need help][help-wanted-image]][help-wanted-url]
[![Follow Twitter][twitter-image]][twitter-url] [![Gitter][gitter-english-image]][gitter-english-url] [![Gitter][gitter-chinese-image]][gitter-chinese-url] [![[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/circleci/build/github/ant-design/ant-design/master?style=flat-square
[circleci-url]: https://circleci.com/gh/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
[semver-stability-image]: https://api.dependabot.com/badges/compatibility_score?dependency-name=antd&package-manager=npm_and_yarn&version-scheme=semver
</div>
[![](https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*Yl83RJhUE7kAAAAAAAAAAABkARQnAQ)](https://ant.design)
English | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md)
## ✨ Features
- 🌈 Enterprise-class UI designed for web applications.
- 📦 A set of high-quality React components out of the box.
- 🛡 Written in TypeScript with predictable static types.
- ⚙️ Whole package of design resources and development tools.
- 🌍 Internationalization support for dozens of languages.
- 🎨 Powerful theme customization in every detail.
## 🖥 Environment Support
- 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/)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| --- | --- | --- | --- | --- |
| IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 📦 Install
## Install
```bash
npm install antd
```
```bash
yarn add antd
```
## Usage
## 🔨 Usage
### Use prebuilt bundle
```jsx
import { Button, DatePicker } from 'antd';
const App = () => (
<>
<Button type="primary">PRESS ME</Button>
<DatePicker placeholder="select date" />
</>
);
import { DatePicker } from 'antd';
ReactDOM.render(<DatePicker />, mountNode);
```
And import style manually:
```jsx
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
```
### TypeScript
### Use modularized antd
`antd` is written in TypeScript with complete definitions, check [Use in TypeScript](https://ant.design/docs/react/use-in-typescript) to getting started.
- Use [babel-plugin-import](https://github.com/ant-design/babel-plugin-import) (Recommended)
## 🌍 Internationalization
```js
// .babelrc
{
"plugins": [["import", { libraryName: "antd", style: "css" }]]
}
```
Dozens of languages supported in `antd`, see [i18n](https://ant.design/docs/react/i18n).
Then you can import components from antd directly.
## 🔗 Links
```jsx
// import js and css modularly, parsed by babel-plugin-import
import { DatePicker } from 'antd';
```
- [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/)
- Manually import
```jsx
import DatePicker from 'antd/lib/date-picker'; // just for js
import 'antd/lib/date-picker/style/css'; // with style
```
## Browser Support
Normal browsers and Internet Explorer 9+.
> [IE8 issues](https://github.com/xcatliu/react-ie8)
## TypeScript
tsconfig.json
```
{
"compilerOptions": {
"moduleResolution": "node",
"jsx": "preserve",
"allowSyntheticDefaultImports": true
}
}
```
## Links
- [Home page](http://ant.design/)
- [UI library](http://ant.design/docs/react/introduce)
- [ChangeLog](CHANGELOG.en-US.md)
- [Scaffold tool](https://github.com/ant-design/antd-init/)
- [Development tool](http://ant-tool.github.io/)
- [React components](http://react-component.github.io/)
- [Mobile UI](http://mobile.ant.design)
- [Ant Design Icons](https://github.com/ant-design/ant-design-icons)
- [Ant Design Colors](https://github.com/ant-design/ant-design-colors)
- [Ant Design Pro Layout](https://github.com/ant-design/ant-design-pro-layout)
- [Ant Design Pro Blocks](https://github.com/ant-design/pro-blocks)
- [Dark Theme](https://github.com/ant-design/ant-design-dark-theme)
- [Landing Pages](https://landing.ant.design)
- [Motion](https://motion.ant.design)
- [Scaffold Market](http://scaffold.ant.design)
- [React style guide](https://github.com/react-component/react-component.github.io/blob/master/docs/zh-cn/component-code-style.md)
- [React component design guide](https://github.com/react-component/react-component.github.io/blob/master/docs/zh-cn/component-design.md)
- [Developer Instruction](https://github.com/ant-design/ant-design/wiki/Development)
- [Versioning Release Note](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B)
- [FAQ](https://ant.design/docs/react/faq)
- [CodeSandbox Template](https://u.ant.design/codesandbox-repro) for bug reports
- [Boilerplates](https://github.com/ant-design/ant-design/issues/129)
- [FAQ](https://github.com/ant-design/ant-design/wiki/FAQ)
- [CodePen boilerplate](http://codepen.io/benjycui/pen/KgPZrE?editors=001) for bug reports
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
- [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
## Contributing
Use Gitpod, a free online dev environment for GitHub.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design)
Or clone locally:
```bash
$ git clone git@github.com:ant-design/ant-design.git
$ cd ant-design
$ npm install
$ npm start
```
Open your browser and visit http://127.0.0.1:8001 , see more at [Development](https://github.com/ant-design/ant-design/wiki/Development).
## 🤝 Contributing [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
Read our [contributing guide](https://ant.design/docs/react/contributing) and let's build a better antd together.
We welcome all contributions. Please read our [CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) first. You can submit any ideas as [pull requests](https://github.com/ant-design/ant-design/pulls) or as [GitHub issues](https://github.com/ant-design/ant-design/issues). If you'd like to improve code, check out the [Development Instructions](https://github.com/ant-design/ant-design/wiki/Development) and have a good time! :)
If you are a collaborator, please follow our [Pull Request principle](https://github.com/ant-design/ant-design/wiki/PR-principle) to create a Pull Request by [collaborator template](https://github.com/ant-design/ant-design/compare?expand=1&template=collaborator.md).
[![Let's fund issues in this repository](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884)
## ❤️ Sponsors and Backers [![](https://opencollective.com/ant-design/tiers/sponsors/badge.svg?label=Sponsors&color=brightgreen)](https://opencollective.com/ant-design#support) [![](https://opencollective.com/ant-design/tiers/backers/badge.svg?label=Backers&color=brightgreen)](https://opencollective.com/ant-design#support)
[![](https://opencollective.com/ant-design/tiers/sponsors.svg?avatarHeight=36)](https://opencollective.com/ant-design#support)
[![](https://opencollective.com/ant-design/tiers/backers.svg?avatarHeight=36)](https://opencollective.com/ant-design#support)
We welcome all contributions, please read our [CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) first. You can submit any ideas as [pull requests](https://github.com/ant-design/ant-design/pulls) or as a [GitHub issue](https://github.com/ant-design/ant-design/issues). If you'd like to improve code, check out the [Development Instruction](https://github.com/ant-design/ant-design/wiki/Development) and have a good time! :)

View File

@@ -1,16 +0,0 @@
# Security Policy
## Supported Versions
Use this section to tell people about which versions of your project are currently being supported with security updates.
| Version | Supported |
| ------- | ------------------ |
| 4.x | :white_check_mark: |
| < 4.0 | :x: |
## Reporting a Vulnerability
Use this section to tell people how to report a vulnerability.
Tell them where to go, how often they can expect to get an update on a reported vulnerability, what to expect if the vulnerability is accepted or declined, etc.

View File

@@ -1,62 +0,0 @@
name: Ant Design
trigger: none
pr:
autoCancel: true
branches:
exclude:
- gh-pages
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: site
condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
jobs:
- job: Build_Site
steps:
- checkout: self
displayName: 'Checkout'
clean: true
fetchDepth: 1
- task: NodeTool@0
displayName: 'Install Node.js'
inputs:
versionSpec: '14.7.0'
- script: npm install
displayName: 'Install modules'
- script: |
node ./scripts/azure-github-comment.js "[![Prepare preview](https://user-images.githubusercontent.com/5378891/72351368-2c979e00-371b-11ea-9652-eb4e825d745e.gif)](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: '14.7.0'
- 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'

View File

@@ -1,71 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`antd exports modules correctly 1`] = `
Array [
"Affix",
"Anchor",
"AutoComplete",
"Alert",
"Avatar",
"BackTop",
"Badge",
"Breadcrumb",
"Button",
"Calendar",
"Card",
"Collapse",
"Carousel",
"Cascader",
"Checkbox",
"Col",
"Comment",
"ConfigProvider",
"DatePicker",
"Descriptions",
"Divider",
"Dropdown",
"Drawer",
"Empty",
"Form",
"Grid",
"Input",
"Image",
"InputNumber",
"Layout",
"List",
"message",
"Menu",
"Mentions",
"Modal",
"Statistic",
"notification",
"PageHeader",
"Pagination",
"Popconfirm",
"Popover",
"Progress",
"Radio",
"Rate",
"Result",
"Row",
"Select",
"Skeleton",
"Slider",
"Space",
"Spin",
"Steps",
"Switch",
"Table",
"Transfer",
"Tree",
"TreeSelect",
"Tabs",
"Tag",
"TimePicker",
"Timeline",
"Tooltip",
"Typography",
"Upload",
"version",
]
`;

View File

@@ -1,21 +0,0 @@
const OLD_NODE_ENV = process.env.NODE_ENV;
process.env.NODE_ENV = 'development';
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
const antd = require('..');
describe('antd', () => {
afterAll(() => {
process.env.NODE_ENV = OLD_NODE_ENV;
});
it('exports modules correctly', () => {
expect(Object.keys(antd)).toMatchSnapshot();
});
it('should hint when import all components in dev mode', () => {
expect(warnSpy).toHaveBeenCalledWith(
'You are using a whole package of antd, please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size.',
);
warnSpy.mockRestore();
});
});

View File

@@ -1,13 +0,0 @@
import { easeInOutCubic } from '../easings';
describe('Test easings', () => {
it('easeInOutCubic return value', () => {
const nums = [];
// eslint-disable-next-line no-plusplus
for (let index = 0; index < 5; index++) {
nums.push(easeInOutCubic(index, 1, 5, 4));
}
expect(nums).toEqual([1, 1.25, 3, 4.75, 5]);
});
});

View File

@@ -1,57 +0,0 @@
import getScroll from '../getScroll';
describe('getScroll', () => {
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();
});
});

View File

@@ -1,11 +0,0 @@
/**
* @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);
});
});

View File

@@ -1,14 +0,0 @@
import ResponsiveObserve, { responsiveMap } from '../responsiveObserve';
describe('Test ResponsiveObserve', () => {
it('test ResponsiveObserve subscribe and unsubscribe', () => {
const { xs } = responsiveMap;
const subscribeFunc = jest.fn();
const token = ResponsiveObserve.subscribe(subscribeFunc);
expect(ResponsiveObserve.matchHandlers[xs].mql.matches).toBeTruthy();
expect(subscribeFunc).toBeCalledTimes(1);
ResponsiveObserve.unsubscribe(token);
expect(ResponsiveObserve.matchHandlers[xs].mql.removeListener).toBeCalled();
});
});

View File

@@ -1,66 +0,0 @@
import scrollTo from '../scrollTo';
import { sleep } from '../../../tests/utils';
describe('Test ScrollTo function', () => {
let dateNowMock;
beforeEach(() => {
dateNowMock = jest
.spyOn(Date, 'now')
.mockImplementationOnce(() => 0)
.mockImplementationOnce(() => 1000);
});
afterEach(() => {
dateNowMock.mockRestore();
});
it('test scrollTo', async () => {
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
window.scrollY = y;
window.pageYOffset = y;
});
scrollTo(1000);
await sleep(20);
expect(window.pageYOffset).toBe(1000);
scrollToSpy.mockRestore();
});
it('test callback - option', async () => {
const cbMock = jest.fn();
scrollTo(1000, {
callback: cbMock,
});
await sleep(20);
expect(cbMock).toHaveBeenCalledTimes(1);
});
it('test getContainer - option', async () => {
const div = document.createElement('div');
scrollTo(1000, {
getContainer: () => div,
});
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);
});
});

View File

@@ -1,12 +0,0 @@
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' }),
);
});
});

View File

@@ -1,8 +0,0 @@
import UnreachableException from '../unreachableException';
describe('UnreachableException', () => {
it('error thrown matches snapshot', () => {
const exception = new UnreachableException('some value');
expect(exception.message).toMatchInlineSnapshot(`"unreachable case: \\"some value\\""`);
});
});

View File

@@ -1,26 +0,0 @@
import React from 'react';
import { mount } from 'enzyme';
import useSyncState from '../hooks/useSyncState';
describe('Table', () => {
it('useSyncState', () => {
const Test = () => {
const [getVal, setVal] = useSyncState('light');
return (
<span
onClick={() => {
setVal('bamboo');
}}
>
{getVal()}
</span>
);
};
const wrapper = mount(<Test />);
expect(wrapper.text()).toEqual('light');
wrapper.find('span').simulate('click');
expect(wrapper.text()).toEqual('bamboo');
});
});

View File

@@ -1,231 +0,0 @@
import raf from 'raf';
import React from 'react';
import { mount } from 'enzyme';
import KeyCode from 'rc-util/lib/KeyCode';
import delayRaf from '../raf';
import {
throttleByAnimationFrame,
throttleByAnimationFrameDecorator,
} from '../throttleByAnimationFrame';
import getDataOrAriaProps from '../getDataOrAriaProps';
import Wave from '../wave';
import TransButton from '../transButton';
import { isStyleSupport, isFlexSupported } from '../styleChecker';
import { sleep } from '../../../tests/utils';
import focusTest from '../../../tests/shared/focusTest';
describe('Test utils function', () => {
focusTest(TransButton);
describe('throttle', () => {
it('throttle function should work', async () => {
const callback = jest.fn();
const throttled = throttleByAnimationFrame(callback);
expect(callback).not.toHaveBeenCalled();
throttled();
throttled();
await sleep(20);
expect(callback).toHaveBeenCalled();
expect(callback.mock.calls.length).toBe(1);
});
it('throttle function should be canceled', async () => {
const callback = jest.fn();
const throttled = throttleByAnimationFrame(callback);
throttled();
throttled.cancel();
await sleep(20);
expect(callback).not.toHaveBeenCalled();
});
it('throttleByAnimationFrameDecorator should works', async () => {
const callbackFn = jest.fn();
class Test {
@throttleByAnimationFrameDecorator()
// eslint-disable-next-line class-methods-use-this
callback() {
callbackFn();
}
}
const test = new Test();
test.callback();
test.callback();
test.callback();
await sleep(30);
expect(callbackFn).toHaveBeenCalledTimes(1);
});
});
describe('getDataOrAriaProps', () => {
it('returns all data-* properties from an object', () => {
const props = {
onClick: () => {},
isOpen: true,
'data-test': 'test-id',
'data-id': 1234,
};
const results = getDataOrAriaProps(props);
expect(results).toEqual({
'data-test': 'test-id',
'data-id': 1234,
});
});
it('does not return data-__ properties from an object', () => {
const props = {
onClick: () => {},
isOpen: true,
'data-__test': 'test-id',
'data-__id': 1234,
};
const results = getDataOrAriaProps(props);
expect(results).toEqual({});
});
it('returns all aria-* properties from an object', () => {
const props = {
onClick: () => {},
isOpen: true,
'aria-labelledby': 'label-id',
'aria-label': 'some-label',
};
const results = getDataOrAriaProps(props);
expect(results).toEqual({
'aria-labelledby': 'label-id',
'aria-label': 'some-label',
});
});
it('returns role property from an object', () => {
const props = {
onClick: () => {},
isOpen: true,
role: 'search',
};
const results = getDataOrAriaProps(props);
expect(results).toEqual({ role: 'search' });
});
});
it('delayRaf', done => {
jest.useRealTimers();
let bamboo = false;
delayRaf(() => {
bamboo = true;
}, 3);
// Do nothing, but insert in the frame
// https://github.com/ant-design/ant-design/issues/16290
delayRaf(() => {}, 3);
// Variable bamboo should be false in frame 2 but true in frame 4
raf(() => {
expect(bamboo).toBe(false);
// Frame 2
raf(() => {
expect(bamboo).toBe(false);
// Frame 3
raf(() => {
// Frame 4
raf(() => {
expect(bamboo).toBe(true);
done();
});
});
});
});
});
describe('wave', () => {
it('bindAnimationEvent should return when node is null', () => {
const wrapper = mount(
<Wave>
<button type="button" disabled>
button
</button>
</Wave>,
).instance();
expect(wrapper.bindAnimationEvent()).toBe(undefined);
});
it('bindAnimationEvent.onClick should return when children is hidden', () => {
const wrapper = mount(
<Wave>
<button type="button" style={{ display: 'none' }}>
button
</button>
</Wave>,
).instance();
expect(wrapper.bindAnimationEvent()).toBe(undefined);
});
it('bindAnimationEvent.onClick should return when children is input', () => {
const wrapper = mount(
<Wave>
<input />
</Wave>,
).instance();
expect(wrapper.bindAnimationEvent()).toBe(undefined);
});
it('should not throw when click it', () => {
expect(() => {
const wrapper = mount(
<Wave>
<div />
</Wave>,
);
wrapper.simulate('click');
}).not.toThrow();
});
it('should not throw when no children', () => {
expect(() => mount(<Wave />)).not.toThrow();
});
});
describe('TransButton', () => {
it('can be focus/blur', () => {
const wrapper = mount(<TransButton>TransButton</TransButton>);
expect(typeof wrapper.instance().focus).toBe('function');
expect(typeof wrapper.instance().blur).toBe('function');
});
it('should trigger onClick when press enter', () => {
const onClick = jest.fn();
const preventDefault = jest.fn();
const wrapper = mount(<TransButton onClick={onClick}>TransButton</TransButton>);
wrapper.simulate('keyUp', { keyCode: KeyCode.ENTER });
expect(onClick).toHaveBeenCalled();
wrapper.simulate('keyDown', { keyCode: KeyCode.ENTER, preventDefault });
expect(preventDefault).toHaveBeenCalled();
});
});
describe('style', () => {
it('isFlexSupported', () => {
expect(isFlexSupported).toBe(true);
});
it('isStyleSupport', () => {
expect(isStyleSupport('color')).toBe(true);
expect(isStyleSupport('not-existed')).toBe(false);
});
it('isStyleSupport return false in service side', () => {
const spy = jest
.spyOn(window.document, 'documentElement', 'get')
.mockImplementation(() => undefined);
expect(isStyleSupport('color')).toBe(false);
expect(isStyleSupport('not-existed')).toBe(false);
spy.mockRestore();
});
});
});

View File

@@ -1,151 +0,0 @@
import React from 'react';
import { mount } from 'enzyme';
import Wave from '../wave';
import ConfigProvider from '../../config-provider';
import mountTest from '../../../tests/shared/mountTest';
import { sleep } from '../../../tests/utils';
describe('Wave component', () => {
mountTest(Wave);
afterEach(() => {
const styles = document.getElementsByTagName('style');
for (let i = 0; i < styles.length; i += 1) {
styles[i].remove();
}
});
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>,
);
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);
wrapper.unmount();
process.env.NODE_ENV = TEST_NODE_ENV;
});
it('isHidden is mocked', () => {
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');
wrapper.unmount();
});
it('wave color is grey', async () => {
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');
expect(styles.length).toBe(0);
wrapper.unmount();
});
it('wave color is not grey', async () => {
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');
expect(styles.length).toBe(1);
expect(styles[0].innerHTML).toContain('--antd-wave-shadow-color: red;');
wrapper.unmount();
});
it('read wave color from border-top-color', async () => {
const wrapper = mount(
<Wave>
<div style={{ borderTopColor: 'blue' }}>button</div>
</Wave>,
);
wrapper.find('div').getDOMNode().click();
await sleep(0);
const styles = document.getElementsByTagName('style');
expect(styles.length).toBe(1);
expect(styles[0].innerHTML).toContain('--antd-wave-shadow-color: blue;');
wrapper.unmount();
});
it('read wave color from background color', async () => {
const wrapper = mount(
<Wave>
<div style={{ backgroundColor: 'green' }}>button</div>
</Wave>,
);
wrapper.find('div').getDOMNode().click();
await sleep(0);
const styles = document.getElementsByTagName('style');
expect(styles.length).toBe(1);
expect(styles[0].innerHTML).toContain('--antd-wave-shadow-color: green;');
wrapper.unmount();
});
it('read wave color from border firstly', async () => {
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');
expect(styles.length).toBe(1);
expect(styles[0].innerHTML).toContain('--antd-wave-shadow-color: yellow;');
wrapper.unmount();
});
it('hidden element with -leave className', async () => {
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');
expect(styles.length).toBe(0);
wrapper.unmount();
});
it('ConfigProvider csp', async () => {
const wrapper = mount(
<ConfigProvider csp={{ nonce: 'YourNonceCode' }}>
<Wave>
<button type="button">button</button>
</Wave>
</ConfigProvider>,
);
wrapper.find('button').getDOMNode().click();
await sleep(0);
const styles = document.getElementsByTagName('style');
expect(styles[0].getAttribute('nonce')).toBe('YourNonceCode');
wrapper.unmount();
});
});

View File

@@ -1,22 +0,0 @@
import { ElementOf, tuple } from './type';
export const PresetStatusColorTypes = tuple('success', 'processing', 'error', 'default', 'warning');
// eslint-disable-next-line import/prefer-default-export
export const PresetColorTypes = tuple(
'pink',
'red',
'yellow',
'orange',
'cyan',
'green',
'blue',
'purple',
'geekblue',
'magenta',
'volcano',
'gold',
'lime',
);
export type PresetColorType = ElementOf<typeof PresetColorTypes>;
export type PresetStatusColorType = ElementOf<typeof PresetStatusColorTypes>;

View File

@@ -1,7 +0,0 @@
import devWarning, { resetWarned } from 'rc-util/lib/warning';
export { resetWarned };
export default (valid: boolean, component: string, message: string): void => {
devWarning(valid, `[antd: ${component}] ${message}`);
};

View File

@@ -1,10 +0,0 @@
// eslint-disable-next-line import/prefer-default-export
export function easeInOutCubic(t: number, b: number, c: number, d: number) {
const cc = c - b;
t /= d / 2;
if (t < 1) {
return (cc / 2) * t * t * t + b;
}
// eslint-disable-next-line no-return-assign
return (cc / 2) * ((t -= 2) * t * t + 2) + b;
}

View File

@@ -1,11 +0,0 @@
export default function getDataOrAriaProps(props: any) {
return Object.keys(props).reduce((prev: any, key: string) => {
if (
(key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-' || key === 'role') &&
key.substr(0, 7) !== 'data-__'
) {
prev[key] = props[key];
}
return prev;
}, {});
}

View File

@@ -0,0 +1,10 @@
import assign from 'object-assign';
export default function getLocale(props, context, componentName, getDefaultLocale) {
const locale = context && context.antLocale && context.antLocale[componentName] ?
context.antLocale[componentName] : getDefaultLocale();
const result = assign({}, locale, props.locale);
result.lang = assign({}, locale.lang, props.locale.lang);
return result;
}

View File

@@ -1,18 +0,0 @@
import * as React from 'react';
export type RenderFunction = () => React.ReactNode;
export const getRenderPropValue = (
propValue?: React.ReactNode | RenderFunction,
): React.ReactNode => {
if (!propValue) {
return null;
}
const isRenderFunction = typeof propValue === 'function';
if (isRenderFunction) {
return (propValue as RenderFunction)();
}
return propValue;
};

View File

@@ -0,0 +1,12 @@
export default function getRequestAnimationFrame() {
if (typeof window === 'undefined') {
return () => {};
}
if (window.requestAnimationFrame) {
return window.requestAnimationFrame;
}
const prefix = ['moz', 'ms', 'webkit'].filter(key => `${key}RequestAnimationFrame` in window)[0];
return prefix
? window[`${prefix}RequestAnimationFrame`]
: callback => setTimeout(callback, 1000 / 60);
}

View File

@@ -1,27 +1,17 @@
export function isWindow(obj: any) {
return obj !== null && obj !== undefined && obj === obj.window;
}
export default function getScroll(
target: HTMLElement | Window | Document | null,
top: boolean,
): number {
export default function getScroll(target, top): number {
if (typeof window === 'undefined') {
return 0;
}
const prop = top ? 'pageYOffset' : 'pageXOffset';
const method = top ? 'scrollTop' : 'scrollLeft';
let result = 0;
if (isWindow(target)) {
result = (target as Window)[top ? 'pageYOffset' : 'pageXOffset'];
} else if (target instanceof Document) {
result = target.documentElement[method];
} else if (target) {
result = (target as HTMLElement)[method];
const isWindow = target === window;
let ret = isWindow ? target[prop] : target[method];
// ie6,7,8 standard mode
if (isWindow && typeof ret !== 'number') {
ret = window.document.documentElement[method];
}
if (target && !isWindow(target) && typeof result !== 'number') {
result = ((target as HTMLElement).ownerDocument || (target as Document)).documentElement[
method
];
}
return result;
return ret;
}

View File

@@ -1,19 +0,0 @@
import * as React from 'react';
import { fillRef } from '../ref';
function useCombinedRefs<T>(
...refs: Array<React.MutableRefObject<T> | ((instance: T) => void) | null>
) {
const targetRef = React.useRef<T>();
React.useEffect(() => {
refs.forEach(ref => {
if (!ref) return;
fillRef(ref, targetRef.current);
});
}, [refs]);
return targetRef;
}
export default useCombinedRefs;

View File

@@ -1,6 +0,0 @@
import * as React from 'react';
export default function useForceUpdate() {
const [, forceUpdate] = React.useReducer(x => x + 1, 0);
return forceUpdate;
}

View File

@@ -1,21 +0,0 @@
import * as React from 'react';
export default function usePatchElement(): [
React.ReactElement[],
(element: React.ReactElement) => Function,
] {
const [elements, setElements] = React.useState<React.ReactElement[]>([]);
function patchElement(element: React.ReactElement) {
// append a new element to elements (and create a new ref)
setElements(originElements => [...originElements, element]);
// return a function that removes the new element out of elements (and create a new ref)
// it works a little like useEffect
return () => {
setElements(originElements => originElements.filter(ele => ele !== element));
};
}
return [elements, patchElement];
}

View File

@@ -1,18 +0,0 @@
import * as React from 'react';
import useForceUpdate from './useForceUpdate';
type UseSyncStateProps<T> = [() => T, (newValue: T) => void];
export default function useSyncState<T>(initialValue: T): UseSyncStateProps<T> {
const ref = React.useRef<T>(initialValue);
const forceUpdate = useForceUpdate();
return [
() => ref.current,
(newValue: T) => {
ref.current = newValue;
// re-render
forceUpdate();
},
];
}

View File

@@ -0,0 +1,24 @@
let animation;
function isCssAnimationSupported() {
if (animation !== undefined) {
return animation;
}
const domPrefixes = 'Webkit Moz O ms Khtml'.split(' ');
const elm = document.createElement('div');
if (elm.style.animationName !== undefined) {
animation = true;
}
if (animation !== undefined) {
for (let i = 0; i < domPrefixes.length; i++) {
if (elm.style[`${domPrefixes[i]}AnimationName`] !== undefined) {
animation = true;
break;
}
}
}
animation = animation || false;
return animation;
}
export default isCssAnimationSupported;

View File

@@ -1,5 +0,0 @@
const isNumeric = (value: any): boolean => {
return !isNaN(parseFloat(value)) && isFinite(value);
};
export default isNumeric;

View File

@@ -1,24 +0,0 @@
import { CSSMotionProps, MotionEventHandler, MotionEndEventHandler } from 'rc-motion';
// ================== Collapse Motion ==================
const getCollapsedHeight: MotionEventHandler = () => ({ height: 0, opacity: 0 });
const getRealHeight: MotionEventHandler = node => ({ height: node.scrollHeight, opacity: 1 });
const getCurrentHeight: MotionEventHandler = node => ({ height: node.offsetHeight });
const skipOpacityTransition: MotionEndEventHandler = (_, event) =>
(event as TransitionEvent).propertyName === 'height';
const collapseMotion: CSSMotionProps = {
motionName: 'ant-motion-collapse',
onAppearStart: getCollapsedHeight,
onEnterStart: getCollapsedHeight,
onAppearActive: getRealHeight,
onEnterActive: getRealHeight,
onLeaveStart: getCurrentHeight,
onLeaveActive: getCollapsedHeight,
onAppearEnd: skipOpacityTransition,
onEnterEnd: skipOpacityTransition,
onLeaveEnd: skipOpacityTransition,
motionDeadline: 500,
};
export default collapseMotion;

View File

@@ -0,0 +1,36 @@
import cssAnimation from 'css-animation';
function animate(node, show, done) {
let height;
return cssAnimation(node, 'ant-motion-collapse', {
start() {
if (!show) {
node.style.height = `${node.offsetHeight}px`;
} else {
height = node.offsetHeight;
node.style.height = 0;
}
},
active() {
node.style.height = `${show ? height : 0}px`;
},
end() {
node.style.height = '';
done();
},
});
}
const animation = {
enter(node, done) {
return animate(node, true, done);
},
leave(node, done) {
return animate(node, false, done);
},
appear(node, done) {
return animate(node, true, done);
},
};
export default animation;

View File

@@ -1,38 +0,0 @@
import raf from 'raf';
interface RafMap {
[id: number]: number;
}
let id: number = 0;
const ids: RafMap = {};
// Support call raf with delay specified frame
export default function wrapperRaf(callback: () => void, delayFrames: number = 1): number {
const myId: number = id++;
let restFrames: number = delayFrames;
function internalCallback() {
restFrames -= 1;
if (restFrames <= 0) {
callback();
delete ids[myId];
} else {
ids[myId] = raf(internalCallback);
}
}
ids[myId] = raf(internalCallback);
return myId;
}
wrapperRaf.cancel = function cancel(pid?: number) {
if (pid === undefined) return;
raf.cancel(ids[pid]);
delete ids[pid];
};
wrapperRaf.ids = ids; // export this for test usage

View File

@@ -1,17 +0,0 @@
import * as React from 'react';
export const { isValidElement } = React;
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;
}

View File

@@ -1,17 +0,0 @@
import * as React from 'react';
export function fillRef<T>(ref: React.Ref<T>, node: T) {
if (typeof ref === 'function') {
ref(node);
} else if (typeof ref === 'object' && ref && 'current' in ref) {
(ref as any).current = node;
}
}
export function composeRef<T>(...refs: React.Ref<T>[]): React.Ref<T> {
return (node: T) => {
refs.forEach(ref => {
fillRef(ref, node);
});
};
}

View File

@@ -1,74 +0,0 @@
export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
export type BreakpointMap = Record<Breakpoint, string>;
export type ScreenMap = Partial<Record<Breakpoint, boolean>>;
export type ScreenSizeMap = Partial<Record<Breakpoint, number>>;
export const responsiveArray: Breakpoint[] = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
export const responsiveMap: BreakpointMap = {
xs: '(max-width: 575px)',
sm: '(min-width: 576px)',
md: '(min-width: 768px)',
lg: '(min-width: 992px)',
xl: '(min-width: 1200px)',
xxl: '(min-width: 1600px)',
};
type SubscribeFunc = (screens: ScreenMap) => void;
const subscribers = new Map<Number, SubscribeFunc>();
let subUid = -1;
let screens = {};
const responsiveObserve = {
matchHandlers: {} as {
[prop: string]: {
mql: MediaQueryList;
listener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | null;
};
},
dispatch(pointMap: ScreenMap) {
screens = pointMap;
subscribers.forEach(func => func(screens));
return subscribers.size >= 1;
},
subscribe(func: SubscribeFunc): number {
if (!subscribers.size) this.register();
subUid += 1;
subscribers.set(subUid, func);
func(screens);
return subUid;
},
unsubscribe(token: number) {
subscribers.delete(token);
if (!subscribers.size) this.unregister();
},
unregister() {
Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
const matchMediaQuery = responsiveMap[screen];
const handler = this.matchHandlers[matchMediaQuery];
handler?.mql.removeListener(handler?.listener);
});
subscribers.clear();
},
register() {
Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
const matchMediaQuery = responsiveMap[screen];
const listener = ({ matches }: { matches: boolean }) => {
this.dispatch({
...screens,
[screen]: matches,
});
};
const mql = window.matchMedia(matchMediaQuery);
mql.addListener(listener);
this.matchHandlers[matchMediaQuery] = {
mql,
listener,
};
listener(mql);
});
},
};
export default responsiveObserve;

View File

@@ -1,38 +0,0 @@
import raf from 'raf';
import getScroll, { isWindow } from './getScroll';
import { easeInOutCubic } from './easings';
interface ScrollToOptions {
/** Scroll container, default as window */
getContainer?: () => HTMLElement | Window | Document;
/** Scroll end callback */
callback?: () => any;
/** Animation duration, default as 450 */
duration?: number;
}
export default function scrollTo(y: number, options: ScrollToOptions = {}) {
const { getContainer = () => window, callback, duration = 450 } = options;
const container = getContainer();
const scrollTop = getScroll(container, true);
const startTime = Date.now();
const frameFunc = () => {
const timestamp = Date.now();
const time = timestamp - startTime;
const nextScrollTop = easeInOutCubic(time > duration ? duration : time, scrollTop, y, duration);
if (isWindow(container)) {
(container as Window).scrollTo(window.pageXOffset, nextScrollTop);
} else if (container instanceof HTMLDocument || container.constructor.name === 'HTMLDocument') {
(container as HTMLDocument).documentElement.scrollTop = nextScrollTop;
} else {
(container as HTMLElement).scrollTop = nextScrollTop;
}
if (time < duration) {
raf(frameFunc);
} else if (typeof callback === 'function') {
callback();
}
};
raf(frameFunc);
}

View File

@@ -0,0 +1,12 @@
export default function splitObject(obj, parts): Array<any> {
const left = {};
const right = {};
Object.keys(obj).forEach((k) => {
if (parts.indexOf(k) !== -1) {
left[k] = obj[k];
} else {
right[k] = obj[k];
}
});
return [left, right];
}

View File

@@ -1,11 +0,0 @@
export const isStyleSupport = (styleName: string | Array<string>): boolean => {
if (typeof window !== 'undefined' && window.document && window.document.documentElement) {
const styleNameList = Array.isArray(styleName) ? styleName : [styleName];
const { documentElement } = window.document;
return styleNameList.some(name => name in documentElement.style);
}
return false;
};
export const isFlexSupported = isStyleSupport(['flex', 'webkitFlex', 'Flex', 'msFlex']);

View File

@@ -1,50 +0,0 @@
import raf from 'raf';
export function throttleByAnimationFrame(fn: (...args: any[]) => void) {
let requestId: number | null;
const later = (args: any[]) => () => {
requestId = null;
fn(...args);
};
const throttled = (...args: any[]) => {
if (requestId == null) {
requestId = raf(later(args));
}
};
(throttled as any).cancel = () => raf.cancel(requestId!);
return throttled;
}
export function throttleByAnimationFrameDecorator() {
return function throttle(target: any, key: string, descriptor: any) {
const fn = descriptor.value;
let definingProperty = false;
return {
configurable: true,
get() {
// In IE11 calling Object.defineProperty has a side-effect of evaluating the
// getter for the property which is being replaced. This causes infinite
// recursion and an "Out of stack space" error.
// eslint-disable-next-line no-prototype-builtins
if (definingProperty || this === target.prototype || this.hasOwnProperty(key)) {
/* istanbul ignore next */
return fn;
}
const boundFn = throttleByAnimationFrame(fn.bind(this));
definingProperty = true;
Object.defineProperty(this, key, {
value: boundFn,
configurable: true,
writable: true,
});
definingProperty = false;
return boundFn;
},
};
};
}

View File

@@ -1,100 +0,0 @@
/**
* Wrap of sub component which need use as Button capacity (like Icon component).
* This helps accessibility reader to tread as a interactive button to operation.
*/
import * as React from 'react';
import KeyCode from 'rc-util/lib/KeyCode';
interface TransButtonProps extends React.HTMLAttributes<HTMLDivElement> {
onClick?: (e?: React.MouseEvent<HTMLDivElement>) => void;
noStyle?: boolean;
autoFocus?: boolean;
disabled?: boolean;
}
const inlineStyle: React.CSSProperties = {
border: 0,
background: 'transparent',
padding: 0,
lineHeight: 'inherit',
display: 'inline-block',
};
class TransButton extends React.Component<TransButtonProps> {
div?: HTMLDivElement;
lastKeyCode?: number;
componentDidMount() {
const { autoFocus } = this.props;
if (autoFocus) {
this.focus();
}
}
onKeyDown: React.KeyboardEventHandler<HTMLDivElement> = event => {
const { keyCode } = event;
if (keyCode === KeyCode.ENTER) {
event.preventDefault();
}
};
onKeyUp: React.KeyboardEventHandler<HTMLDivElement> = event => {
const { keyCode } = event;
const { onClick } = this.props;
if (keyCode === KeyCode.ENTER && onClick) {
onClick();
}
};
setRef = (btn: HTMLDivElement) => {
this.div = btn;
};
focus() {
if (this.div) {
this.div.focus();
}
}
blur() {
if (this.div) {
this.div.blur();
}
}
render() {
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
role="button"
tabIndex={0}
ref={this.setRef}
{...restProps}
onKeyDown={this.onKeyDown}
onKeyUp={this.onKeyUp}
style={mergedStyle}
/>
);
}
}
export default TransButton;

View File

@@ -1,16 +0,0 @@
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
// https://stackoverflow.com/questions/46176165/ways-to-get-string-literal-type-of-array-values-without-enum-overhead
export const tuple = <T extends string[]>(...args: T) => args;
export const tupleNum = <T extends number[]>(...args: T) => args;
/**
* https://stackoverflow.com/a/59187769
* Extract the type of an element of an array/tuple without performing indexing
*/
export type ElementOf<T> = T extends (infer E)[] ? E : T extends readonly (infer F)[] ? F : never;
/**
* https://github.com/Microsoft/TypeScript/issues/29729
*/
export type LiteralUnion<T extends U, U> = T | (U & {});

View File

@@ -1,5 +0,0 @@
export default class UnreachableException {
constructor(value: never) {
return new Error(`unreachable case: ${JSON.stringify(value)}`);
}
}

View File

@@ -1,214 +0,0 @@
import * as React from 'react';
import TransitionEvents from '@ant-design/css-animation/lib/Event';
import { supportRef, composeRef } from 'rc-util/lib/ref';
import raf from './raf';
import { ConfigConsumer, ConfigConsumerProps, CSPConfig, ConfigContext } from '../config-provider';
import { cloneElement } from './reactNode';
let styleForPseudo: HTMLStyleElement | null;
// Where el is the DOM element you'd like to test for visibility
function isHidden(element: HTMLElement) {
if (process.env.NODE_ENV === 'test') {
return false;
}
return !element || element.offsetParent === null;
}
function isNotGrey(color: string) {
// eslint-disable-next-line no-useless-escape
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\d.]*)?\)/);
if (match && match[1] && match[2] && match[3]) {
return !(match[1] === match[2] && match[2] === match[3]);
}
return true;
}
export default class Wave extends React.Component<{ insertExtraNode?: boolean }> {
static contextType = ConfigContext;
private instance?: {
cancel: () => void;
};
private containerRef = React.createRef<HTMLDivElement>();
private extraNode: HTMLDivElement;
private clickWaveTimeoutId: number;
private animationStartId: number;
private animationStart: boolean = false;
private destroyed: boolean = false;
private csp?: CSPConfig;
context: ConfigConsumerProps;
componentDidMount() {
const node = this.containerRef.current as HTMLDivElement;
if (!node || node.nodeType !== 1) {
return;
}
this.instance = this.bindAnimationEvent(node);
}
componentWillUnmount() {
if (this.instance) {
this.instance.cancel();
}
if (this.clickWaveTimeoutId) {
clearTimeout(this.clickWaveTimeoutId);
}
this.destroyed = true;
}
onClick = (node: HTMLElement, waveColor: string) => {
if (!node || isHidden(node) || node.className.indexOf('-leave') >= 0) {
return;
}
const { insertExtraNode } = this.props;
this.extraNode = document.createElement('div');
const { extraNode } = this;
const { getPrefixCls } = this.context;
extraNode.className = `${getPrefixCls('')}-click-animating-node`;
const attributeName = this.getAttributeName();
node.setAttribute(attributeName, 'true');
// Not white or transparent or grey
styleForPseudo = styleForPseudo || document.createElement('style');
if (
waveColor &&
waveColor !== '#ffffff' &&
waveColor !== 'rgb(255, 255, 255)' &&
isNotGrey(waveColor) &&
!/rgba\((?:\d*, ){3}0\)/.test(waveColor) && // any transparent rgba color
waveColor !== 'transparent'
) {
// Add nonce if CSP exist
if (this.csp && this.csp.nonce) {
styleForPseudo.nonce = this.csp.nonce;
}
extraNode.style.borderColor = waveColor;
styleForPseudo.innerHTML = `
[${getPrefixCls('')}-click-animating-without-extra-node='true']::after, .${getPrefixCls(
'',
)}-click-animating-node {
--antd-wave-shadow-color: ${waveColor};
}`;
if (!document.body.contains(styleForPseudo)) {
document.body.appendChild(styleForPseudo);
}
}
if (insertExtraNode) {
node.appendChild(extraNode);
}
TransitionEvents.addStartEventListener(node, this.onTransitionStart);
TransitionEvents.addEndEventListener(node, this.onTransitionEnd);
};
onTransitionStart = (e: AnimationEvent) => {
if (this.destroyed) {
return;
}
const node = this.containerRef.current as HTMLDivElement;
if (!e || e.target !== node || this.animationStart) {
return;
}
this.resetEffect(node);
};
onTransitionEnd = (e: AnimationEvent) => {
if (!e || e.animationName !== 'fadeEffect') {
return;
}
this.resetEffect(e.target as HTMLElement);
};
getAttributeName() {
const { getPrefixCls } = this.context;
const { insertExtraNode } = this.props;
return insertExtraNode
? `${getPrefixCls('')}-click-animating`
: `${getPrefixCls('')}-click-animating-without-extra-node`;
}
bindAnimationEvent = (node: HTMLElement) => {
if (
!node ||
!node.getAttribute ||
node.getAttribute('disabled') ||
node.className.indexOf('disabled') >= 0
) {
return;
}
const onClick = (e: MouseEvent) => {
// Fix radio button click twice
if ((e.target as HTMLElement).tagName === 'INPUT' || isHidden(e.target as HTMLElement)) {
return;
}
this.resetEffect(node);
// Get wave color from target
const waveColor =
getComputedStyle(node).getPropertyValue('border-top-color') || // Firefox Compatible
getComputedStyle(node).getPropertyValue('border-color') ||
getComputedStyle(node).getPropertyValue('background-color');
this.clickWaveTimeoutId = window.setTimeout(() => this.onClick(node, waveColor), 0);
raf.cancel(this.animationStartId);
this.animationStart = true;
// Render to trigger transition event cost 3 frames. Let's delay 10 frames to reset this.
this.animationStartId = raf(() => {
this.animationStart = false;
}, 10);
};
node.addEventListener('click', onClick, true);
return {
cancel: () => {
node.removeEventListener('click', onClick, true);
},
};
};
resetEffect(node: HTMLElement) {
if (!node || node === this.extraNode || !(node instanceof Element)) {
return;
}
const { insertExtraNode } = this.props;
const attributeName = this.getAttributeName();
node.setAttribute(attributeName, 'false'); // edge has bug on `removeAttribute` #14466
if (styleForPseudo) {
styleForPseudo.innerHTML = '';
}
if (insertExtraNode && this.extraNode && node.contains(this.extraNode)) {
node.removeChild(this.extraNode);
}
TransitionEvents.removeStartEventListener(node, this.onTransitionStart);
TransitionEvents.removeEndEventListener(node, this.onTransitionEnd);
}
renderWave = ({ csp }: ConfigConsumerProps) => {
const { children } = this.props;
this.csp = csp;
if (!React.isValidElement(children)) return children;
let ref: React.Ref<any> = this.containerRef;
if (supportRef(children)) {
ref = composeRef((children as any).ref, this.containerRef as any);
}
return cloneElement(children, { ref });
};
render() {
return <ConfigConsumer>{this.renderWave}</ConfigConsumer>;
}
}

View File

@@ -1,233 +0,0 @@
import React from 'react';
import { mount, ReactWrapper, HTMLAttributes } from 'enzyme';
import ResizeObserverImpl from 'rc-resize-observer';
import Affix, { AffixProps, AffixState } from '..';
import { getObserverEntities } from '../utils';
import Button from '../../button';
import rtlTest from '../../../tests/shared/rtlTest';
import { sleep } from '../../../tests/utils';
const events: Partial<Record<keyof HTMLElementEventMap, (ev: Partial<Event>) => void>> = {};
class AffixMounter extends React.Component<{
offsetBottom?: number;
offsetTop?: number;
onTestUpdatePosition?(): void;
onChange?: () => void;
}> {
private container: HTMLDivElement;
public affix: Affix;
componentDidMount() {
this.container.addEventListener = jest
.fn()
.mockImplementation((event: keyof HTMLElementEventMap, cb: (ev: Partial<Event>) => void) => {
events[event] = cb;
});
}
getTarget = () => this.container;
render() {
return (
<div
ref={node => {
this.container = node!;
}}
className="container"
>
<Affix
className="fixed"
target={this.getTarget}
ref={ele => {
this.affix = ele!;
}}
{...this.props}
>
<Button type="primary">Fixed at the top of container</Button>
</Affix>
</div>
);
}
}
describe('Affix Render', () => {
rtlTest(Affix);
const domMock = jest.spyOn(HTMLElement.prototype, 'getBoundingClientRect');
let affixMounterWrapper: ReactWrapper<unknown, unknown, AffixMounter>;
let affixWrapper: ReactWrapper<AffixProps, AffixState, Affix>;
const classRect: Record<string, DOMRect> = {
container: {
top: 0,
bottom: 100,
} as DOMRect,
};
beforeAll(() => {
domMock.mockImplementation(function fn(this: HTMLElement) {
return (
classRect[this.className] || {
top: 0,
bottom: 0,
}
);
});
});
afterAll(() => {
domMock.mockRestore();
});
const movePlaceholder = async (top: number) => {
classRect.fixed = {
top,
bottom: top,
} as DOMRect;
if (events.scroll == null) {
throw new Error('scroll should be set');
}
events.scroll({
type: 'scroll',
});
await sleep(20);
};
it('Anchor render perfectly', async () => {
document.body.innerHTML = '<div id="mounter" />';
affixMounterWrapper = mount(<AffixMounter />, { attachTo: document.getElementById('mounter') });
await sleep(20);
await movePlaceholder(0);
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeFalsy();
await movePlaceholder(-100);
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
await movePlaceholder(0);
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeFalsy();
});
it('support offsetBottom', async () => {
document.body.innerHTML = '<div id="mounter" />';
affixMounterWrapper = mount(<AffixMounter offsetBottom={0} />, {
attachTo: document.getElementById('mounter'),
});
await sleep(20);
await movePlaceholder(300);
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
await movePlaceholder(0);
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeFalsy();
await movePlaceholder(300);
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
});
it('updatePosition when offsetTop changed', async () => {
document.body.innerHTML = '<div id="mounter" />';
const onChange = jest.fn();
affixMounterWrapper = mount(<AffixMounter offsetTop={0} onChange={onChange} />, {
attachTo: document.getElementById('mounter'),
});
await sleep(20);
await movePlaceholder(-100);
expect(onChange).toHaveBeenLastCalledWith(true);
expect(affixMounterWrapper.instance().affix.state.affixStyle?.top).toBe(0);
affixMounterWrapper.setProps({
offsetTop: 10,
});
await sleep(20);
expect(affixMounterWrapper.instance().affix.state.affixStyle?.top).toBe(10);
});
describe('updatePosition when target changed', () => {
it('function change', () => {
document.body.innerHTML = '<div id="mounter" />';
const container = document.querySelector('#id') as HTMLDivElement;
const getTarget = () => container;
affixWrapper = mount(<Affix target={getTarget}>{null}</Affix>);
affixWrapper.setProps({ target: () => null });
expect(affixWrapper.instance().state.status).toBe(0);
expect(affixWrapper.instance().state.affixStyle).toBe(undefined);
expect(affixWrapper.instance().state.placeholderStyle).toBe(undefined);
});
it('instance change', async () => {
const getObserverLength = () => Object.keys(getObserverEntities()).length;
const container = document.createElement('div');
document.body.appendChild(container);
let target: HTMLDivElement | null = container;
const originLength = getObserverLength();
const getTarget = () => target;
affixWrapper = mount(<Affix target={getTarget}>{null}</Affix>);
await sleep(50);
expect(getObserverLength()).toBe(originLength + 1);
target = null;
affixWrapper.setProps({});
affixWrapper.update();
await sleep(50);
expect(getObserverLength()).toBe(originLength);
});
});
describe('updatePosition when size changed', () => {
it.each([
{ name: 'inner', index: 0 },
{ name: 'outer', index: 1 },
])('inner or outer', async ({ index }) => {
document.body.innerHTML = '<div id="mounter" />';
const updateCalled = jest.fn();
affixMounterWrapper = mount(
<AffixMounter offsetBottom={0} onTestUpdatePosition={updateCalled} />,
{
attachTo: document.getElementById('mounter'),
},
);
await sleep(20);
await movePlaceholder(300);
expect(affixMounterWrapper.instance().affix.state.affixStyle).toBeTruthy();
await sleep(20);
affixMounterWrapper.update();
// Mock trigger resize
updateCalled.mockReset();
const resizeObserverInstance: ReactWrapper<
HTMLAttributes,
unknown,
ResizeObserverImpl
> = affixMounterWrapper.find('ResizeObserver') as any;
resizeObserverInstance
.at(index)
.instance()
.onResize(
[
{
target: {
getBoundingClientRect: () => ({ width: 99, height: 99 }),
} as Element,
contentRect: {} as DOMRect,
},
],
({} as unknown) as ResizeObserver,
);
await sleep(20);
expect(updateCalled).toHaveBeenCalled();
});
});
});

View File

@@ -1,9 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Affix Render rtl render component should be rendered correctly in RTL direction 1`] = `
<div>
<div
class=""
/>
</div>
`;

Some files were not shown because too many files have changed in this diff Show More