mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-09 10:59:19 +08:00
Compare commits
25 Commits
3.2.2
...
2.x-stable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eac43ed892 | ||
|
|
f5250cabe1 | ||
|
|
125085398c | ||
|
|
9c78bfaee4 | ||
|
|
35d11d1cb1 | ||
|
|
992c8d1562 | ||
|
|
a3fc715d3a | ||
|
|
03da3efae7 | ||
|
|
97d3422043 | ||
|
|
a609518d28 | ||
|
|
ef6d7a5d90 | ||
|
|
5be1bad67f | ||
|
|
b70fede5de | ||
|
|
358aa84fef | ||
|
|
6f716d1003 | ||
|
|
739c6ead54 | ||
|
|
a7255ee885 | ||
|
|
06ff0d44db | ||
|
|
e96b0fc768 | ||
|
|
8489fedb4c | ||
|
|
adf98d3c19 | ||
|
|
ba87b45903 | ||
|
|
1e8830637f | ||
|
|
2275195e15 | ||
|
|
dcf9d4c294 |
10
.babelrc
Normal file
10
.babelrc
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"env": {
|
||||
"test": {
|
||||
"presets": ["es2015", "react", "stage-0"],
|
||||
"plugins": [
|
||||
"add-module-exports"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
57
.github/CONTRIBUTING.md
vendored
57
.github/CONTRIBUTING.md
vendored
@@ -1,13 +1,58 @@
|
||||
# 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 documentation](http://facebook.github.io/react/docs/getting-started.html) or just Google (not Baidu, seriously) your questions with keyword *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
|
||||
|
||||
**Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github)
|
||||
|
||||
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 discuss 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 documentation, 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.
|
||||
|
||||
7
.jest.js
7
.jest.js
@@ -37,16 +37,9 @@ module.exports = {
|
||||
'!components/style/index.tsx',
|
||||
'!components/*/locale/index.tsx',
|
||||
'!components/*/__tests__/**/type.tsx',
|
||||
'!components/**/*/interface.{ts,tsx}',
|
||||
],
|
||||
transformIgnorePatterns,
|
||||
snapshotSerializers: [
|
||||
'enzyme-to-json/serializer',
|
||||
],
|
||||
mapCoverage: true,
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsConfigFile: './tsconfig.test.json',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -18,9 +18,4 @@ module.exports = {
|
||||
snapshotSerializers: [
|
||||
'enzyme-to-json/serializer'
|
||||
],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsConfigFile: './tsconfig.test.json',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
"selector-list-comma-newline-after": null,
|
||||
"selector-pseudo-element-colon-notation": null,
|
||||
"unit-no-unknown": null,
|
||||
"value-list-max-empty-lines": null,
|
||||
"font-family-no-missing-generic-family-keyword": null,
|
||||
"no-descending-specificity": null
|
||||
"value-list-max-empty-lines": null
|
||||
}
|
||||
}
|
||||
|
||||
47
.travis.yml
47
.travis.yml
@@ -5,24 +5,33 @@ language: node_js
|
||||
node_js:
|
||||
- 8
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- env: TEST_TYPE=lint
|
||||
- env: REACT=16 TEST_TYPE=test:dist
|
||||
- env: REACT=16 TEST_TYPE=test:lib
|
||||
- env: REACT=16 TEST_TYPE=test:es
|
||||
- env: REACT=16 TEST_TYPE=test:dom
|
||||
- env: REACT=16 TEST_TYPE=test:node
|
||||
- env: REACT=15 TEST_TYPE=test:dist
|
||||
- env: REACT=15 TEST_TYPE=test:lib
|
||||
- env: REACT=15 TEST_TYPE=test:es
|
||||
- env: REACT=15 TEST_TYPE=test:dom
|
||||
- env: REACT=15 TEST_TYPE=test:node
|
||||
- env: REACT=16 TEST_TYPE=bisheng:build
|
||||
|
||||
before_script:
|
||||
- scripts/install-react.sh
|
||||
env:
|
||||
matrix:
|
||||
- TEST_TYPE=lint
|
||||
- TEST_TYPE=test:dist
|
||||
- TEST_TYPE=test:lib
|
||||
- TEST_TYPE=test:es
|
||||
- TEST_TYPE=test:dom
|
||||
- TEST_TYPE=test:node
|
||||
|
||||
script:
|
||||
- scripts/travis-script.sh
|
||||
- |
|
||||
if [ "$TEST_TYPE" = lint ]; then
|
||||
npm run lint
|
||||
elif [ "$TEST_TYPE" = test:dist ]; then
|
||||
npm run dist && \
|
||||
node ./tests/dekko/dist.test.js && \
|
||||
LIB_DIR=dist npm test -- -w 2
|
||||
elif [ "$TEST_TYPE" = test:lib ]; then
|
||||
npm run compile && \
|
||||
node ./tests/dekko/lib.test.js && \
|
||||
LIB_DIR=lib npm test -- -w 2
|
||||
elif [ "$TEST_TYPE" = test:es ]; then
|
||||
npm run compile && \
|
||||
LIB_DIR=es npm test -- -w 2
|
||||
elif [ "$TEST_TYPE" = test:dom ]; then
|
||||
npm test -- --coverage -w 2 && \
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
elif [ "$TEST_TYPE" = test:node ]; then
|
||||
npm run test-node -- -w 2
|
||||
fi
|
||||
|
||||
1738
CHANGELOG.en-US.md
1738
CHANGELOG.en-US.md
File diff suppressed because it is too large
Load Diff
1681
CHANGELOG.zh-CN.md
1681
CHANGELOG.zh-CN.md
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
<p align="center">
|
||||
<a href="http://ant.design">
|
||||
<img width="230" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
<img width="320" src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -35,12 +35,12 @@
|
||||
|
||||
## 参与共建 [](http://makeapullrequest.com)
|
||||
|
||||
请参考[贡献指南](https://ant.design/docs/react/contributing-cn).
|
||||
`antd` 是一个开源项目,我们欢迎社区参与共建。如果你对此项目感兴趣,有 [很多方式](https://opensource.guide/how-to-contribute/) 进行参与。你可以 watch 这个仓库,加入 [issue 中的讨论](https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3ADiscussion),以及尝试实现一些 [已接受的特性](https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22PR+welcome%22)。我们会给予有活跃贡献的社区成员 [collaborator 权限](https://github.com/ant-design/ant-design/issues/3222)。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
npm install antd --save
|
||||
npm install antd
|
||||
```
|
||||
|
||||
## 示例
|
||||
@@ -56,15 +56,28 @@ ReactDOM.render(<DatePicker />, mountNode);
|
||||
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
```
|
||||
|
||||
你也可以[按需加载组件](https://ant.design/docs/react/getting-started-cn#按需加载)。
|
||||
按需加载可通过此写法 `import DatePicker from 'antd/lib/date-picker'` 或使用 Babel 插件 [babel-plugin-import](https://github.com/ant-design/babel-plugin-import),或使用 TypeScript 插件 [ts-import-plugin](https://github.com/Brooooooklyn/ts-import-plugin)。
|
||||
|
||||
## TypeScript
|
||||
|
||||
参考 [在 TypeScript 中使用](https://ant.design/docs/react/use-in-typescript-cn)
|
||||
```js
|
||||
// tsconfig.json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"jsx": "preserve",
|
||||
"allowSyntheticDefaultImports": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 注意:
|
||||
> - 设置 `allowSyntheticDefaultImports` 避免 `error TS1192: Module 'react' has no default export` 的错误。
|
||||
> - 不要使用 @types/antd, antd 已经自带了 TypeScript 定义。
|
||||
|
||||
## 国际化
|
||||
|
||||
参考 [国际化文档](http://ant.design/docs/react/i18n-cn)。
|
||||
参考 [国际化文档](http://ant.design/docs/react/i18n)。
|
||||
|
||||
## 链接
|
||||
|
||||
@@ -80,7 +93,7 @@ import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
- [开发者说明](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://github.com/ant-design/ant-design/wiki/FAQ)
|
||||
- [CodeSandbox 模板](https://u.ant.design/codesandbox-repro) for bug reports
|
||||
- [CodePen 模板](http://codepen.io/benjycui/pen/KgPZrE?editors=001) for bug reports
|
||||
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
|
||||
- [定制主题](http://ant.design/docs/react/customize-theme-cn)
|
||||
|
||||
@@ -96,7 +109,7 @@ $ npm start
|
||||
|
||||
## 如何贡献
|
||||
|
||||
阅读我们的[贡献指南](./.github/CONTRIBUTING.md).
|
||||
在任何形式的参与前,请先阅读 [贡献者文档](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md)。如果你希望参与贡献,欢迎 [Pull Request](https://github.com/ant-design/ant-design/pulls),或给我们 [报告 Bug](http://new-issue.ant.design/)。
|
||||
|
||||
> 强烈推荐阅读 [《提问的智慧》](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),更好的问题更容易获得帮助。
|
||||
|
||||
|
||||
68
README.md
68
README.md
@@ -1,6 +1,6 @@
|
||||
<p align="center">
|
||||
<a href="http://ant.design">
|
||||
<img width="230" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
<img width="320" src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -20,10 +20,6 @@ An enterprise-class UI design language and React-based implementation.
|
||||
|
||||
[中文 README](README-zh_CN.md)
|
||||
|
||||
## 3.0 Released Now! :tada::tada::tada:
|
||||
|
||||
[Announcing Ant Design 3.0](https://medium.com/ant-design/announcing-ant-design-3-0-70e3e65eca0c)
|
||||
|
||||
## Features
|
||||
|
||||
- An enterprise-class UI design language for web applications.
|
||||
@@ -39,12 +35,12 @@ An enterprise-class UI design language and React-based implementation.
|
||||
|
||||
## Let's build a better antd together [](http://makeapullrequest.com)
|
||||
|
||||
Read our [contributing guide](https://ant.design/docs/react/contributing).
|
||||
`antd` is an open source project; improvements are welcomed. If you are interested in contributing to `antd`, you can watch this repository, join in [discussion](https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3ADiscussion), or try to implement some [features which have been accepted](https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22PR+welcome%22). Actually, there are [many ways](https://opensource.guide/how-to-contribute/) to contribute. And we are always happy to [offer collaborator permission](https://github.com/ant-design/ant-design/issues/3222) for some active contributors.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install antd --save
|
||||
npm install antd
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -60,12 +56,63 @@ And import style manually:
|
||||
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
|
||||
```
|
||||
|
||||
Or [import components on demand](https://ant.design/docs/react/getting-started#Import-on-Demand)
|
||||
### Use modularized antd
|
||||
|
||||
- Manually import
|
||||
|
||||
```jsx
|
||||
import DatePicker from 'antd/lib/date-picker'; // for js
|
||||
import 'antd/lib/date-picker/style/css'; // for css
|
||||
// import 'antd/lib/date-picker/style'; // that will import less
|
||||
```
|
||||
|
||||
- Use [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)
|
||||
|
||||
```js
|
||||
// .babelrc or babel-loader option
|
||||
{
|
||||
"plugins": [
|
||||
["import", { "libraryName": "antd", "style": "css" }] // `style: true` for less
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Then you can import components from antd, equivalent to import manually below.
|
||||
|
||||
```jsx
|
||||
// import js and css modularly, parsed by babel-plugin-import
|
||||
import { DatePicker } from 'antd';
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
See [Use in TypeScript](https://ant.design/docs/react/use-in-typescript)
|
||||
```js
|
||||
// tsconfig.json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"jsx": "preserve",
|
||||
"allowSyntheticDefaultImports": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> Note:
|
||||
> - set `allowSyntheticDefaultImports` to prevent `error TS1192: Module 'react' has no default export`.
|
||||
> - Don't use @types/antd, antd provide a built-in ts definition already.
|
||||
|
||||
#### Use [ts-import-plugin](https://github.com/Brooooooklyn/ts-import-plugin) with modularized antd
|
||||
|
||||
```js
|
||||
{
|
||||
loader: "ts-loader", // or awesome-typescript-loader
|
||||
options {
|
||||
getCustomTransformers: () => ({
|
||||
before: [ tsImportPluginFactory({ libraryName: "antd", style: "css" }) ]
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Internationalization
|
||||
|
||||
@@ -84,7 +131,7 @@ See [i18n](http://ant.design/docs/react/i18n).
|
||||
- [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://github.com/ant-design/ant-design/wiki/FAQ)
|
||||
- [CodeSandbox Template](https://u.ant.design/codesandbox-repro) for bug reports
|
||||
- [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](http://ant.design/docs/react/customize-theme)
|
||||
|
||||
@@ -92,7 +139,6 @@ See [i18n](http://ant.design/docs/react/i18n).
|
||||
|
||||
```bash
|
||||
$ git clone git@github.com:ant-design/ant-design.git
|
||||
$ cd ant-design
|
||||
$ npm install
|
||||
$ npm start
|
||||
```
|
||||
|
||||
@@ -19,14 +19,12 @@ Array [
|
||||
"Checkbox",
|
||||
"Col",
|
||||
"DatePicker",
|
||||
"Divider",
|
||||
"Dropdown",
|
||||
"Form",
|
||||
"Icon",
|
||||
"Input",
|
||||
"InputNumber",
|
||||
"Layout",
|
||||
"List",
|
||||
"LocaleProvider",
|
||||
"message",
|
||||
"Menu",
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
// https://github.com/moment/moment/issues/3650
|
||||
export default function callMoment(moment: any, ...args: any[]) {
|
||||
return (moment.default || moment)(...args);
|
||||
}
|
||||
30
components/_util/getLocale.tsx
Normal file
30
components/_util/getLocale.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
export function getComponentLocale(props, context, componentName, getDefaultLocale) {
|
||||
let locale: any = {};
|
||||
if (context && context.antLocale && context.antLocale[componentName]) {
|
||||
locale = context.antLocale[componentName];
|
||||
} else {
|
||||
const defaultLocale = getDefaultLocale();
|
||||
// TODO: make default lang of antd be English
|
||||
// https://github.com/ant-design/ant-design/issues/6334
|
||||
locale = defaultLocale.default || defaultLocale;
|
||||
}
|
||||
|
||||
const result = {
|
||||
...locale,
|
||||
...props.locale,
|
||||
};
|
||||
result.lang = {
|
||||
...locale.lang,
|
||||
...props.locale.lang,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getLocaleCode(context) {
|
||||
const localeCode = context.antLocale && context.antLocale.locale;
|
||||
// Had use LocaleProvide but didn't set locale
|
||||
if (context.antLocale && context.antLocale.exist && !localeCode) {
|
||||
return 'zh-cn';
|
||||
}
|
||||
return localeCode;
|
||||
}
|
||||
@@ -2,7 +2,7 @@ const availablePrefixs = ['moz', 'ms', 'webkit'];
|
||||
|
||||
function requestAnimationFramePolyfill() {
|
||||
let lastTime = 0;
|
||||
return function(callback: (n: number) => void) {
|
||||
return function(callback) {
|
||||
const currTime = new Date().getTime();
|
||||
const timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||||
const id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
|
||||
@@ -23,11 +23,11 @@ export default function getRequestAnimationFrame() {
|
||||
const prefix = availablePrefixs.filter(key => `${key}RequestAnimationFrame` in window)[0];
|
||||
|
||||
return prefix
|
||||
? (window as any)[`${prefix}RequestAnimationFrame`]
|
||||
? window[`${prefix}RequestAnimationFrame`]
|
||||
: requestAnimationFramePolyfill();
|
||||
}
|
||||
|
||||
export function cancelRequestAnimationFrame(id: number) {
|
||||
export function cancelRequestAnimationFrame(id) {
|
||||
if (typeof window === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
@@ -39,8 +39,6 @@ export function cancelRequestAnimationFrame(id: number) {
|
||||
)[0];
|
||||
|
||||
return prefix ?
|
||||
(
|
||||
(window as any)[`${prefix}CancelAnimationFrame`] ||
|
||||
(window as any)[`${prefix}CancelRequestAnimationFrame`]
|
||||
).call(this, id) : clearTimeout(id);
|
||||
(window[`${prefix}CancelAnimationFrame`] || window[`${prefix}CancelRequestAnimationFrame`]).call(this, id)
|
||||
: clearTimeout(id);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export default function getScroll(target: any, top: boolean): number {
|
||||
export default function getScroll(target, top): number {
|
||||
if (typeof window === 'undefined') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
let animation: boolean;
|
||||
let animation;
|
||||
|
||||
function isCssAnimationSupported() {
|
||||
if (animation !== undefined) {
|
||||
@@ -11,7 +11,7 @@ function isCssAnimationSupported() {
|
||||
}
|
||||
if (animation !== undefined) {
|
||||
for (let i = 0; i < domPrefixes.length; i++) {
|
||||
if ((elm.style as any)[`${domPrefixes[i]}AnimationName`] !== undefined) {
|
||||
if (elm.style[`${domPrefixes[i]}AnimationName`] !== undefined) {
|
||||
animation = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3,18 +3,18 @@ import getRequestAnimationFrame, { cancelRequestAnimationFrame } from './getRequ
|
||||
|
||||
const reqAnimFrame = getRequestAnimationFrame();
|
||||
|
||||
function animate(node: HTMLElement, show: boolean, done: () => void) {
|
||||
let height: number;
|
||||
let requestAnimationFrameId: number;
|
||||
function animate(node, show, done) {
|
||||
let height;
|
||||
let requestAnimationFrameId;
|
||||
return cssAnimation(node, 'ant-motion-collapse', {
|
||||
start() {
|
||||
if (!show) {
|
||||
node.style.height = `${node.offsetHeight}px`;
|
||||
node.style.opacity = '1';
|
||||
node.style.opacity = 1;
|
||||
} else {
|
||||
height = node.offsetHeight;
|
||||
node.style.height = '0px';
|
||||
node.style.opacity = '0';
|
||||
node.style.height = 0;
|
||||
node.style.opacity = 0;
|
||||
}
|
||||
},
|
||||
active() {
|
||||
@@ -23,7 +23,7 @@ function animate(node: HTMLElement, show: boolean, done: () => void) {
|
||||
}
|
||||
requestAnimationFrameId = reqAnimFrame(() => {
|
||||
node.style.height = `${show ? height : 0}px`;
|
||||
node.style.opacity = show ? '1' : '0';
|
||||
node.style.opacity = show ? 1 : 0;
|
||||
});
|
||||
},
|
||||
end() {
|
||||
@@ -38,13 +38,13 @@ function animate(node: HTMLElement, show: boolean, done: () => void) {
|
||||
}
|
||||
|
||||
const animation = {
|
||||
enter(node: HTMLElement, done: () => void) {
|
||||
enter(node, done) {
|
||||
return animate(node, true, done);
|
||||
},
|
||||
leave(node: HTMLElement, done: () => void) {
|
||||
leave(node, done) {
|
||||
return animate(node, false, done);
|
||||
},
|
||||
appear(node: HTMLElement, done: () => void) {
|
||||
appear(node, done) {
|
||||
return animate(node, true, done);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,27 +2,27 @@ import getRequestAnimationFrame, { cancelRequestAnimationFrame } from '../_util/
|
||||
|
||||
const reqAnimFrame = getRequestAnimationFrame();
|
||||
|
||||
export default function throttleByAnimationFrame(fn: () => void) {
|
||||
let requestId: number | null;
|
||||
export default function throttleByAnimationFrame(fn) {
|
||||
let requestId;
|
||||
|
||||
const later = (args: any[]) => () => {
|
||||
const later = args => () => {
|
||||
requestId = null;
|
||||
fn(...args);
|
||||
};
|
||||
|
||||
const throttled = (...args: any[]) => {
|
||||
const throttled = (...args) => {
|
||||
if (requestId == null) {
|
||||
requestId = reqAnimFrame(later(args));
|
||||
}
|
||||
};
|
||||
|
||||
(throttled as any).cancel = () => cancelRequestAnimationFrame(requestId!);
|
||||
(throttled as any).cancel = () => cancelRequestAnimationFrame(requestId);
|
||||
|
||||
return throttled;
|
||||
}
|
||||
|
||||
export function throttleByAnimationFrameDecorator() {
|
||||
return function(target: any, key: string, descriptor: any) {
|
||||
return function(target, key, descriptor) {
|
||||
let fn = descriptor.value;
|
||||
let definingProperty = false;
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export default function triggerEvent(el: Element, type: string) {
|
||||
export default function triggerEvent(el, type) {
|
||||
if ('createEvent' in document) {
|
||||
// modern browsers, IE9+
|
||||
const e = document.createEvent('HTMLEvents');
|
||||
|
||||
@@ -60,7 +60,7 @@ describe('Affix Render', () => {
|
||||
const wrapper = mount(<AffixMounter />, { attachTo: document.getElementById('mounter') });
|
||||
jest.runAllTimers();
|
||||
|
||||
wrapper.instance().affix.fixedNode.parentNode.getBoundingClientRect = jest.fn(() => {
|
||||
wrapper.node.affix.refs.fixedNode.parentNode.getBoundingClientRect = jest.fn(() => {
|
||||
return {
|
||||
bottom: 100, height: 28, left: 0, right: 0, top: -50, width: 195,
|
||||
};
|
||||
@@ -71,6 +71,6 @@ describe('Affix Render', () => {
|
||||
});
|
||||
|
||||
jest.runAllTimers();
|
||||
expect(wrapper.instance().affix.state.affixStyle).not.toBe(null);
|
||||
expect(wrapper.node.affix.state.affixStyle).not.toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import classNames from 'classnames';
|
||||
@@ -8,13 +8,13 @@ import omit from 'omit.js';
|
||||
import getScroll from '../_util/getScroll';
|
||||
import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationFrame';
|
||||
|
||||
function getTargetRect(target: HTMLElement | Window | null): ClientRect {
|
||||
function getTargetRect(target): ClientRect {
|
||||
return target !== window ?
|
||||
(target as HTMLElement).getBoundingClientRect() :
|
||||
{ top: 0, left: 0, bottom: 0 } as ClientRect;
|
||||
target.getBoundingClientRect() :
|
||||
{ top: 0, left: 0, bottom: 0 };
|
||||
}
|
||||
|
||||
function getOffset(element: HTMLElement, target: HTMLElement | Window | null) {
|
||||
function getOffset(element: HTMLElement, target) {
|
||||
const elemRect = element.getBoundingClientRect();
|
||||
const targetRect = getTargetRect(target);
|
||||
|
||||
@@ -55,16 +55,11 @@ export interface AffixProps {
|
||||
/** 固定状态改变时触发的回调函数 */
|
||||
onChange?: (affixed?: boolean) => void;
|
||||
/** 设置 Affix 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 */
|
||||
target?: () => Window | HTMLElement | null;
|
||||
target?: () => Window | HTMLElement;
|
||||
prefixCls?: string;
|
||||
}
|
||||
|
||||
export interface AffixState {
|
||||
affixStyle: React.CSSProperties | undefined;
|
||||
placeholderStyle: React.CSSProperties | undefined;
|
||||
}
|
||||
|
||||
export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
export default class Affix extends React.Component<AffixProps, any> {
|
||||
static propTypes = {
|
||||
offsetTop: PropTypes.number,
|
||||
offsetBottom: PropTypes.number,
|
||||
@@ -74,6 +69,9 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
scrollEvent: any;
|
||||
resizeEvent: any;
|
||||
timeout: any;
|
||||
refs: {
|
||||
fixedNode: HTMLElement;
|
||||
};
|
||||
|
||||
events = [
|
||||
'resize',
|
||||
@@ -85,18 +83,17 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
'load',
|
||||
];
|
||||
|
||||
eventHandlers: {
|
||||
[key: string]: any;
|
||||
} = {};
|
||||
eventHandlers = {};
|
||||
|
||||
state: AffixState = {
|
||||
affixStyle: undefined,
|
||||
placeholderStyle: undefined,
|
||||
};
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
affixStyle: null,
|
||||
placeholderStyle: null,
|
||||
};
|
||||
}
|
||||
|
||||
private fixedNode: HTMLElement;
|
||||
|
||||
setAffixStyle(e: any, affixStyle: React.CSSProperties | null) {
|
||||
setAffixStyle(e, affixStyle) {
|
||||
const { onChange = noop, target = getDefaultTarget } = this.props;
|
||||
const originalAffixStyle = this.state.affixStyle;
|
||||
const isWindow = target() === window;
|
||||
@@ -106,7 +103,7 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
if (shallowequal(affixStyle, originalAffixStyle)) {
|
||||
return;
|
||||
}
|
||||
this.setState({ affixStyle: affixStyle as React.CSSProperties }, () => {
|
||||
this.setState({ affixStyle }, () => {
|
||||
const affixed = !!this.state.affixStyle;
|
||||
if ((affixStyle && !originalAffixStyle) ||
|
||||
(!affixStyle && originalAffixStyle)) {
|
||||
@@ -115,16 +112,16 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
});
|
||||
}
|
||||
|
||||
setPlaceholderStyle(placeholderStyle: React.CSSProperties | null) {
|
||||
setPlaceholderStyle(placeholderStyle) {
|
||||
const originalPlaceholderStyle = this.state.placeholderStyle;
|
||||
if (shallowequal(placeholderStyle, originalPlaceholderStyle)) {
|
||||
return;
|
||||
}
|
||||
this.setState({ placeholderStyle: placeholderStyle as React.CSSProperties });
|
||||
this.setState({ placeholderStyle });
|
||||
}
|
||||
|
||||
@throttleByAnimationFrameDecorator()
|
||||
updatePosition(e: any) {
|
||||
updatePosition(e) {
|
||||
let { offsetTop, offsetBottom, offset, target = getDefaultTarget } = this.props;
|
||||
const targetNode = target();
|
||||
|
||||
@@ -134,8 +131,8 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
const affixNode = ReactDOM.findDOMNode(this) as HTMLElement;
|
||||
const elemOffset = getOffset(affixNode, targetNode);
|
||||
const elemSize = {
|
||||
width: this.fixedNode.offsetWidth,
|
||||
height: this.fixedNode.offsetHeight,
|
||||
width: this.refs.fixedNode.offsetWidth,
|
||||
height: this.refs.fixedNode.offsetHeight,
|
||||
};
|
||||
|
||||
const offsetMode = {
|
||||
@@ -157,10 +154,9 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
if (scrollTop > elemOffset.top - (offsetTop as number) && offsetMode.top) {
|
||||
// Fixed Top
|
||||
const width = elemOffset.width;
|
||||
const top = targetRect.top + (offsetTop as number);
|
||||
this.setAffixStyle(e, {
|
||||
position: 'fixed',
|
||||
top,
|
||||
top: targetRect.top + (offsetTop as number),
|
||||
left: targetRect.left + elemOffset.left,
|
||||
width,
|
||||
});
|
||||
@@ -204,10 +200,10 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: AffixProps) {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.target !== nextProps.target) {
|
||||
this.clearEventListeners();
|
||||
this.setTargetEventListeners(nextProps.target!);
|
||||
this.setTargetEventListeners(nextProps.target);
|
||||
|
||||
// Mock Event object.
|
||||
this.updatePosition({});
|
||||
@@ -220,7 +216,7 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
(this.updatePosition as any).cancel();
|
||||
}
|
||||
|
||||
setTargetEventListeners(getTarget: () => HTMLElement | Window | null) {
|
||||
setTargetEventListeners(getTarget) {
|
||||
const target = getTarget();
|
||||
if (!target) {
|
||||
return;
|
||||
@@ -241,10 +237,6 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
});
|
||||
}
|
||||
|
||||
saveFixedNode = (node: HTMLDivElement) => {
|
||||
this.fixedNode = node;
|
||||
}
|
||||
|
||||
render() {
|
||||
const className = classNames({
|
||||
[this.props.prefixCls || 'ant-affix']: this.state.affixStyle,
|
||||
@@ -254,7 +246,7 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
||||
const placeholderStyle = { ...this.state.placeholderStyle, ...this.props.style };
|
||||
return (
|
||||
<div {...props} style={placeholderStyle}>
|
||||
<div className={className} ref={this.saveFixedNode} style={this.state.affixStyle}>
|
||||
<div className={className} ref="fixedNode" style={this.state.affixStyle}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -301,7 +301,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Success Tips
|
||||
success tips
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
|
||||
@@ -23,7 +23,7 @@ ReactDOM.render(
|
||||
<Alert message="Warning" type="warning" showIcon />
|
||||
<Alert message="Error" type="error" showIcon />
|
||||
<Alert
|
||||
message="Success Tips"
|
||||
message="success tips"
|
||||
description="Detailed description and advices about successful copywriting."
|
||||
type="success"
|
||||
showIcon
|
||||
|
||||
@@ -21,6 +21,5 @@ Alert component for feedback.
|
||||
| description | Additional content of Alert | string\|ReactNode | - |
|
||||
| message | Content of Alert | string\|ReactNode | - |
|
||||
| showIcon | Whether to show icon | boolean | false, in `banner` mode default is true |
|
||||
| iconType | Icon type, effective when `showIcon` is `true` | string | - |
|
||||
| type | Type of Alert styles, options: `success`, `info`, `warning`, `error` | string | `info`, in `banner` mode default is `warning` |
|
||||
| onClose | Callback when Alert is closed | Function | - |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Animate from 'rc-animate';
|
||||
import Icon from '../icon';
|
||||
import classNames from 'classnames';
|
||||
@@ -23,7 +23,6 @@ export interface AlertProps {
|
||||
onClose?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
/** Whether to show icon */
|
||||
showIcon?: boolean;
|
||||
iconType?: string;
|
||||
style?: React.CSSProperties;
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
@@ -60,7 +59,7 @@ export default class Alert extends React.Component<AlertProps, any> {
|
||||
render() {
|
||||
let {
|
||||
closable, description, type, prefixCls = 'ant-alert', message, closeText, showIcon, banner,
|
||||
className = '', style, iconType,
|
||||
className = '', style,
|
||||
} = this.props;
|
||||
|
||||
// banner模式默认有 Icon
|
||||
@@ -68,28 +67,27 @@ export default class Alert extends React.Component<AlertProps, any> {
|
||||
// banner模式默认为警告
|
||||
type = banner && type === undefined ? 'warning' : type || 'info';
|
||||
|
||||
if (!iconType) {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
iconType = 'check-circle';
|
||||
break;
|
||||
case 'info':
|
||||
iconType = 'info-circle';
|
||||
break;
|
||||
case 'error':
|
||||
iconType = 'cross-circle';
|
||||
break;
|
||||
case 'warning':
|
||||
iconType = 'exclamation-circle';
|
||||
break;
|
||||
default:
|
||||
iconType = 'default';
|
||||
}
|
||||
let iconType = '';
|
||||
switch (type) {
|
||||
case 'success':
|
||||
iconType = 'check-circle';
|
||||
break;
|
||||
case 'info':
|
||||
iconType = 'info-circle';
|
||||
break;
|
||||
case 'error':
|
||||
iconType = 'cross-circle';
|
||||
break;
|
||||
case 'warning':
|
||||
iconType = 'exclamation-circle';
|
||||
break;
|
||||
default:
|
||||
iconType = 'default';
|
||||
}
|
||||
|
||||
// use outline icon in alert with description
|
||||
if (!!description) {
|
||||
iconType += '-o';
|
||||
}
|
||||
// use outline icon in alert with description
|
||||
if (!!description) {
|
||||
iconType += '-o';
|
||||
}
|
||||
|
||||
let alertCls = classNames(prefixCls, {
|
||||
|
||||
@@ -22,6 +22,5 @@ title: Alert
|
||||
| description | 警告提示的辅助性文字介绍 | string\|ReactNode | 无 |
|
||||
| message | 警告提示内容 | string\|ReactNode | 无 |
|
||||
| showIcon | 是否显示辅助图标 | boolean | false,`banner` 模式下默认值为 true |
|
||||
| iconType | 自定义图标类型,`showIcon` 为 `true` 时有效 | string | - |
|
||||
| type | 指定警告提示的样式,有四种选择 `success`、`info`、`warning`、`error` | string | `info`,`banner` 模式下默认值为 `warning` |
|
||||
| onClose | 关闭时触发的回调函数 | Function | 无 |
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
|
||||
@alert-prefix-cls: ~"@{ant-prefix}-alert";
|
||||
|
||||
@@ -7,71 +6,75 @@
|
||||
@alert-text-color: @text-color;
|
||||
|
||||
.@{alert-prefix-cls} {
|
||||
.reset-component;
|
||||
position: relative;
|
||||
padding: 8px 15px 8px 37px;
|
||||
padding: 8px 48px 8px 38px;
|
||||
border-radius: @border-radius-base;
|
||||
color: @alert-text-color;
|
||||
font-size: @font-size-base;
|
||||
line-height: @line-height-base;
|
||||
|
||||
&&-no-icon {
|
||||
padding: 8px 15px;
|
||||
padding: 8px 48px 8px 16px;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
top: 8px + @font-size-base * @line-height-base / 2 - @font-size-base / 2 + 1px;
|
||||
font-size: @font-size-lg;
|
||||
top: 8px + @font-size-base * @line-height-base / 2 - @font-size-lg / 2;
|
||||
left: 16px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&-description {
|
||||
font-size: @font-size-base;
|
||||
line-height: 22px;
|
||||
line-height: 21px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-success {
|
||||
border: @border-width-base @border-style-base ~`colorPalette("@{success-color}", 3)`;
|
||||
background-color: ~`colorPalette("@{success-color}", 1)`;
|
||||
border: @border-width-base @border-style-base @green-2;
|
||||
background-color: @green-1;
|
||||
.@{alert-prefix-cls}-icon {
|
||||
color: @success-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-info {
|
||||
border: @border-width-base @border-style-base ~`colorPalette("@{info-color}", 3)`;
|
||||
background-color: ~`colorPalette("@{info-color}", 1)`;
|
||||
border: @border-width-base @border-style-base @primary-2;
|
||||
background-color: @primary-1;
|
||||
.@{alert-prefix-cls}-icon {
|
||||
color: @info-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-warning {
|
||||
border: @border-width-base @border-style-base ~`colorPalette("@{warning-color}", 3)`;
|
||||
background-color: ~`colorPalette("@{warning-color}", 1)`;
|
||||
border: @border-width-base @border-style-base @yellow-2;
|
||||
background-color: @yellow-1;
|
||||
.@{alert-prefix-cls}-icon {
|
||||
color: @warning-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-error {
|
||||
border: @border-width-base @border-style-base ~`colorPalette("@{error-color}", 3)`;
|
||||
background-color: ~`colorPalette("@{error-color}", 1)`;
|
||||
border: @border-width-base @border-style-base @red-2;
|
||||
background-color: @red-1;
|
||||
.@{alert-prefix-cls}-icon {
|
||||
color: @error-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-close-icon {
|
||||
font-size: @font-size-sm;
|
||||
font-size: @font-size-base;
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 8px;
|
||||
line-height: 22px;
|
||||
top: 10px;
|
||||
height: 12px;
|
||||
line-height: 12px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
|
||||
.@{iconfont-css-prefix}-cross {
|
||||
color: @text-color-secondary;
|
||||
transition: color .3s;
|
||||
transition: color .3s ease;
|
||||
&:hover {
|
||||
color: #404040;
|
||||
}
|
||||
@@ -84,21 +87,21 @@
|
||||
}
|
||||
|
||||
&-with-description {
|
||||
padding: 15px 15px 15px 64px;
|
||||
padding: 16px 16px 16px 60px;
|
||||
position: relative;
|
||||
border-radius: @border-radius-base;
|
||||
color: @text-color;
|
||||
line-height: @line-height-base;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
&-with-description&-no-icon {
|
||||
padding: 15px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
&-with-description &-icon {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 24px;
|
||||
left: 20px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
@@ -43,7 +43,7 @@ function easeInOutCubic(t: number, b: number, c: number, d: number) {
|
||||
|
||||
const reqAnimFrame = getRequestAnimationFrame();
|
||||
const sharpMatcherRegx = /#([^#]+)$/;
|
||||
function scrollTo(href: string, offsetTop = 0, target: () => Window | HTMLElement, callback = () => { }) {
|
||||
function scrollTo(href: string, offsetTop = 0, target, callback = () => { }) {
|
||||
const scrollTop = getScroll(target(), true);
|
||||
const sharpLinkMatch = sharpMatcherRegx.exec(href);
|
||||
if (!sharpLinkMatch) { return; }
|
||||
@@ -98,7 +98,9 @@ export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
antAnchor: PropTypes.object,
|
||||
};
|
||||
|
||||
private inkNode: HTMLSpanElement;
|
||||
refs: {
|
||||
ink?: any;
|
||||
};
|
||||
|
||||
private links: String[];
|
||||
private scrollEvent: any;
|
||||
@@ -158,7 +160,7 @@ export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
});
|
||||
}
|
||||
|
||||
handleScrollTo = (link: string) => {
|
||||
handleScrollTo = (link) => {
|
||||
const { offsetTop, target = getDefaultTarget } = this.props;
|
||||
this.animating = true;
|
||||
this.setState({ activeLink: link });
|
||||
@@ -201,14 +203,10 @@ export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
const { prefixCls } = this.props;
|
||||
const linkNode = ReactDOM.findDOMNode(this as any).getElementsByClassName(`${prefixCls}-link-title-active`)[0];
|
||||
if (linkNode) {
|
||||
this.inkNode.style.top = `${(linkNode as any).offsetTop + linkNode.clientHeight / 2 - 4.5}px`;
|
||||
this.refs.ink.style.top = `${(linkNode as any).offsetTop + linkNode.clientHeight / 2 - 4.5}px`;
|
||||
}
|
||||
}
|
||||
|
||||
saveInkNode = (node: HTMLSpanElement) => {
|
||||
this.inkNode = node;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
prefixCls,
|
||||
@@ -231,19 +229,11 @@ export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
'fixed': !affix && !showInkInFixed,
|
||||
});
|
||||
|
||||
const wrapperStyle = {
|
||||
maxHeight: offsetTop ? `calc(100vh - ${offsetTop}px)` : '100vh',
|
||||
...style,
|
||||
};
|
||||
|
||||
const anchorContent = (
|
||||
<div
|
||||
className={wrapperClass}
|
||||
style={wrapperStyle}
|
||||
>
|
||||
<div className={wrapperClass} style={style}>
|
||||
<div className={anchorClass}>
|
||||
<div className={`${prefixCls}-ink`} >
|
||||
<span className={inkClass} ref={this.saveInkNode} />
|
||||
<span className={inkClass} ref="ink" />
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ describe('Anchor Render', () => {
|
||||
|
||||
wrapper.find('a[href="#API"]').simulate('click');
|
||||
|
||||
wrapper.instance().handleScroll();
|
||||
expect(wrapper.instance().state).not.toBe(null);
|
||||
wrapper.node.handleScroll();
|
||||
expect(wrapper.node.state).not.toBe(null);
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - click', () => {
|
||||
@@ -25,7 +25,7 @@ describe('Anchor Render', () => {
|
||||
</Anchor>
|
||||
);
|
||||
wrapper.find('a[href="http://www.example.com/#API"]').simulate('click');
|
||||
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
||||
expect(wrapper.node.state.activeLink).toBe('http://www.example.com/#API');
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - scoll', () => {
|
||||
@@ -41,8 +41,8 @@ describe('Anchor Render', () => {
|
||||
<Link href="http://www.example.com/#API" title="API" />
|
||||
</Anchor>
|
||||
);
|
||||
wrapper.instance().handleScroll();
|
||||
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
||||
wrapper.node.handleScroll();
|
||||
expect(wrapper.node.state.activeLink).toBe('http://www.example.com/#API');
|
||||
});
|
||||
|
||||
it('Anchor render perfectly for complete href - scollTo', () => {
|
||||
@@ -58,7 +58,7 @@ describe('Anchor Render', () => {
|
||||
<Link href="##API" title="API" />
|
||||
</Anchor>
|
||||
);
|
||||
wrapper.instance().handleScrollTo('##API');
|
||||
expect(wrapper.instance().state.activeLink).toBe('##API');
|
||||
wrapper.node.handleScrollTo('##API');
|
||||
expect(wrapper.node.state.activeLink).toBe('##API');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,7 +7,6 @@ exports[`renders ./components/anchor/demo/basic.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-anchor-wrapper"
|
||||
style="max-height:100vh"
|
||||
>
|
||||
<div
|
||||
class="ant-anchor"
|
||||
@@ -80,10 +79,9 @@ exports[`renders ./components/anchor/demo/basic.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/anchor/demo/static.md correctly 1`] = `
|
||||
exports[`renders ./components/anchor/demo/fixed.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-anchor-wrapper"
|
||||
style="max-height:100vh"
|
||||
>
|
||||
<div
|
||||
class="ant-anchor fixed"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 静态位置
|
||||
en-US: Static Anchor
|
||||
zh-CN: 固定
|
||||
en-US: Fixed Anchor
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
@@ -17,7 +17,7 @@ For displaying anchor hyperlinks on page and jumping between them.
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| affix | Fixed mode of Anchor | boolean | true |
|
||||
| affix | Fixed mode of Anchor | boolean | false |
|
||||
| bounds | Bounding distance of anchor area | number | 5(px) |
|
||||
| offsetBottom | Pixels to offset from bottom when calculating position of scroll | number | - |
|
||||
| offsetTop | Pixels to offset from top when calculating position of scroll | number | 0 |
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import Anchor from './Anchor';
|
||||
import AnchorLink from './AnchorLink';
|
||||
|
||||
export { AnchorProps } from './Anchor';
|
||||
export { AnchorLinkProps } from './AnchorLink';
|
||||
|
||||
Anchor.Link = AnchorLink;
|
||||
export default Anchor;
|
||||
|
||||
@@ -18,7 +18,7 @@ title: Anchor
|
||||
|
||||
| 成员 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| affix | 固定模式 | boolean | true |
|
||||
| affix | 固定模式 | boolean | false |
|
||||
| bounds | 锚点区域边界 | number | 5(px) |
|
||||
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | number | |
|
||||
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | |
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
|
||||
@anchor-border-width: 2px;
|
||||
|
||||
.@{ant-prefix}-anchor {
|
||||
.reset-component;
|
||||
position: relative;
|
||||
padding-left: @anchor-border-width;
|
||||
|
||||
&-wrapper {
|
||||
background-color: @component-background;
|
||||
overflow: auto;
|
||||
padding-left: 4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
&-ink {
|
||||
@@ -23,7 +14,7 @@
|
||||
&:before {
|
||||
content: ' ';
|
||||
position: relative;
|
||||
width: @anchor-border-width;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-color: @border-color-split;
|
||||
@@ -32,10 +23,10 @@
|
||||
&-ball {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 8px;
|
||||
border: 2px solid @primary-color;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 9px;
|
||||
border: 3px solid @primary-color;
|
||||
background-color: @component-background;
|
||||
left: 50%;
|
||||
transition: top .3s ease-in-out;
|
||||
@@ -51,7 +42,7 @@
|
||||
}
|
||||
|
||||
&-link {
|
||||
padding: 8px 0 8px 16px;
|
||||
padding: 8px 0 8px 18px;
|
||||
line-height: 1;
|
||||
|
||||
&-title {
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
|
||||
export interface InputElementProps {
|
||||
children: React.ReactElement<any>;
|
||||
}
|
||||
|
||||
export default class InputElement extends React.Component<InputElementProps, any> {
|
||||
export default class InputElement extends React.Component<any, any> {
|
||||
private ele: HTMLInputElement;
|
||||
|
||||
focus = () => {
|
||||
this.ele.focus ? this.ele.focus() : (ReactDOM.findDOMNode(this.ele) as HTMLInputElement).focus();
|
||||
this.ele.focus ? this.ele.focus() : (findDOMNode(this.ele) as HTMLInputElement).focus();
|
||||
}
|
||||
blur = () => {
|
||||
this.ele.blur ? this.ele.blur() : (ReactDOM.findDOMNode(this.ele) as HTMLInputElement).blur();
|
||||
this.ele.blur ? this.ele.blur() : (findDOMNode(this.ele) as HTMLInputElement).blur();
|
||||
}
|
||||
saveRef = (ele: HTMLInputElement) => {
|
||||
this.ele = ele;
|
||||
const { ref: childRef } = this.props.children as any;
|
||||
const childRef = this.props.children.ref;
|
||||
if (typeof childRef === 'function') {
|
||||
childRef(ele);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-show-search ant-select-auto-complete ant-select ant-select-combobox ant-select-enabled"
|
||||
style="width:200px"
|
||||
style="width:200px;"
|
||||
>
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
@@ -18,7 +18,7 @@ exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
style="display:block;user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
input here
|
||||
@@ -46,7 +46,7 @@ exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
|
||||
</div>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
style="user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<b />
|
||||
@@ -58,11 +58,11 @@ exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
|
||||
exports[`renders ./components/auto-complete/demo/certain-category.md correctly 1`] = `
|
||||
<div
|
||||
class="certain-category-search-wrapper"
|
||||
style="width:250px"
|
||||
style="width:250px;"
|
||||
>
|
||||
<div
|
||||
class="ant-select-lg ant-select-lg certain-category-search ant-select-show-search ant-select-auto-complete ant-select ant-select-combobox ant-select-enabled"
|
||||
style="width:100%"
|
||||
style="width:100%;"
|
||||
>
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
@@ -77,7 +77,7 @@ exports[`renders ./components/auto-complete/demo/certain-category.md correctly 1
|
||||
>
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
style="display:block;user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
input here
|
||||
@@ -116,7 +116,7 @@ exports[`renders ./components/auto-complete/demo/certain-category.md correctly 1
|
||||
</div>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
style="user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<b />
|
||||
@@ -129,7 +129,7 @@ exports[`renders ./components/auto-complete/demo/certain-category.md correctly 1
|
||||
exports[`renders ./components/auto-complete/demo/custom.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-show-search ant-select-auto-complete ant-select ant-select-combobox ant-select-enabled"
|
||||
style="width:200px"
|
||||
style="width:200px;"
|
||||
>
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
@@ -152,7 +152,7 @@ exports[`renders ./components/auto-complete/demo/custom.md correctly 1`] = `
|
||||
<textarea
|
||||
class="ant-input custom ant-select-search__field"
|
||||
placeholder="input here"
|
||||
style="height:50px"
|
||||
style="height:50px;"
|
||||
/>
|
||||
<span
|
||||
class="ant-select-search__field__mirror"
|
||||
@@ -165,7 +165,7 @@ exports[`renders ./components/auto-complete/demo/custom.md correctly 1`] = `
|
||||
</div>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
style="user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<b />
|
||||
@@ -177,7 +177,7 @@ exports[`renders ./components/auto-complete/demo/custom.md correctly 1`] = `
|
||||
exports[`renders ./components/auto-complete/demo/non-case-sensitive.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-show-search ant-select-auto-complete ant-select ant-select-combobox ant-select-enabled"
|
||||
style="width:200px"
|
||||
style="width:200px;"
|
||||
>
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
@@ -192,7 +192,7 @@ exports[`renders ./components/auto-complete/demo/non-case-sensitive.md correctly
|
||||
>
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
style="display:block;user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
try to type \`b\`
|
||||
@@ -220,7 +220,7 @@ exports[`renders ./components/auto-complete/demo/non-case-sensitive.md correctly
|
||||
</div>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
style="user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<b />
|
||||
@@ -232,7 +232,7 @@ exports[`renders ./components/auto-complete/demo/non-case-sensitive.md correctly
|
||||
exports[`renders ./components/auto-complete/demo/options.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select-show-search ant-select-auto-complete ant-select ant-select-combobox ant-select-enabled"
|
||||
style="width:200px"
|
||||
style="width:200px;"
|
||||
>
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
@@ -247,7 +247,7 @@ exports[`renders ./components/auto-complete/demo/options.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
style="display:block;user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
input here
|
||||
@@ -275,7 +275,7 @@ exports[`renders ./components/auto-complete/demo/options.md correctly 1`] = `
|
||||
</div>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
style="user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<b />
|
||||
@@ -287,11 +287,11 @@ exports[`renders ./components/auto-complete/demo/options.md correctly 1`] = `
|
||||
exports[`renders ./components/auto-complete/demo/uncertain-category.md correctly 1`] = `
|
||||
<div
|
||||
class="global-search-wrapper"
|
||||
style="width:300px"
|
||||
style="width:300px;"
|
||||
>
|
||||
<div
|
||||
class="ant-select-lg ant-select-lg global-search ant-select-show-search ant-select-auto-complete ant-select ant-select-combobox ant-select-enabled"
|
||||
style="width:100%"
|
||||
style="width:100%;"
|
||||
>
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
@@ -306,7 +306,7 @@ exports[`renders ./components/auto-complete/demo/uncertain-category.md correctly
|
||||
>
|
||||
<div
|
||||
class="ant-select-selection__placeholder"
|
||||
style="display:block;user-select:none;-webkit-user-select:none"
|
||||
style="display:block;user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
input here
|
||||
@@ -350,7 +350,7 @@ exports[`renders ./components/auto-complete/demo/uncertain-category.md correctly
|
||||
</div>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
style="user-select:none;-webkit-user-select:none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<b />
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import AutoComplete from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
|
||||
describe('AutoComplete with Custom Input Element Render', () => {
|
||||
focusTest(AutoComplete);
|
||||
|
||||
it('AutoComplete with custom Input render perfectly', () => {
|
||||
const wrapper = mount(
|
||||
<AutoComplete dataSource={['12345', '23456', '34567']}>
|
||||
@@ -15,7 +12,7 @@ describe('AutoComplete with Custom Input Element Render', () => {
|
||||
|
||||
expect(wrapper.find('textarea').length).toBe(1);
|
||||
wrapper.find('textarea').simulate('change', { target: { value: '123' } });
|
||||
const dropdownWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
||||
const dropdownWrapper = mount(wrapper.find('Trigger').node.getComponent());
|
||||
|
||||
// should not filter data source defaultly
|
||||
expect(dropdownWrapper.find('MenuItem').length).toBe(3);
|
||||
@@ -21,7 +21,6 @@ const dataSource = ['12345', '23456', '34567'];
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| allowClear | Show clear button, effective in multiple mode only. | boolean | false |
|
||||
| autoFocus | get focus when component mounted | boolean | false |
|
||||
| backfill | backfill selected item the input when using keyboard | boolean | false |
|
||||
| children (for customize input element) | customize input element | HTMLInputElement / HTMLTextAreaElement / React.ReactElement<InputProps> | `<Input />` |
|
||||
| children (for dataSource) | Data source for autocomplet | React.ReactElement<OptionProps> / Array<React.ReactElement<OptionProps>> | - |
|
||||
@@ -33,13 +32,6 @@ const dataSource = ['12345', '23456', '34567'];
|
||||
| optionLabelProp | Which prop value of option will render as content of select. | string | `children` |
|
||||
| placeholder | placeholder of input | string | - |
|
||||
| value | selected option | string\|string\[]\|{ key: string, label: string\|ReactNode }\|Array<{ key: string, label: string\|ReactNode }> | - |
|
||||
| onChange | Called when select an option or input value change, or value of input is changed | function(value) | - |
|
||||
| onChange | Called when select an option or input value change, or value of input is changed | function(value, label) | - |
|
||||
| onSearch | Called when searching items. | function(value) | - |
|
||||
| onSelect | Called when a option is selected. param is option's value and option instance. | function(value, option) | - |
|
||||
|
||||
## Methods
|
||||
|
||||
| Name | Description |
|
||||
| ---- | ----------- |
|
||||
| blur() | remove focus |
|
||||
| focus() | get focus |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import { Option, OptGroup } from 'rc-select';
|
||||
import classNames from 'classnames';
|
||||
import Select, { AbstractSelectProps, SelectValue, OptionProps, OptGroupProps } from '../select';
|
||||
@@ -8,7 +8,7 @@ import InputElement from './InputElement';
|
||||
export interface DataSourceItemObject { value: string; text: string; }
|
||||
export type DataSourceItemType = string | DataSourceItemObject;
|
||||
|
||||
export interface AutoCompleteInputProps {
|
||||
export interface InputProps {
|
||||
onChange?: React.FormEventHandler<any>;
|
||||
value: any;
|
||||
}
|
||||
@@ -16,7 +16,7 @@ export interface AutoCompleteInputProps {
|
||||
export type ValidInputElement =
|
||||
HTMLInputElement |
|
||||
HTMLTextAreaElement |
|
||||
React.ReactElement<AutoCompleteInputProps>;
|
||||
React.ReactElement<InputProps>;
|
||||
|
||||
export interface AutoCompleteProps extends AbstractSelectProps {
|
||||
value?: SelectValue;
|
||||
@@ -34,7 +34,7 @@ function isSelectOptionOrSelectOptGroup(child: any): Boolean {
|
||||
return child && child.type && (child.type.isSelectOption || child.type.isSelectOptGroup);
|
||||
}
|
||||
|
||||
export default class AutoComplete extends React.Component<AutoCompleteProps, {}> {
|
||||
export default class AutoComplete extends React.Component<AutoCompleteProps, any> {
|
||||
static Option = Option as React.ClassicComponentClass<OptionProps>;
|
||||
static OptGroup = OptGroup as React.ClassicComponentClass<OptGroupProps>;
|
||||
|
||||
@@ -47,8 +47,6 @@ export default class AutoComplete extends React.Component<AutoCompleteProps, {}>
|
||||
filterOption: false,
|
||||
};
|
||||
|
||||
private select: any;
|
||||
|
||||
getInputElement = () => {
|
||||
const { children } = this.props;
|
||||
const element = children && React.isValidElement(children) && children.type !== Option ?
|
||||
@@ -61,18 +59,6 @@ export default class AutoComplete extends React.Component<AutoCompleteProps, {}>
|
||||
);
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.select.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.select.blur();
|
||||
}
|
||||
|
||||
saveSelect = (node: any) => {
|
||||
this.select = node;
|
||||
}
|
||||
|
||||
render() {
|
||||
let {
|
||||
size, className = '', notFoundContent, prefixCls, optionLabelProp, dataSource, children,
|
||||
@@ -120,7 +106,6 @@ export default class AutoComplete extends React.Component<AutoCompleteProps, {}>
|
||||
optionLabelProp={optionLabelProp}
|
||||
getInputElement={this.getInputElement}
|
||||
notFoundContent={notFoundContent}
|
||||
ref={this.saveSelect}
|
||||
>
|
||||
{options}
|
||||
</Select>
|
||||
|
||||
@@ -22,7 +22,6 @@ const dataSource = ['12345', '23456', '34567'];
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| allowClear | 支持清除, 单选模式有效 | boolean | false |
|
||||
| autoFocus | 自动获取焦点 | boolean | false |
|
||||
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false |
|
||||
| children (自动完成的数据源) | 自动完成的数据源 | React.ReactElement<OptionProps> / Array<React.ReactElement<OptionProps>> | - |
|
||||
| children (自定义输入框) | 自定义输入框 | HTMLInputElement / HTMLTextAreaElement / React.ReactElement<InputProps> | `<Input />` |
|
||||
@@ -37,10 +36,3 @@ const dataSource = ['12345', '23456', '34567'];
|
||||
| onChange | 选中 option,或 input 的 value 变化时,调用此函数 | function(value) | 无 |
|
||||
| onSearch | 搜索补全项的时候调用 | function(value) | 无 |
|
||||
| onSelect | 被选中时调用,参数为选中项的 value 值 | function(value, option) | 无 |
|
||||
|
||||
## 方法
|
||||
|
||||
| 名称 | 描述 |
|
||||
| --- | --- |
|
||||
| blur() | 移除焦点 |
|
||||
| focus() | 获取焦点 |
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
@autocomplete-prefix-cls: ~"@{select-prefix-cls}-auto-complete";
|
||||
|
||||
.@{autocomplete-prefix-cls} {
|
||||
.reset-component;
|
||||
|
||||
&.@{select-prefix-cls} {
|
||||
.@{select-prefix-cls} {
|
||||
&-selection {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
style="margin-right:24px"
|
||||
style="margin-right:24px;"
|
||||
>
|
||||
<span
|
||||
class="ant-badge"
|
||||
@@ -22,7 +22,7 @@ exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
|
||||
>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1100%);-webkit-transform:translateY(-1100%);transform:translateY(-1100%)"
|
||||
style="transition:none;-ms-transform:translateY(-1100%);-webkit-transform:translateY(-1100%);transform:translateY(-1100%);"
|
||||
>
|
||||
<p
|
||||
class=""
|
||||
@@ -253,7 +253,7 @@ exports[`renders ./components/avatar/demo/dynamic.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="ant-avatar ant-avatar-lg ant-avatar-circle"
|
||||
style="background-color:#f56a00;vertical-align:middle"
|
||||
style="background-color:#f56a00;"
|
||||
>
|
||||
<span
|
||||
class="ant-avatar-string"
|
||||
@@ -263,7 +263,7 @@ exports[`renders ./components/avatar/demo/dynamic.md correctly 1`] = `
|
||||
</span>
|
||||
<button
|
||||
class="ant-btn ant-btn-sm"
|
||||
style="margin-left:16px;vertical-align:middle"
|
||||
style="margin-left:16px;"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@@ -309,7 +309,7 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
</span>
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
style="color:#f56a00;background-color:#fde3cf"
|
||||
style="color:#f56a00;background-color:#fde3cf;"
|
||||
>
|
||||
<span
|
||||
class="ant-avatar-string"
|
||||
@@ -319,7 +319,7 @@ exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
|
||||
</span>
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-icon"
|
||||
style="background-color:#87d068"
|
||||
style="background-color:#87d068;"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-user"
|
||||
|
||||
@@ -37,12 +37,8 @@ class Autoset extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Avatar style={{ backgroundColor: this.state.color, verticalAlign: 'middle' }} size="large">
|
||||
{this.state.user}
|
||||
</Avatar>
|
||||
<Button size="small" style={{ marginLeft: 16, verticalAlign: 'middle' }} onClick={this.changeUser}>
|
||||
Change
|
||||
</Button>
|
||||
<Avatar style={{ backgroundColor: this.state.color }} size="large">{this.state.user}</Avatar>
|
||||
<Button size="small" style={{ marginLeft: 16 }} onClick={this.changeUser}>Change</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Icon from '../icon';
|
||||
import classNames from 'classnames';
|
||||
|
||||
@@ -83,7 +83,7 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
|
||||
const classString = classNames(prefixCls, className, sizeCls, {
|
||||
[`${prefixCls}-${shape}`]: shape,
|
||||
[`${prefixCls}-image`]: src && this.state.isImgExist,
|
||||
[`${prefixCls}-image`]: src,
|
||||
[`${prefixCls}-icon`]: icon,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
|
||||
@avatar-prefix-cls: ~"@{ant-prefix}-avatar";
|
||||
|
||||
.@{avatar-prefix-cls} {
|
||||
.reset-component;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
background: @avatar-bg;
|
||||
@@ -12,11 +10,6 @@
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
|
||||
&-image {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.avatar-size(@avatar-size-base, @avatar-font-size-base);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ exports[`renders ./components/back-top/demo/basic.md correctly 1`] = `
|
||||
<div>
|
||||
Scroll down to see the bottom-right
|
||||
<strong
|
||||
style="color:rgba(64, 64, 64, 0.6)"
|
||||
style="color:rgba(64, 64, 64, 0.6);"
|
||||
>
|
||||
gray
|
||||
</strong>
|
||||
@@ -16,7 +16,7 @@ exports[`renders ./components/back-top/demo/custom.md correctly 1`] = `
|
||||
<div>
|
||||
Scroll down to see the bottom-right
|
||||
<strong
|
||||
style="color:#1088e9"
|
||||
style="color:#1088e9;"
|
||||
>
|
||||
blue
|
||||
</strong>
|
||||
|
||||
@@ -15,7 +15,7 @@ describe('BackTop', () => {
|
||||
const wrapper = mount(<BackTop visibilityHeight={-1} />);
|
||||
document.documentElement.scrollTop = 400;
|
||||
// trigger scroll manually
|
||||
wrapper.instance().handleScroll();
|
||||
wrapper.node.handleScroll();
|
||||
jest.runAllTimers();
|
||||
wrapper.find('.ant-back-top').simulate('click');
|
||||
jest.runAllTimers();
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import Animate from 'rc-animate';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import Icon from '../icon';
|
||||
import getScroll from '../_util/getScroll';
|
||||
import getRequestAnimationFrame from '../_util/getRequestAnimationFrame';
|
||||
|
||||
@@ -108,7 +109,7 @@ export default class BackTop extends React.Component<BackTopProps, any> {
|
||||
|
||||
const defaultElement = (
|
||||
<div className={`${prefixCls}-content`}>
|
||||
<div className={`${prefixCls}-icon`} />
|
||||
<Icon className={`${prefixCls}-icon`} type="to-top" />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -118,7 +119,6 @@ export default class BackTop extends React.Component<BackTopProps, any> {
|
||||
'className',
|
||||
'children',
|
||||
'visibilityHeight',
|
||||
'target',
|
||||
]);
|
||||
|
||||
const backTopBtn = this.state.visible ? (
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
|
||||
@backtop-prefix-cls: ~"@{ant-prefix}-back-top";
|
||||
|
||||
.@{backtop-prefix-cls} {
|
||||
.reset-component;
|
||||
z-index: @zindex-back-top;
|
||||
position: fixed;
|
||||
right: 100px;
|
||||
@@ -21,7 +19,6 @@
|
||||
color: @back-top-color;
|
||||
text-align: center;
|
||||
transition: all .3s @ease-in-out;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover {
|
||||
background-color: @back-top-hover-bg;
|
||||
@@ -30,11 +27,7 @@
|
||||
}
|
||||
|
||||
&-icon {
|
||||
margin: 12px auto;
|
||||
width: 14px;
|
||||
height: 16px;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAoCAYAAACWwljjAAAABGdBTUEAALGPC/xhBQAAAbtJREFUWAntmMtKw0AUhhMvS5cuxILgQlRUpIggIoKIIoigG1eC+AA+jo+i6FIXBfeuXIgoeKVeitVWJX5HWhhDksnUpp3FDPyZk3Nm5nycmZKkXhAEOXSA3lG7muTeRzmfy6HneUvIhnYkQK+Q9NhAA0Opg0vBEhjBKHiyb8iGMyQMOYuK41BcBSypAL+MYXSKjtFAW7EAGEO3qN4uMQbbAkXiSfRQJ1H6a+yhlkKRcAoVFYiweYNjtCVQJJpBz2GCiPt7fBOZQpFgDpUikse5HgnkM4Fi4QX0Fpc5wf9EbLqpUCy4jMoJSXWhFwbMNgWKhVbRhy5jirhs9fy/oFhgHVVTJEs7RLZ8sSEoJm6iz7SZDMbJ+/OKERQTttCXQRLToRUmrKWCYuA2+jbN0MB4OQobYShfdTCgn/sL1K36M7TLrN3n+758aPy2rrpR6+/od5E8tf/A1uLS9aId5T7J3CNYihkQ4D9PiMdMC7mp4rjB9kjFjZp8BlnVHJBuO1yFXIV0FdDF3RlyFdJVQBdv5AxVdIsq8apiZ2PyYO1EVykesGfZEESsCkweyR8MUW+V8uJ1gkYipmpdP1pm2aJVPEGzAAAAAElFTkSuQmCC) ~"100%/100%" no-repeat;
|
||||
font-size: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@import './responsive';
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
@media screen and (max-width: @screen-md) {
|
||||
.@{backtop-prefix-cls} {
|
||||
right: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @screen-xs) {
|
||||
.@{backtop-prefix-cls} {
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import { createElement, Component } from 'react';
|
||||
import omit from 'omit.js';
|
||||
import classNames from 'classnames';
|
||||
|
||||
function getNumberArray(num: string | number | undefined) {
|
||||
function getNumberArray(num) {
|
||||
return num ?
|
||||
num.toString()
|
||||
.split('')
|
||||
@@ -21,12 +21,7 @@ export interface ScrollNumberProps {
|
||||
title?: string | number;
|
||||
}
|
||||
|
||||
export interface ScrollNumberState {
|
||||
animateStarted?: boolean;
|
||||
count?: string | number;
|
||||
}
|
||||
|
||||
export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNumberState> {
|
||||
export default class ScrollNumber extends Component<ScrollNumberProps, any> {
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-scroll-number',
|
||||
count: null,
|
||||
@@ -36,7 +31,7 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
||||
|
||||
lastCount: any;
|
||||
|
||||
constructor(props: ScrollNumberProps) {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
animateStarted: true,
|
||||
@@ -44,14 +39,14 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
||||
};
|
||||
}
|
||||
|
||||
getPositionByNum(num: number, i: number) {
|
||||
getPositionByNum(num, i) {
|
||||
if (this.state.animateStarted) {
|
||||
return 10 + num;
|
||||
}
|
||||
const currentDigit = getNumberArray(this.state.count)[i];
|
||||
const lastDigit = getNumberArray(this.lastCount)[i];
|
||||
// 同方向则在同一侧切换数字
|
||||
if (this.state.count! > this.lastCount) {
|
||||
if (this.state.count > this.lastCount) {
|
||||
if (currentDigit >= lastDigit) {
|
||||
return 10 + num;
|
||||
}
|
||||
@@ -63,7 +58,7 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
||||
return num;
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: ScrollNumberProps) {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if ('count' in nextProps) {
|
||||
if (this.state.count === nextProps.count) {
|
||||
return;
|
||||
@@ -90,7 +85,7 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
||||
}
|
||||
}
|
||||
|
||||
renderNumberList(position: number) {
|
||||
renderNumberList(position) {
|
||||
const childrenToReturn: React.ReactElement<any>[] = [];
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const currentClassName = (position === i) ? 'current' : '';
|
||||
@@ -99,7 +94,7 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
||||
return childrenToReturn;
|
||||
}
|
||||
|
||||
renderCurrentNumber(num: number, i: number) {
|
||||
renderCurrentNumber(num, i) {
|
||||
const position = this.getPositionByNum(num, i);
|
||||
const removeTransition = this.state.animateStarted ||
|
||||
(getNumberArray(this.lastCount)[i] === undefined);
|
||||
@@ -117,7 +112,7 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
||||
|
||||
renderNumberElement() {
|
||||
const state = this.state;
|
||||
if (!state.count || isNaN(state.count as number)) {
|
||||
if (!state.count || isNaN(state.count)) {
|
||||
return state.count;
|
||||
}
|
||||
return getNumberArray(state.count)
|
||||
|
||||
@@ -16,7 +16,7 @@ exports[`renders ./components/badge/demo/basic.md correctly 1`] = `
|
||||
>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%)"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%);"
|
||||
>
|
||||
<p
|
||||
class=""
|
||||
@@ -206,7 +206,7 @@ exports[`renders ./components/badge/demo/change.md correctly 1`] = `
|
||||
>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%)"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%);"
|
||||
>
|
||||
<p
|
||||
class=""
|
||||
@@ -383,7 +383,7 @@ exports[`renders ./components/badge/demo/change.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="margin-top:10px"
|
||||
style="margin-top:10px;"
|
||||
>
|
||||
<span
|
||||
class="ant-badge"
|
||||
@@ -423,13 +423,6 @@ exports[`renders ./components/badge/demo/dot.md correctly 1`] = `
|
||||
data-show="true"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-badge"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-notification"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-badge"
|
||||
>
|
||||
@@ -463,7 +456,7 @@ exports[`renders ./components/badge/demo/link.md correctly 1`] = `
|
||||
>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%)"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%);"
|
||||
>
|
||||
<p
|
||||
class=""
|
||||
@@ -627,13 +620,13 @@ exports[`renders ./components/badge/demo/no-wrapper.md correctly 1`] = `
|
||||
class="ant-badge ant-badge-not-a-wrapper"
|
||||
>
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count ant-badge-multiple-words"
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true"
|
||||
title="25"
|
||||
>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1200%);-webkit-transform:translateY(-1200%);transform:translateY(-1200%)"
|
||||
style="transition:none;-ms-transform:translateY(-1200%);-webkit-transform:translateY(-1200%);transform:translateY(-1200%);"
|
||||
>
|
||||
<p
|
||||
class=""
|
||||
@@ -788,7 +781,7 @@ exports[`renders ./components/badge/demo/no-wrapper.md correctly 1`] = `
|
||||
</span>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%)"
|
||||
style="transition:none;-ms-transform:translateY(-1500%);-webkit-transform:translateY(-1500%);transform:translateY(-1500%);"
|
||||
>
|
||||
<p
|
||||
class=""
|
||||
@@ -949,12 +942,12 @@ exports[`renders ./components/badge/demo/no-wrapper.md correctly 1`] = `
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true"
|
||||
style="background-color:#fff;color:#999;box-shadow:0 0 0 1px #d9d9d9 inset"
|
||||
style="background-color:#fff;color:#999;box-shadow:0 0 0 1px #d9d9d9 inset;"
|
||||
title="4"
|
||||
>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1400%);-webkit-transform:translateY(-1400%);transform:translateY(-1400%)"
|
||||
style="transition:none;-ms-transform:translateY(-1400%);-webkit-transform:translateY(-1400%);transform:translateY(-1400%);"
|
||||
>
|
||||
<p
|
||||
class=""
|
||||
@@ -1113,9 +1106,9 @@ exports[`renders ./components/badge/demo/no-wrapper.md correctly 1`] = `
|
||||
class="ant-badge ant-badge-not-a-wrapper"
|
||||
>
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count ant-badge-multiple-words"
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true"
|
||||
style="background-color:#52c41a"
|
||||
style="background-color:#87d068;"
|
||||
title="109"
|
||||
>
|
||||
99+
|
||||
@@ -1134,13 +1127,13 @@ exports[`renders ./components/badge/demo/overflow.md correctly 1`] = `
|
||||
href="#"
|
||||
/>
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count ant-badge-multiple-words"
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true"
|
||||
title="99"
|
||||
>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1900%);-webkit-transform:translateY(-1900%);transform:translateY(-1900%)"
|
||||
style="transition:none;-ms-transform:translateY(-1900%);-webkit-transform:translateY(-1900%);transform:translateY(-1900%);"
|
||||
>
|
||||
<p
|
||||
class=""
|
||||
@@ -1295,7 +1288,7 @@ exports[`renders ./components/badge/demo/overflow.md correctly 1`] = `
|
||||
</span>
|
||||
<span
|
||||
class="ant-scroll-number-only"
|
||||
style="transition:none;-ms-transform:translateY(-1900%);-webkit-transform:translateY(-1900%);transform:translateY(-1900%)"
|
||||
style="transition:none;-ms-transform:translateY(-1900%);-webkit-transform:translateY(-1900%);transform:translateY(-1900%);"
|
||||
>
|
||||
<p
|
||||
class=""
|
||||
@@ -1458,7 +1451,7 @@ exports[`renders ./components/badge/demo/overflow.md correctly 1`] = `
|
||||
href="#"
|
||||
/>
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count ant-badge-multiple-words"
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true"
|
||||
title="100"
|
||||
>
|
||||
@@ -1473,7 +1466,7 @@ exports[`renders ./components/badge/demo/overflow.md correctly 1`] = `
|
||||
href="#"
|
||||
/>
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count ant-badge-multiple-words"
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true"
|
||||
title="99"
|
||||
>
|
||||
@@ -1488,7 +1481,7 @@ exports[`renders ./components/badge/demo/overflow.md correctly 1`] = `
|
||||
href="#"
|
||||
/>
|
||||
<sup
|
||||
class="ant-scroll-number ant-badge-count ant-badge-multiple-words"
|
||||
class="ant-scroll-number ant-badge-count"
|
||||
data-show="true"
|
||||
title="1000"
|
||||
>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Badge from '../index';
|
||||
|
||||
describe('Badge', () => {
|
||||
test('badge dot not scaling count > 9', () => {
|
||||
const badge = mount(<Badge count={10} dot />);
|
||||
expect(badge.find('.ant-card-multiple-words').length).toBe(0);
|
||||
});
|
||||
test('badge dot not showing count == 0', () => {
|
||||
const badge = mount(<Badge count={0} dot />);
|
||||
expect(badge.find('.ant-badge-dot').length).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -30,12 +30,12 @@ ReactDOM.render(
|
||||
|
||||
<style>
|
||||
.ant-badge:not(.ant-badge-status) {
|
||||
margin-right: 20px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
.head-example {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 4px;
|
||||
border-radius: 6px;
|
||||
background: #eee;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ title:
|
||||
## en-US
|
||||
|
||||
This will simply display a red badge, without a specific count.
|
||||
If count equals 0, it won't display the dot.
|
||||
|
||||
````jsx
|
||||
import { Badge, Icon } from 'antd';
|
||||
@@ -22,9 +21,6 @@ ReactDOM.render(
|
||||
<Badge dot>
|
||||
<Icon type="notification" />
|
||||
</Badge>
|
||||
<Badge count={0} dot>
|
||||
<Icon type="notification" />
|
||||
</Badge>
|
||||
<Badge dot>
|
||||
<a href="#">Link something</a>
|
||||
</Badge>
|
||||
|
||||
@@ -22,7 +22,7 @@ ReactDOM.render(
|
||||
<div>
|
||||
<Badge count={25} />
|
||||
<Badge count={4} style={{ backgroundColor: '#fff', color: '#999', boxShadow: '0 0 0 1px #d9d9d9 inset' }} />
|
||||
<Badge count={109} style={{ backgroundColor: '#52c41a' }} />
|
||||
<Badge count={109} style={{ backgroundColor: '#87d068' }} />
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
||||
|
||||
@@ -24,9 +24,8 @@ Badge normally appears in proximity to notifications or user avatars with eye-ca
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| count | Number to show in badge | number\|ReactNode | |
|
||||
| count | Number to show in badge | number | |
|
||||
| dot | Whether to display a red dot instead of `count` | boolean | `false` |
|
||||
| offset | set offset of the badge dot, like`[x, y]` | `[number, number]` | - |
|
||||
| overflowCount | Max count to show | number | 99 |
|
||||
| showZero | Whether to show badge when `count` is zero | boolean | `false` |
|
||||
| status | Set Badge as a status dot | `success` \| `processing` \| `default` \| `error` \| `warning` | `''` |
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Animate from 'rc-animate';
|
||||
import ScrollNumber from './ScrollNumber';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export { ScrollNumberProps } from './ScrollNumber';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
export interface BadgeProps {
|
||||
/** Number to show in badge */
|
||||
@@ -20,7 +19,6 @@ export interface BadgeProps {
|
||||
className?: string;
|
||||
status?: 'success' | 'processing' | 'default' | 'error' | 'warning';
|
||||
text?: string;
|
||||
offset?: [number | string, number | string];
|
||||
}
|
||||
|
||||
export default class Badge extends React.Component<BadgeProps, any> {
|
||||
@@ -56,41 +54,39 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
dot,
|
||||
status,
|
||||
text,
|
||||
offset,
|
||||
...restProps,
|
||||
} = this.props;
|
||||
const isDot = dot || status;
|
||||
let displayCount = (count as number) > (overflowCount as number) ? `${overflowCount}+` : count;
|
||||
const isZero = displayCount === '0' || displayCount === 0;
|
||||
const isDot = (dot && !isZero) || status;
|
||||
// dot mode don't need count
|
||||
if (isDot) {
|
||||
displayCount = '';
|
||||
}
|
||||
|
||||
const isZero = displayCount === '0' || displayCount === 0;
|
||||
const isEmpty = displayCount === null || displayCount === undefined || displayCount === '';
|
||||
const hidden = (isEmpty || (isZero && !showZero)) && !isDot;
|
||||
const statusCls = classNames({
|
||||
[`${prefixCls}-status-dot`]: !!status,
|
||||
[`${prefixCls}-status-${status}`]: !!status,
|
||||
});
|
||||
const scrollNumberCls = classNames({
|
||||
[`${prefixCls}-dot`]: isDot,
|
||||
[`${prefixCls}-count`]: !isDot,
|
||||
[`${prefixCls}-multiple-words`]: !isDot && count && count.toString && count.toString().length > 1,
|
||||
[`${prefixCls}-status-${status}`]: !!status,
|
||||
});
|
||||
const badgeCls = classNames(className, prefixCls, {
|
||||
[`${prefixCls}-status`]: !!status,
|
||||
[`${prefixCls}-not-a-wrapper`]: !children,
|
||||
});
|
||||
const styleWithOffset = offset ? {
|
||||
marginTop: offset[0],
|
||||
marginLeft: offset[1],
|
||||
...style,
|
||||
} : style;
|
||||
|
||||
warning(
|
||||
!(children && status),
|
||||
'`Badge[children]` and `Badge[status]` cannot be used at the same time.',
|
||||
);
|
||||
// <Badge status="success" />
|
||||
if (!children && status) {
|
||||
const statusCls = classNames({
|
||||
[`${prefixCls}-status-dot`]: !!status,
|
||||
[`${prefixCls}-status-${status}`]: true,
|
||||
});
|
||||
return (
|
||||
<span className={badgeCls} style={styleWithOffset}>
|
||||
<span className={badgeCls}>
|
||||
<span className={statusCls} />
|
||||
<span className={`${prefixCls}-status-text`}>{text}</span>
|
||||
</span>
|
||||
@@ -104,7 +100,7 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
className={scrollNumberCls}
|
||||
count={displayCount}
|
||||
title={count}
|
||||
style={styleWithOffset}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
|
||||
|
||||
@@ -25,9 +25,8 @@ title: Badge
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | number\|ReactNode | |
|
||||
| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | number | |
|
||||
| dot | 不展示数字,只有一个小红点 | boolean | false |
|
||||
| offset | 设置状态点的位置偏移,格式为 `[x, y]` | `[number, number]` | - |
|
||||
| overflowCount | 展示封顶的数字值 | number | 99 |
|
||||
| showZero | 当数值为 0 时,是否展示 Badge | boolean | false |
|
||||
| status | 设置 Badge 为状态点 | Enum{ 'success', 'processing, 'default', 'error', 'warning' } | '' |
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
|
||||
@badge-prefix-cls: ~"@{ant-prefix}-badge";
|
||||
@number-prefix-cls: ~"@{ant-prefix}-scroll-number";
|
||||
|
||||
.@{badge-prefix-cls} {
|
||||
.reset-component;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
@@ -24,20 +22,15 @@
|
||||
text-align: center;
|
||||
padding: 0 6px;
|
||||
font-size: @badge-font-size;
|
||||
font-weight: @badge-font-weight;
|
||||
white-space: nowrap;
|
||||
transform-origin: -10% center;
|
||||
box-shadow: 0 0 0 1px #fff;
|
||||
font-family: tahoma;
|
||||
a,
|
||||
a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&-multiple-words {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
&-dot {
|
||||
position: absolute;
|
||||
transform: translateX(-50%);
|
||||
@@ -56,19 +49,16 @@
|
||||
vertical-align: baseline;
|
||||
|
||||
&-dot {
|
||||
width: @badge-status-size;
|
||||
height: @badge-status-size;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
&-success {
|
||||
background-color: @success-color;
|
||||
}
|
||||
&-processing {
|
||||
background-color: @processing-color;
|
||||
background-color: @primary-color;
|
||||
position: relative;
|
||||
&:after {
|
||||
position: absolute;
|
||||
@@ -77,7 +67,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
border: 1px solid @processing-color;
|
||||
border: 1px solid @primary-color;
|
||||
content: '';
|
||||
animation: antStatusProcessing 1.2s infinite ease-in-out;
|
||||
}
|
||||
@@ -109,7 +99,7 @@
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
&-not-a-wrapper .@{ant-prefix}-scroll-number {
|
||||
&-not-a-wrapper &-count {
|
||||
top: auto;
|
||||
display: block;
|
||||
position: relative;
|
||||
@@ -136,7 +126,6 @@
|
||||
height: @badge-height;
|
||||
> p {
|
||||
height: @badge-height;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,21 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { cloneElement } from 'react';
|
||||
import warning from '../_util/warning';
|
||||
import BreadcrumbItem from './BreadcrumbItem';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export interface Route {
|
||||
path: string;
|
||||
breadcrumbName: string;
|
||||
}
|
||||
|
||||
export interface BreadcrumbProps {
|
||||
prefixCls?: string;
|
||||
routes?: Route[];
|
||||
params?: any;
|
||||
routes?: Array<any>;
|
||||
params?: Object;
|
||||
separator?: React.ReactNode;
|
||||
itemRender?: (route: any, params: any, routes: Array<any>, paths: Array<string>) => React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function getBreadcrumbName(route: Route, params: any) {
|
||||
function getBreadcrumbName(route, params) {
|
||||
if (!route.breadcrumbName) {
|
||||
return null;
|
||||
}
|
||||
@@ -32,7 +27,7 @@ function getBreadcrumbName(route: Route, params: any) {
|
||||
return name;
|
||||
}
|
||||
|
||||
function defaultItemRender(route: Route, params: any, routes: Route[], paths: string[]) {
|
||||
function defaultItemRender(route, params, routes, paths) {
|
||||
const isLastItem = routes.indexOf(route) === routes.length - 1;
|
||||
const name = getBreadcrumbName(route, params);
|
||||
return isLastItem
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export interface BreadcrumbItemProps {
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
import { render } from 'enzyme';
|
||||
import demoTest from '../../../tests/shared/demoTest';
|
||||
import routerDemo from '../demo/router.md';
|
||||
|
||||
demoTest('breadcrumb', { skip: ['router.md', 'router-4.md'] });
|
||||
|
||||
const testMethod = typeof window !== 'undefined' ? test : test.skip;
|
||||
testMethod('renders ./components/breadcrumb/demo/router.md correctly', () => {
|
||||
const wrapper = render(routerDemo);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import Breadcrumb from './Breadcrumb';
|
||||
import BreadcrumbItem from './BreadcrumbItem';
|
||||
|
||||
export { BreadcrumbProps } from './Breadcrumb';
|
||||
export { BreadcrumbItemProps } from './BreadcrumbItem';
|
||||
|
||||
Breadcrumb.Item = BreadcrumbItem;
|
||||
export default Breadcrumb;
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
|
||||
@breadcrumb-prefix-cls: ~"@{ant-prefix}-breadcrumb";
|
||||
|
||||
.@{breadcrumb-prefix-cls} {
|
||||
.reset-component;
|
||||
color: @breadcrumb-base-color;
|
||||
font-size: @breadcrumb-font-size;
|
||||
|
||||
.@{iconfont-css-prefix} {
|
||||
font-size: @breadcrumb-icon-font-size;
|
||||
}
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
|
||||
a {
|
||||
color: @breadcrumb-link-color;
|
||||
color: @text-color;
|
||||
transition: color .3s;
|
||||
&:hover {
|
||||
color: @breadcrumb-link-color-hover;
|
||||
color: @primary-5;
|
||||
}
|
||||
}
|
||||
|
||||
& > span:last-child {
|
||||
color: @breadcrumb-last-item-color;
|
||||
font-weight: 500;
|
||||
color: @text-color;
|
||||
}
|
||||
|
||||
& > span:last-child &-separator {
|
||||
@@ -29,8 +24,8 @@
|
||||
}
|
||||
|
||||
&-separator {
|
||||
margin: @breadcrumb-separator-margin;
|
||||
color: @breadcrumb-separator-color;
|
||||
margin: 0 8px;
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
&-link {
|
||||
|
||||
@@ -251,7 +251,7 @@ exports[`renders ./components/button/demo/disabled.md correctly 1`] = `
|
||||
|
||||
exports[`renders ./components/button/demo/ghost.md correctly 1`] = `
|
||||
<div
|
||||
style="background:rgb(190, 200, 200);padding:26px 16px 16px"
|
||||
style="background:rgb(190, 200, 200);padding:26px 16px 16px;"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-background-ghost"
|
||||
@@ -481,7 +481,6 @@ exports[`renders ./components/button/demo/size.md correctly 1`] = `
|
||||
checked=""
|
||||
class="ant-radio-button-input"
|
||||
type="radio"
|
||||
value="large"
|
||||
/>
|
||||
<span
|
||||
class="ant-radio-button-inner"
|
||||
@@ -500,7 +499,6 @@ exports[`renders ./components/button/demo/size.md correctly 1`] = `
|
||||
<input
|
||||
class="ant-radio-button-input"
|
||||
type="radio"
|
||||
value="default"
|
||||
/>
|
||||
<span
|
||||
class="ant-radio-button-inner"
|
||||
@@ -519,7 +517,6 @@ exports[`renders ./components/button/demo/size.md correctly 1`] = `
|
||||
<input
|
||||
class="ant-radio-button-input"
|
||||
type="radio"
|
||||
value="small"
|
||||
/>
|
||||
<span
|
||||
class="ant-radio-button-inner"
|
||||
|
||||
@@ -1,32 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Button fixbug renders {0} , 0 and {false} 1`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
>
|
||||
0
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button fixbug renders {0} , 0 and {false} 2`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
0
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button fixbug renders {0} , 0 and {false} 3`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Button renders Chinese characters correctly 1`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
@@ -76,15 +49,3 @@ exports[`Button renders correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button should support link button 1`] = `
|
||||
<a
|
||||
class="ant-btn"
|
||||
href="http://ant.design"
|
||||
target="_blank"
|
||||
>
|
||||
<span>
|
||||
link button
|
||||
</span>
|
||||
</a>
|
||||
`;
|
||||
|
||||
@@ -52,7 +52,7 @@ describe('Button', () => {
|
||||
<DefaultButton />
|
||||
);
|
||||
wrapper.simulate('click');
|
||||
expect(wrapper.find('.ant-btn-loading').length).toBe(1);
|
||||
expect(wrapper.hasClass('ant-btn-loading')).toBe(true);
|
||||
});
|
||||
|
||||
it('should change loading state with delay', () => {
|
||||
@@ -74,26 +74,4 @@ describe('Button', () => {
|
||||
wrapper.simulate('click');
|
||||
expect(wrapper.hasClass('ant-btn-loading')).toBe(false);
|
||||
});
|
||||
|
||||
it('should support link button', () => {
|
||||
const wrapper = mount(
|
||||
<Button target="_blank" href="http://ant.design">link button</Button>
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('fixbug renders {0} , 0 and {false}', () => {
|
||||
const wrapper = render(
|
||||
<Button>{0}</Button>
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const wrapper1 = render(
|
||||
<Button>0</Button>
|
||||
);
|
||||
expect(wrapper1).toMatchSnapshot();
|
||||
const wrapper2 = render(
|
||||
<Button>{false}</Button>
|
||||
);
|
||||
expect(wrapper2).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { ButtonSize } from './button';
|
||||
|
||||
export type ButtonSize = 'small' | 'large';
|
||||
|
||||
export interface ButtonGroupProps {
|
||||
size?: ButtonSize;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
@@ -47,18 +46,12 @@ export interface ButtonProps {
|
||||
onClick?: React.FormEventHandler<any>;
|
||||
onMouseUp?: React.FormEventHandler<any>;
|
||||
onMouseDown?: React.FormEventHandler<any>;
|
||||
onKeyPress?: React.KeyboardEventHandler<any>;
|
||||
onKeyDown?: React.KeyboardEventHandler<any>;
|
||||
tabIndex?: number;
|
||||
loading?: boolean | { delay?: number };
|
||||
disabled?: boolean;
|
||||
style?: React.CSSProperties;
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
ghost?: boolean;
|
||||
target?: string;
|
||||
href?: string;
|
||||
download?: string;
|
||||
}
|
||||
|
||||
export default class Button extends React.Component<ButtonProps, any> {
|
||||
@@ -90,20 +83,9 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
this.state = {
|
||||
loading: props.loading,
|
||||
clicked: false,
|
||||
hasTwoCNChar: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// Fix for HOC usage like <FormatMessage />
|
||||
const buttonText = (findDOMNode(this) as HTMLElement).innerText;
|
||||
if (this.isNeedInserted() && isTwoCNChar(buttonText)) {
|
||||
this.setState({
|
||||
hasTwoCNChar: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: ButtonProps) {
|
||||
const currentLoading = this.props.loading;
|
||||
const loading = nextProps.loading;
|
||||
@@ -113,7 +95,7 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
}
|
||||
|
||||
if (typeof loading !== 'boolean' && loading && loading.delay) {
|
||||
this.delayTimeout = window.setTimeout(() => this.setState({ loading }), loading.delay);
|
||||
this.delayTimeout = setTimeout(() => this.setState({ loading }), loading.delay);
|
||||
} else {
|
||||
this.setState({ loading });
|
||||
}
|
||||
@@ -132,7 +114,7 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
// Add click effect
|
||||
this.setState({ clicked: true });
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = window.setTimeout(() => this.setState({ clicked: false }), 500);
|
||||
this.timeout = setTimeout(() => this.setState({ clicked: false }), 500);
|
||||
|
||||
const onClick = this.props.onClick;
|
||||
if (onClick) {
|
||||
@@ -140,18 +122,12 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
}
|
||||
}
|
||||
|
||||
isNeedInserted() {
|
||||
const { loading, icon, children } = this.props;
|
||||
const iconType = loading ? 'loading' : icon;
|
||||
return React.Children.count(children) === 1 && (!iconType || iconType === 'loading');
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
type, shape, size, className, htmlType, children, icon, prefixCls, ghost, ...others,
|
||||
} = this.props;
|
||||
|
||||
const { loading, clicked, hasTwoCNChar } = this.state;
|
||||
const { loading, clicked } = this.state;
|
||||
|
||||
// large => lg
|
||||
// small => sm
|
||||
@@ -166,8 +142,6 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
break;
|
||||
}
|
||||
|
||||
const ComponentProp = others.href ? 'a' : 'button';
|
||||
|
||||
const classes = classNames(prefixCls, className, {
|
||||
[`${prefixCls}-${type}`]: type,
|
||||
[`${prefixCls}-${shape}`]: shape,
|
||||
@@ -176,23 +150,22 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
[`${prefixCls}-loading`]: loading,
|
||||
[`${prefixCls}-clicked`]: clicked,
|
||||
[`${prefixCls}-background-ghost`]: ghost,
|
||||
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar,
|
||||
});
|
||||
|
||||
const iconType = loading ? 'loading' : icon;
|
||||
const iconNode = iconType ? <Icon type={iconType} /> : null;
|
||||
const kids = (children || children === 0)
|
||||
? React.Children.map(children, child => insertSpace(child, this.isNeedInserted())) : null;
|
||||
const needInserted = React.Children.count(children) === 1 && (!iconType || iconType === 'loading');
|
||||
const kids = React.Children.map(children, child => insertSpace(child, needInserted));
|
||||
|
||||
return (
|
||||
<ComponentProp
|
||||
<button
|
||||
{...omit(others, ['loading'])}
|
||||
type={others.href ? undefined : (htmlType || 'button')}
|
||||
type={htmlType || 'button'}
|
||||
className={classes}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
{iconNode}{kids}
|
||||
</ComponentProp>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,27 +17,22 @@ To get a customized button, just set `type`/`shape`/`size`/`loading`/`disabled`.
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| ghost | make background transparent and invert text and border colors, added in 2.7 | boolean | false |
|
||||
| href | redirect url of link button | string | - |
|
||||
| htmlType | set the original html `type` of `button`, see: [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type) | string | `button` |
|
||||
| icon | set the icon of button, see: Icon component | string | - |
|
||||
| loading | set the loading status of button | boolean \| { delay: number } | false |
|
||||
| shape | can be set to `circle` or omitted | string | - |
|
||||
| size | can be set to `small` `large` or omitted | string | `default` |
|
||||
| target | same as target attribute of a, works when href is specified | string | - |
|
||||
| type | can be set to `primary` `ghost` `dashed` `danger`(added in 2.7) or omitted (meaning `default`) | string | `default` |
|
||||
| onClick | set the handler to handle `click` event | function | - |
|
||||
|
||||
`<Button>Hello world!</Button>` will be rendered into `<button><span>Hello world!</span></button>`, and all the properties which are not listed above will be transferred to the `<button>` tag.
|
||||
|
||||
`<Button href="http://example.com">Hello world!</Button>` will be rendered into `<a href="http://example.com"><span>Hello world!</span></a>`.
|
||||
|
||||
<style>
|
||||
[id^=components-button-demo-] .ant-btn {
|
||||
margin-right: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
[id^=components-button-demo-] .ant-btn-group > .ant-btn,
|
||||
[id^=components-button-demo-] .ant-btn-group > span > .ant-btn {
|
||||
[id^=components-button-demo-] .ant-btn-group > .ant-btn {
|
||||
margin-right: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import Button from './button';
|
||||
import ButtonGroup from './button-group';
|
||||
|
||||
export { ButtonProps, ButtonShape, ButtonSize, ButtonType } from './button';
|
||||
export { ButtonGroupProps } from './button-group';
|
||||
|
||||
Button.Group = ButtonGroup;
|
||||
export default Button;
|
||||
|
||||
@@ -20,20 +20,16 @@ subtitle: 按钮
|
||||
| 属性 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| ghost | 幽灵属性,使按钮背景透明,版本 2.7 中增加 | boolean | false |
|
||||
| href | 点击跳转的地址,指定此属性 button 的行为和 a 链接一致 | string | - |
|
||||
| htmlType | 设置 `button` 原生的 `type` 值,可选值请参考 [HTML 标准](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type) | string | `button` |
|
||||
| icon | 设置按钮的图标类型 | string | - |
|
||||
| loading | 设置按钮载入状态 | boolean \| { delay: number } | `false` |
|
||||
| shape | 设置按钮形状,可选值为 `circle` 或者不设 | string | - |
|
||||
| size | 设置按钮大小,可选值为 `small` `large` 或者不设 | string | `default` |
|
||||
| target | 相当于 a 链接的 target 属性,href 存在时生效 | string | - |
|
||||
| type | 设置按钮类型,可选值为 `primary` `dashed` `danger`(版本 2.7 中增加) 或者不设 | string | - |
|
||||
| onClick | `click` 事件的 handler | function | - |
|
||||
|
||||
`<Button>Hello world!</Button>` 最终会被渲染为 `<button><span>Hello world!</span></button>`,并且除了上表中的属性,其它属性都会直接传到 `<button></button>`。
|
||||
|
||||
`<Button href="http://example.com">Hello world!</Button>` 则会渲染为 `<a href="http://example.com"><span>Hello world!</span></a>`。
|
||||
|
||||
<style>
|
||||
[id^="components-button-demo-"] .ant-btn {
|
||||
margin-right: 8px;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
// Button styles
|
||||
// -----------------------------
|
||||
.@{btn-prefix-cls} {
|
||||
line-height: @line-height-base;
|
||||
.btn;
|
||||
.btn-default;
|
||||
|
||||
@@ -128,7 +127,7 @@
|
||||
// To ensure that a space will be placed between character and `Icon`.
|
||||
> .@{iconfont-css-prefix} + span,
|
||||
> span + .@{iconfont-css-prefix} {
|
||||
margin-left: 8px;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
&-clicked:after {
|
||||
@@ -156,21 +155,12 @@
|
||||
}
|
||||
|
||||
&-background-ghost&-primary {
|
||||
.button-variant-ghost(@btn-primary-bg);
|
||||
.button-variant-ghost(@primary-color);
|
||||
}
|
||||
|
||||
&-background-ghost&-danger {
|
||||
.button-variant-ghost(@btn-danger-color);
|
||||
}
|
||||
|
||||
&-two-chinese-chars:first-letter {
|
||||
letter-spacing: .34em;
|
||||
}
|
||||
|
||||
&-two-chinese-chars > * {
|
||||
letter-spacing: .34em;
|
||||
margin-right: -.34em;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes buttonEffect {
|
||||
@@ -183,13 +173,3 @@
|
||||
border-width: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
a.@{btn-prefix-cls} {
|
||||
line-height: @btn-height-base - 2px;
|
||||
&-lg {
|
||||
line-height: @btn-height-lg - 2px;
|
||||
}
|
||||
&-sm {
|
||||
line-height: @btn-height-sm - 2px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
.button-color(@primary-5; @background; @primary-5);
|
||||
.button-color(@primary-color; @background; @primary-color);
|
||||
}
|
||||
|
||||
&:active,
|
||||
@@ -56,12 +56,12 @@
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
.button-color(@btn-primary-color; ~`colorPalette("@{color}", 5)`; ~`colorPalette("@{color}", 5)`);
|
||||
.button-color(@btn-primary-color; @color; @color;);
|
||||
}
|
||||
|
||||
&:active,
|
||||
&.active {
|
||||
.button-color(@btn-primary-color; ~`colorPalette("@{color}", 7)`; ~`colorPalette("@{color}", 7)`);
|
||||
.button-color(@btn-primary-color; ~`colorPalette("@{color}", 7)`; ~`colorPalette("@{color}", 7)`;);
|
||||
}
|
||||
|
||||
.button-disabled();
|
||||
@@ -108,6 +108,7 @@
|
||||
display: inline-block;
|
||||
> .@{btnClassName} {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
@@ -138,6 +139,7 @@
|
||||
// --------------------------------------------------
|
||||
.btn() {
|
||||
display: inline-block;
|
||||
margin-bottom: 0;
|
||||
font-weight: @btn-font-weight;
|
||||
text-align: center;
|
||||
touch-action: manipulation;
|
||||
@@ -145,6 +147,7 @@
|
||||
background-image: none;
|
||||
border: @border-width-base @border-style-base transparent;
|
||||
white-space: nowrap;
|
||||
line-height: 1.15; // https://github.com/ant-design/ant-design/issues/7070
|
||||
.button-size(@btn-height-base; @btn-padding-base; @font-size-base; @btn-border-radius-base);
|
||||
user-select: none;
|
||||
transition: all .3s @ease-in-out;
|
||||
@@ -182,7 +185,7 @@
|
||||
}
|
||||
|
||||
&-sm {
|
||||
.button-size(@btn-height-sm; @btn-padding-sm; @btn-font-size-sm; @btn-border-radius-sm);
|
||||
.button-size(@btn-height-sm; @btn-padding-sm; @font-size-base; @btn-border-radius-sm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +201,7 @@
|
||||
&:focus,
|
||||
&:active,
|
||||
&.active {
|
||||
background: @btn-default-bg;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,8 +244,6 @@
|
||||
|
||||
.@{btnClassName} + .@{btnClassName},
|
||||
.@{btnClassName} + &,
|
||||
span + .@{btnClassName},
|
||||
.@{btnClassName} + span,
|
||||
& + .@{btnClassName},
|
||||
& + & {
|
||||
margin-left: -1px;
|
||||
@@ -250,23 +251,23 @@
|
||||
|
||||
.@{btnClassName}:not(:first-child):not(:last-child) {
|
||||
border-radius: 0;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
> .@{btnClassName}:first-child,
|
||||
> span:first-child > .@{btnClassName} {
|
||||
> .@{btnClassName}:first-child {
|
||||
margin-left: 0;
|
||||
&:not(:last-child) {
|
||||
border-bottom-right-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
> .@{btnClassName}:first-child:not(:last-child),
|
||||
> span:first-child:not(:last-child) > .@{btnClassName} {
|
||||
border-bottom-right-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
> .@{btnClassName}:last-child:not(:first-child),
|
||||
> span:last-child:not(:first-child) > .@{btnClassName} {
|
||||
> .@{btnClassName}:last-child:not(:first-child) {
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
& > & {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import * as moment from 'moment';
|
||||
import React from 'react';
|
||||
import moment from 'moment';
|
||||
import { PREFIX_CLS } from './Constants';
|
||||
import Select from '../select';
|
||||
import { Group, Button } from '../radio';
|
||||
@@ -12,7 +12,7 @@ export interface HeaderProps {
|
||||
yearSelectOffset?: number;
|
||||
yearSelectTotal?: number;
|
||||
type?: string;
|
||||
onValueChange?: (value: moment.Moment) => void;
|
||||
onValueChange?: (value) => void;
|
||||
onTypeChange?: (type: string) => void;
|
||||
value: any;
|
||||
}
|
||||
@@ -24,9 +24,9 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
yearSelectTotal: 20,
|
||||
};
|
||||
|
||||
private calenderHeaderNode: HTMLDivElement;
|
||||
calenderHeaderNode: any;
|
||||
|
||||
getYearSelectElement(year: number) {
|
||||
getYearSelectElement(year) {
|
||||
const { yearSelectOffset, yearSelectTotal, locale, prefixCls, fullscreen } = this.props;
|
||||
const start = year - (yearSelectOffset as number);
|
||||
const end = start + (yearSelectTotal as number);
|
||||
@@ -61,7 +61,7 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
return months;
|
||||
}
|
||||
|
||||
getMonthSelectElement(month: number, months: number[]) {
|
||||
getMonthSelectElement(month, months) {
|
||||
const props = this.props;
|
||||
const { prefixCls, fullscreen } = props;
|
||||
const options: React.ReactElement<any>[] = [];
|
||||
@@ -84,7 +84,7 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
);
|
||||
}
|
||||
|
||||
onYearChange = (year: string) => {
|
||||
onYearChange = (year) => {
|
||||
const newValue = this.props.value.clone();
|
||||
newValue.year(parseInt(year, 10));
|
||||
|
||||
@@ -94,7 +94,7 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
}
|
||||
}
|
||||
|
||||
onMonthChange = (month: string) => {
|
||||
onMonthChange = (month) => {
|
||||
const newValue = this.props.value.clone();
|
||||
newValue.month(parseInt(month, 10));
|
||||
const onValueChange = this.props.onValueChange;
|
||||
@@ -103,14 +103,14 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
}
|
||||
}
|
||||
|
||||
onTypeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
onTypeChange = (e) => {
|
||||
const onTypeChange = this.props.onTypeChange;
|
||||
if (onTypeChange) {
|
||||
onTypeChange(e.target.value);
|
||||
}
|
||||
}
|
||||
|
||||
getCalenderHeaderNode = (node: HTMLDivElement) => {
|
||||
getCalenderHeaderNode = (node) => {
|
||||
this.calenderHeaderNode = node;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,28 +14,4 @@ describe('Calendar', () => {
|
||||
const value = onSelect.mock.calls[0][0];
|
||||
expect(Moment.isMoment(value)).toBe(true);
|
||||
});
|
||||
|
||||
it('Calendar should change mode by prop', () => {
|
||||
const monthMode = 'month';
|
||||
const yearMode = 'year';
|
||||
const wrapper = mount(
|
||||
<Calendar />
|
||||
);
|
||||
expect(wrapper.state().mode).toEqual(monthMode);
|
||||
wrapper.setProps({ mode: 'year' });
|
||||
expect(wrapper.state().mode).toEqual(yearMode);
|
||||
});
|
||||
|
||||
it('Calendar should switch mode', () => {
|
||||
const monthMode = 'month';
|
||||
const yearMode = 'year';
|
||||
const onPanelChangeStub = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Calendar mode={yearMode} onPanelChange={onPanelChangeStub} />
|
||||
);
|
||||
expect(wrapper.state().mode).toEqual(yearMode);
|
||||
wrapper.instance().setType('date');
|
||||
expect(wrapper.state().mode).toEqual(monthMode);
|
||||
expect(onPanelChangeStub).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
title:
|
||||
zh-CN: 卡片模式
|
||||
en-US: Card
|
||||
---
|
||||
@@ -21,7 +21,7 @@ function onPanelChange(value, mode) {
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div style={{ width: 300, border: '1px solid #d9d9d9', borderRadius: 4 }}>
|
||||
<div style={{ width: 290, border: '1px solid #d9d9d9', borderRadius: 4 }}>
|
||||
<Calendar fullscreen={false} onPanelChange={onPanelChange} />
|
||||
</div>
|
||||
, mountNode);
|
||||
|
||||
@@ -14,7 +14,7 @@ title:
|
||||
This component can be rendered by using `dateCellRender` and `monthCellRender` with the data you need.
|
||||
|
||||
````jsx
|
||||
import { Calendar, Badge } from 'antd';
|
||||
import { Calendar } from 'antd';
|
||||
|
||||
function getListData(value) {
|
||||
let listData;
|
||||
@@ -22,18 +22,18 @@ function getListData(value) {
|
||||
case 8:
|
||||
listData = [
|
||||
{ type: 'warning', content: 'This is warning event.' },
|
||||
{ type: 'success', content: 'This is usual event.' },
|
||||
{ type: 'normal', content: 'This is usual event.' },
|
||||
]; break;
|
||||
case 10:
|
||||
listData = [
|
||||
{ type: 'warning', content: 'This is warning event.' },
|
||||
{ type: 'success', content: 'This is usual event.' },
|
||||
{ type: 'normal', content: 'This is usual event.' },
|
||||
{ type: 'error', content: 'This is error event.' },
|
||||
]; break;
|
||||
case 15:
|
||||
listData = [
|
||||
{ type: 'warning', content: 'This is warning event' },
|
||||
{ type: 'success', content: 'This is very long usual event。。....' },
|
||||
{ type: 'normal', content: 'This is very long usual event。。....' },
|
||||
{ type: 'error', content: 'This is error event 1.' },
|
||||
{ type: 'error', content: 'This is error event 2.' },
|
||||
{ type: 'error', content: 'This is error event 3.' },
|
||||
@@ -51,7 +51,8 @@ function dateCellRender(value) {
|
||||
{
|
||||
listData.map(item => (
|
||||
<li key={item.content}>
|
||||
<Badge status={item.type} text={item.content} />
|
||||
<span className={`event-${item.type}`}>●</span>
|
||||
{item.content}
|
||||
</li>
|
||||
))
|
||||
}
|
||||
@@ -82,20 +83,42 @@ ReactDOM.render(
|
||||
|
||||
````css
|
||||
.events {
|
||||
line-height: 24px;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.events .ant-badge-status {
|
||||
|
||||
.events li {
|
||||
color: #999;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.events li span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.events li span:first-child {
|
||||
font-size: 9px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.event-warning {
|
||||
color: #fac450;
|
||||
}
|
||||
|
||||
.event-normal {
|
||||
color: #108ee9;
|
||||
}
|
||||
|
||||
.event-error {
|
||||
color: #f50;
|
||||
}
|
||||
|
||||
.notes-month {
|
||||
text-align: center;
|
||||
font-size: 28px;
|
||||
}
|
||||
.notes-month section {
|
||||
font-size: 28px;
|
||||
|
||||
@@ -16,10 +16,11 @@ When data is in the form of dates, such as schedules, timetables, prices calenda
|
||||
**Note:** Part of the Calendar's locale is read from `value`. So, please set the locale of `moment` correctly.
|
||||
|
||||
```jsx
|
||||
// The default locale is en-US, if you want to use other locale, just set locale in entry file globaly.
|
||||
// import moment from 'moment';
|
||||
// import 'moment/locale/zh-cn';
|
||||
// moment.locale('zh-cn');
|
||||
import moment from 'moment';
|
||||
|
||||
// It's recommended to set locale in entry file globaly.
|
||||
import 'moment/locale/zh-cn';
|
||||
moment.locale('zh-cn');
|
||||
|
||||
<Calendar
|
||||
dateCellRender={dateCellRender}
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import * as moment from 'moment';
|
||||
import moment from 'moment';
|
||||
import FullCalendar from 'rc-calendar/lib/FullCalendar';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import { PREFIX_CLS } from './Constants';
|
||||
import Header from './Header';
|
||||
import callMoment from '../_util/callMoment';
|
||||
import enUS from './locale/en_US';
|
||||
|
||||
export { HeaderProps } from './Header';
|
||||
import { getComponentLocale, getLocaleCode } from '../_util/getLocale';
|
||||
declare const require: Function;
|
||||
|
||||
function noop() { return null; }
|
||||
|
||||
function zerofixed(v: number) {
|
||||
function zerofixed(v) {
|
||||
if (v < 10) {
|
||||
return `0${v}`;
|
||||
}
|
||||
return `${v}`;
|
||||
}
|
||||
|
||||
export interface CalendarContext {
|
||||
antLocale?: {
|
||||
Calendar?: any,
|
||||
};
|
||||
}
|
||||
|
||||
export type CalendarMode = 'month' | 'year';
|
||||
|
||||
export interface CalendarProps {
|
||||
@@ -40,7 +43,7 @@ export interface CalendarProps {
|
||||
}
|
||||
|
||||
export interface CalendarState {
|
||||
value: moment.Moment;
|
||||
value?: moment.Moment;
|
||||
mode?: CalendarMode;
|
||||
}
|
||||
|
||||
@@ -69,10 +72,18 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
onSelect: PropTypes.func,
|
||||
};
|
||||
|
||||
constructor(props: CalendarProps) {
|
||||
super(props);
|
||||
static contextTypes = {
|
||||
antLocale: PropTypes.object,
|
||||
};
|
||||
|
||||
const value = props.value || props.defaultValue || callMoment(moment);
|
||||
context: CalendarContext;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
// Make sure that moment locale had be set correctly.
|
||||
getComponentLocale(props, context, 'Calendar', () => require('./locale/zh_CN'));
|
||||
|
||||
const value = props.value || props.defaultValue || moment();
|
||||
if (!moment.isMoment(value)) {
|
||||
throw new Error(
|
||||
'The value/defaultValue of Calendar must be a moment object after `antd@2.0`, ' +
|
||||
@@ -88,17 +99,12 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
componentWillReceiveProps(nextProps: CalendarProps) {
|
||||
if ('value' in nextProps) {
|
||||
this.setState({
|
||||
value: nextProps.value!,
|
||||
});
|
||||
}
|
||||
if ('mode' in nextProps && nextProps.mode !== this.props.mode) {
|
||||
this.setState({
|
||||
mode: nextProps.mode!,
|
||||
value: nextProps.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
monthCellRender = (value: moment.Moment) => {
|
||||
monthCellRender = (value) => {
|
||||
const { prefixCls, monthCellRender = noop as Function } = this.props;
|
||||
return (
|
||||
<div className={`${prefixCls}-month`}>
|
||||
@@ -112,7 +118,7 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
);
|
||||
}
|
||||
|
||||
dateCellRender = (value: moment.Moment) => {
|
||||
dateCellRender = (value) => {
|
||||
const { prefixCls, dateCellRender = noop as Function } = this.props;
|
||||
return (
|
||||
<div className={`${prefixCls}-date`}>
|
||||
@@ -126,7 +132,7 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
);
|
||||
}
|
||||
|
||||
setValue = (value: moment.Moment, way: 'select' | 'changePanel') => {
|
||||
setValue = (value, way: 'select' | 'changePanel') => {
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ value });
|
||||
}
|
||||
@@ -139,7 +145,7 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
}
|
||||
}
|
||||
|
||||
setType = (type: string) => {
|
||||
setType = (type) => {
|
||||
const mode = (type === 'date') ? 'month' : 'year';
|
||||
if (this.state.mode !== mode) {
|
||||
this.setState({ mode });
|
||||
@@ -147,33 +153,35 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
}
|
||||
}
|
||||
|
||||
onHeaderValueChange = (value: moment.Moment) => {
|
||||
onHeaderValueChange = (value) => {
|
||||
this.setValue(value, 'changePanel');
|
||||
}
|
||||
|
||||
onHeaderTypeChange = (type: string) => {
|
||||
onHeaderTypeChange = (type) => {
|
||||
this.setType(type);
|
||||
}
|
||||
|
||||
onPanelChange(value: moment.Moment, mode: CalendarMode | undefined) {
|
||||
onPanelChange(value, mode) {
|
||||
const { onPanelChange } = this.props;
|
||||
if (onPanelChange) {
|
||||
onPanelChange(value, mode);
|
||||
}
|
||||
}
|
||||
|
||||
onSelect = (value: moment.Moment) => {
|
||||
onSelect = (value) => {
|
||||
this.setValue(value, 'select');
|
||||
}
|
||||
|
||||
renderCalendar = (locale: any, localeCode: string) => {
|
||||
const { state, props } = this;
|
||||
render() {
|
||||
const { state, props, context } = this;
|
||||
const { value, mode } = state;
|
||||
const localeCode = getLocaleCode(context);
|
||||
if (value && localeCode) {
|
||||
value.locale(localeCode);
|
||||
}
|
||||
const { prefixCls, style, className, fullscreen, dateFullCellRender, monthFullCellRender } = props;
|
||||
const type = (mode === 'year') ? 'month' : 'date';
|
||||
const locale = getComponentLocale(props, context, 'Calendar', () => require('./locale/zh_CN'));
|
||||
|
||||
let cls = className || '';
|
||||
if (fullscreen) {
|
||||
@@ -209,15 +217,4 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<LocaleReceiver
|
||||
componentName="Calendar"
|
||||
defaultLocale={enUS}
|
||||
>
|
||||
{this.renderCalendar}
|
||||
</LocaleReceiver>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,11 @@ title: Calendar
|
||||
**注意:**Calendar 部分 locale 是从 value 中读取,所以请先正确设置 moment 的 locale。
|
||||
|
||||
```jsx
|
||||
// 默认语言为 en-US,所以如果需要使用其他语言,推荐在入口文件全局设置 locale
|
||||
// import moment from 'moment';
|
||||
// import 'moment/locale/zh-cn';
|
||||
// moment.locale('zh-cn');
|
||||
import moment from 'moment';
|
||||
|
||||
// 推荐在入口文件全局设置 locale
|
||||
import 'moment/locale/zh-cn';
|
||||
moment.locale('zh-cn');
|
||||
|
||||
<Calendar
|
||||
dateCellRender={dateCellRender}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
import ar_EG from '../../date-picker/locale/ar_EG';
|
||||
export default ar_EG;
|
||||
@@ -1,2 +0,0 @@
|
||||
import is_IS from '../../date-picker/locale/is_IS';
|
||||
export default is_IS;
|
||||
@@ -1,2 +0,0 @@
|
||||
import ku_IQ from '../../date-picker/locale/ku_IQ';
|
||||
export default ku_IQ;
|
||||
@@ -1,2 +0,0 @@
|
||||
import uk_UA from '../../date-picker/locale/uk_UA';
|
||||
export default uk_UA;
|
||||
@@ -1,10 +1,10 @@
|
||||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
|
||||
@full-calendar-prefix-cls: ~"@{ant-prefix}-fullcalendar";
|
||||
|
||||
.@{full-calendar-prefix-cls} {
|
||||
.reset-component;
|
||||
font-size: @font-size-base;
|
||||
line-height: @line-height-base;
|
||||
outline: none;
|
||||
border-top: @border-width-base @border-style-base @border-color-base;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
|
||||
&-calendar-body {
|
||||
padding: 8px 12px;
|
||||
padding: 8px 8px 14px;
|
||||
}
|
||||
|
||||
table {
|
||||
@@ -46,7 +46,7 @@
|
||||
max-width: 100%;
|
||||
background-color: transparent;
|
||||
width: 100%;
|
||||
height: 256px;
|
||||
height: 246px;
|
||||
}
|
||||
|
||||
table,
|
||||
@@ -91,12 +91,12 @@
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
color: @text-color;
|
||||
border-radius: @border-radius-sm;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: @border-radius-base;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
line-height: 24px;
|
||||
line-height: 22px;
|
||||
transition: all .3s;
|
||||
|
||||
&:hover {
|
||||
@@ -116,7 +116,7 @@
|
||||
|
||||
&-today &-value,
|
||||
&-month-panel-current-cell &-value {
|
||||
box-shadow: 0 0 0 1px @primary-color inset;
|
||||
box-shadow: 0 0 0 1px @primary-color;
|
||||
}
|
||||
|
||||
&-selected-day &-value,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export interface CardGridProps {
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export interface CardMetaProps {
|
||||
prefixCls?: string;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
avatar?: React.ReactNode;
|
||||
title?: React.ReactNode;
|
||||
description?: React.ReactNode;
|
||||
}
|
||||
|
||||
export default (props: CardMetaProps) => {
|
||||
const { prefixCls = 'ant-card', className, avatar, title, description, ...others } = props;
|
||||
const classString = classNames(`${prefixCls}-meta`, className);
|
||||
const avatarDom = avatar ? <div className={`${prefixCls}-meta-avatar`}>{avatar}</div> : null;
|
||||
const titleDom = title ? <div className={`${prefixCls}-meta-title`}>{title}</div> : null;
|
||||
const descriptionDom = description ?
|
||||
<div className={`${prefixCls}-meta-description`}>{description}</div> : null;
|
||||
const MetaDetail = titleDom || descriptionDom ?
|
||||
<div className={`${prefixCls}-meta-detail`}>
|
||||
{titleDom}
|
||||
{descriptionDom}
|
||||
</div> : null;
|
||||
return (
|
||||
<div {...others} className={classString}>
|
||||
{avatarDom}
|
||||
{MetaDetail}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -3,28 +3,24 @@
|
||||
exports[`renders ./components/card/demo/basic.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
style="width:300px"
|
||||
style="width:300px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
Card title
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-extra"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-extra"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
>
|
||||
More
|
||||
</a>
|
||||
</div>
|
||||
More
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -45,23 +41,19 @@ exports[`renders ./components/card/demo/basic.md correctly 1`] = `
|
||||
|
||||
exports[`renders ./components/card/demo/border-less.md correctly 1`] = `
|
||||
<div
|
||||
style="background:#ECECEC;padding:30px"
|
||||
style="background:#ECECEC;padding:30px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card"
|
||||
style="width:300px"
|
||||
style="width:300px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -81,59 +73,17 @@ exports[`renders ./components/card/demo/border-less.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/card/demo/flexible-content.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card ant-card-bordered ant-card-hoverable"
|
||||
style="width:240px"
|
||||
>
|
||||
<div
|
||||
class="ant-card-cover"
|
||||
>
|
||||
<img
|
||||
alt="example"
|
||||
src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<div
|
||||
class="ant-card-meta"
|
||||
>
|
||||
<div
|
||||
class="ant-card-meta-detail"
|
||||
>
|
||||
<div
|
||||
class="ant-card-meta-title"
|
||||
>
|
||||
Europe Street beat
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-meta-description"
|
||||
>
|
||||
www.instagram.com
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/card/demo/grid-card.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card ant-card-bordered ant-card-contain-grid"
|
||||
class="ant-card ant-card-bordered ant-card-no-hovering ant-card-contain-grid"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card Title
|
||||
</div>
|
||||
Card Title
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -141,43 +91,43 @@ exports[`renders ./components/card/demo/grid-card.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-card-grid"
|
||||
style="width:25%;text-align:center"
|
||||
style="width:25%;text-align:center;"
|
||||
>
|
||||
Content
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-grid"
|
||||
style="width:25%;text-align:center"
|
||||
style="width:25%;text-align:center;"
|
||||
>
|
||||
Content
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-grid"
|
||||
style="width:25%;text-align:center"
|
||||
style="width:25%;text-align:center;"
|
||||
>
|
||||
Content
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-grid"
|
||||
style="width:25%;text-align:center"
|
||||
style="width:25%;text-align:center;"
|
||||
>
|
||||
Content
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-grid"
|
||||
style="width:25%;text-align:center"
|
||||
style="width:25%;text-align:center;"
|
||||
>
|
||||
Content
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-grid"
|
||||
style="width:25%;text-align:center"
|
||||
style="width:25%;text-align:center;"
|
||||
>
|
||||
Content
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-grid"
|
||||
style="width:25%;text-align:center"
|
||||
style="width:25%;text-align:center;"
|
||||
>
|
||||
Content
|
||||
</div>
|
||||
@@ -187,183 +137,79 @@ exports[`renders ./components/card/demo/grid-card.md correctly 1`] = `
|
||||
|
||||
exports[`renders ./components/card/demo/in-column.md correctly 1`] = `
|
||||
<div
|
||||
style="background:#ECECEC;padding:30px"
|
||||
style="background:#ECECEC;padding:30px;"
|
||||
>
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left:-8px;margin-right:-8px"
|
||||
style="margin-left:-8px;margin-right:-8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-col-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
Card content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-card"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
Card content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-card"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
Card content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/card/demo/inner.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<p
|
||||
style="font-size:14px;color:rgba(0, 0, 0, 0.85);margin-bottom:16px;font-weight:500"
|
||||
>
|
||||
Group title
|
||||
</p>
|
||||
<div
|
||||
class="ant-card ant-card-bordered ant-card-type-inner"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Inner Card title
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-extra"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
>
|
||||
More
|
||||
</a>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
Inner Card content
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
Card content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card ant-card-bordered ant-card-type-inner"
|
||||
style="margin-top:16px"
|
||||
class="ant-col-8"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
class="ant-card"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Inner Card title
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-extra"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
>
|
||||
More
|
||||
</a>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
Card content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-8"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
class="ant-card"
|
||||
>
|
||||
Inner Card content
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
Card content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -373,19 +219,15 @@ exports[`renders ./components/card/demo/inner.md correctly 1`] = `
|
||||
exports[`renders ./components/card/demo/loading.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card ant-card-loading ant-card-bordered"
|
||||
style="width:34%"
|
||||
style="width:34%;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -396,50 +238,50 @@ exports[`renders ./components/card/demo/loading.md correctly 1`] = `
|
||||
>
|
||||
<p
|
||||
class="ant-card-loading-block"
|
||||
style="width:94%"
|
||||
style="width:94%;"
|
||||
/>
|
||||
<p>
|
||||
<span
|
||||
class="ant-card-loading-block"
|
||||
style="width:28%"
|
||||
style="width:28%;"
|
||||
/>
|
||||
<span
|
||||
class="ant-card-loading-block"
|
||||
style="width:62%"
|
||||
style="width:62%;"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<span
|
||||
class="ant-card-loading-block"
|
||||
style="width:22%"
|
||||
style="width:22%;"
|
||||
/>
|
||||
<span
|
||||
class="ant-card-loading-block"
|
||||
style="width:66%"
|
||||
style="width:66%;"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<span
|
||||
class="ant-card-loading-block"
|
||||
style="width:56%"
|
||||
style="width:56%;"
|
||||
/>
|
||||
<span
|
||||
class="ant-card-loading-block"
|
||||
style="width:39%"
|
||||
style="width:39%;"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<span
|
||||
class="ant-card-loading-block"
|
||||
style="width:21%"
|
||||
style="width:21%;"
|
||||
/>
|
||||
<span
|
||||
class="ant-card-loading-block"
|
||||
style="width:15%"
|
||||
style="width:15%;"
|
||||
/>
|
||||
<span
|
||||
class="ant-card-loading-block"
|
||||
style="width:40%"
|
||||
style="width:40%;"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
@@ -447,90 +289,42 @@ exports[`renders ./components/card/demo/loading.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/card/demo/meta.md correctly 1`] = `
|
||||
exports[`renders ./components/card/demo/no-padding.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
style="width:300px"
|
||||
style="width:240px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-cover"
|
||||
>
|
||||
<img
|
||||
alt="example"
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
style="padding:0;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-meta"
|
||||
class="custom-image"
|
||||
>
|
||||
<div
|
||||
class="ant-card-meta-avatar"
|
||||
>
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle ant-avatar-image"
|
||||
>
|
||||
<img
|
||||
src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-meta-detail"
|
||||
>
|
||||
<div
|
||||
class="ant-card-meta-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-meta-description"
|
||||
>
|
||||
This is the description
|
||||
</div>
|
||||
</div>
|
||||
<img
|
||||
alt="example"
|
||||
src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png"
|
||||
width="100%"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="custom-card"
|
||||
>
|
||||
<h3>
|
||||
Europe Street beat
|
||||
</h3>
|
||||
<p>
|
||||
www.instagram.com
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
class="ant-card-actions"
|
||||
>
|
||||
<li
|
||||
style="width:33.333333333333336%"
|
||||
>
|
||||
<span>
|
||||
<i
|
||||
class="anticon anticon-setting"
|
||||
/>
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
style="width:33.333333333333336%"
|
||||
>
|
||||
<span>
|
||||
<i
|
||||
class="anticon anticon-edit"
|
||||
/>
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
style="width:33.333333333333336%"
|
||||
>
|
||||
<span>
|
||||
<i
|
||||
class="anticon anticon-ellipsis"
|
||||
/>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/card/demo/simple.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
style="width:300px"
|
||||
style="width:300px;"
|
||||
>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
@@ -547,228 +341,3 @@ exports[`renders ./components/card/demo/simple.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/card/demo/tabs.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-card ant-card-bordered ant-card-contain-tabs"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-extra"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
>
|
||||
More
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs ant-tabs-top ant-card-head-tabs ant-tabs-large ant-tabs-line"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-bar"
|
||||
role="tablist"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav-container"
|
||||
>
|
||||
<span
|
||||
class="ant-tabs-tab-prev ant-tabs-tab-btn-disabled"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<span
|
||||
class="ant-tabs-tab-prev-icon"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tabs-tab-next ant-tabs-tab-btn-disabled"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<span
|
||||
class="ant-tabs-tab-next-icon"
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="ant-tabs-nav-wrap"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav-scroll"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav ant-tabs-nav-animated"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-ink-bar ant-tabs-ink-bar-animated"
|
||||
/>
|
||||
<div
|
||||
aria-disabled="false"
|
||||
aria-selected="true"
|
||||
class="ant-tabs-tab-active ant-tabs-tab"
|
||||
role="tab"
|
||||
>
|
||||
tab1
|
||||
</div>
|
||||
<div
|
||||
aria-disabled="false"
|
||||
aria-selected="false"
|
||||
class=" ant-tabs-tab"
|
||||
role="tab"
|
||||
>
|
||||
tab2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-content ant-tabs-content-animated"
|
||||
style="margin-left:0%"
|
||||
>
|
||||
<div
|
||||
aria-hidden="false"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-active"
|
||||
role="tabpanel"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-inactive"
|
||||
role="tabpanel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<p>
|
||||
content1
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<div
|
||||
class="ant-card ant-card-bordered ant-card-contain-tabs"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
/>
|
||||
<div
|
||||
class="ant-tabs ant-tabs-top ant-card-head-tabs ant-tabs-large ant-tabs-line"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-bar"
|
||||
role="tablist"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav-container"
|
||||
>
|
||||
<span
|
||||
class="ant-tabs-tab-prev ant-tabs-tab-btn-disabled"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<span
|
||||
class="ant-tabs-tab-prev-icon"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tabs-tab-next ant-tabs-tab-btn-disabled"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<span
|
||||
class="ant-tabs-tab-next-icon"
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="ant-tabs-nav-wrap"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav-scroll"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav ant-tabs-nav-animated"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-ink-bar ant-tabs-ink-bar-animated"
|
||||
/>
|
||||
<div
|
||||
aria-disabled="false"
|
||||
aria-selected="true"
|
||||
class="ant-tabs-tab-active ant-tabs-tab"
|
||||
role="tab"
|
||||
>
|
||||
article
|
||||
</div>
|
||||
<div
|
||||
aria-disabled="false"
|
||||
aria-selected="false"
|
||||
class=" ant-tabs-tab"
|
||||
role="tab"
|
||||
>
|
||||
app
|
||||
</div>
|
||||
<div
|
||||
aria-disabled="false"
|
||||
aria-selected="false"
|
||||
class=" ant-tabs-tab"
|
||||
role="tab"
|
||||
>
|
||||
project
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-content ant-tabs-content-animated"
|
||||
style="margin-left:0%"
|
||||
>
|
||||
<div
|
||||
aria-hidden="false"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-active"
|
||||
role="tabpanel"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-inactive"
|
||||
role="tabpanel"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-inactive"
|
||||
role="tabpanel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<p>
|
||||
article content
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('Card', () => {
|
||||
});
|
||||
|
||||
function fakeResizeWindowTo(wrapper, width) {
|
||||
Object.defineProperties(wrapper.instance().container, {
|
||||
Object.defineProperties(wrapper.node.container, {
|
||||
offsetWidth: {
|
||||
get() { return width; },
|
||||
configurable: true,
|
||||
@@ -27,11 +27,9 @@ describe('Card', () => {
|
||||
const wrapper = mount(<Card title="xxx">xxx</Card>);
|
||||
fakeResizeWindowTo(wrapper, 1000);
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-card-wider-padding').length).toBe(1);
|
||||
expect(wrapper.hasClass('ant-card-wider-padding')).toBe(true);
|
||||
fakeResizeWindowTo(wrapper, 800);
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-card-wider-padding').length).toBe(0);
|
||||
expect(wrapper.hasClass('ant-card-wider-padding')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,9 +24,3 @@ ReactDOM.render(
|
||||
</Card>
|
||||
, mountNode);
|
||||
````
|
||||
|
||||
<style>
|
||||
.code-box-demo p {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 更灵活的内容展示
|
||||
en-US: Customized content
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以利用 `Card.Meta` 支持更灵活的内容。
|
||||
|
||||
## en-US
|
||||
|
||||
You can use `Card.Meta` to support more flexible content.
|
||||
|
||||
|
||||
````jsx
|
||||
import { Card } from 'antd';
|
||||
const { Meta } = Card;
|
||||
|
||||
ReactDOM.render(
|
||||
<Card
|
||||
hoverable
|
||||
style={{ width: 240 }}
|
||||
cover={<img alt="example" src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png" />}
|
||||
>
|
||||
<Meta
|
||||
title="Europe Street beat"
|
||||
description="www.instagram.com"
|
||||
/>
|
||||
</Card>
|
||||
, mountNode);
|
||||
````
|
||||
@@ -22,7 +22,7 @@ const gridStyle = {
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<Card title="Card Title">
|
||||
<Card title="Card Title" noHovering>
|
||||
<Card.Grid style={gridStyle}>Content</Card.Grid>
|
||||
<Card.Grid style={gridStyle}>Content</Card.Grid>
|
||||
<Card.Grid style={gridStyle}>Content</Card.Grid>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 内部卡片
|
||||
en-US: Inner card
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以放在普通卡片内部,展示多层级结构的信息。
|
||||
|
||||
## en-US
|
||||
|
||||
It can be placed inside the ordinary card to display the information of the multilevel structure.
|
||||
|
||||
````jsx
|
||||
import { Card } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Card title="Card title">
|
||||
<p
|
||||
style={{
|
||||
fontSize: 14,
|
||||
color: 'rgba(0, 0, 0, 0.85)',
|
||||
marginBottom: 16,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
Group title
|
||||
</p>
|
||||
<Card
|
||||
type="inner"
|
||||
title="Inner Card title"
|
||||
extra={<a href="#">More</a>}
|
||||
>
|
||||
Inner Card content
|
||||
</Card>
|
||||
<Card
|
||||
style={{ marginTop: 16 }}
|
||||
type="inner"
|
||||
title="Inner Card title"
|
||||
extra={<a href="#">More</a>}
|
||||
>
|
||||
Inner Card content
|
||||
</Card>
|
||||
</Card>
|
||||
, mountNode);
|
||||
````
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
order: 9
|
||||
title:
|
||||
zh-CN: 支持更多内容配置
|
||||
en-US: Support more content configuration
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
一种支持封面、头像、标题和描述信息的卡片。
|
||||
|
||||
## en-US
|
||||
|
||||
A Card that supports `cover`, `avatar`, `title` and `description`.
|
||||
|
||||
````jsx
|
||||
import { Card, Icon, Avatar } from 'antd';
|
||||
const { Meta } = Card;
|
||||
|
||||
ReactDOM.render(
|
||||
<Card
|
||||
style={{ width: 300 }}
|
||||
cover={<img alt="example" src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png" />}
|
||||
actions={[<Icon type="setting" />, <Icon type="edit" />, <Icon type="ellipsis" />]}
|
||||
>
|
||||
<Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title="Card title"
|
||||
description="This is the description"
|
||||
/>
|
||||
</Card>
|
||||
, mountNode);
|
||||
````
|
||||
43
components/card/demo/no-padding.md
Normal file
43
components/card/demo/no-padding.md
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 更灵活的内容展示
|
||||
en-US: Customized content
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以调整默认边距,设定宽度。
|
||||
|
||||
## en-US
|
||||
|
||||
Customizing default width and margin.
|
||||
|
||||
|
||||
````jsx
|
||||
import { Card } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Card style={{ width: 240 }} bodyStyle={{ padding: 0 }}>
|
||||
<div className="custom-image">
|
||||
<img alt="example" width="100%" src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png" />
|
||||
</div>
|
||||
<div className="custom-card">
|
||||
<h3>Europe Street beat</h3>
|
||||
<p>www.instagram.com</p>
|
||||
</div>
|
||||
</Card>
|
||||
, mountNode);
|
||||
````
|
||||
|
||||
````css
|
||||
.custom-image img {
|
||||
display: block;
|
||||
}
|
||||
.custom-card {
|
||||
padding: 10px 16px;
|
||||
}
|
||||
.custom-card p {
|
||||
color: #999;
|
||||
}
|
||||
````
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user