Compare commits

..

25 Commits

Author SHA1 Message Date
Wei Zhu
eac43ed892 Update release date 2018-04-28 11:06:01 +08:00
Wei Zhu
f5250cabe1 Revert "Bump 2.13.15"
This reverts commit 9c78bfaee4.
2018-04-28 11:05:28 +08:00
Wei Zhu
125085398c Remoove arguments, fix lint 2018-04-28 11:04:10 +08:00
Wei Zhu
9c78bfaee4 Bump 2.13.15 2018-04-01 21:23:48 +08:00
Wei Zhu
35d11d1cb1 docs: Add release date 2018-04-01 21:20:04 +08:00
ojab
992c8d1562 Release 2.13.14 2018-03-27 08:08:57 +00:00
ojab
a3fc715d3a Compat less 3 (#9633)
Fix #7850
2018-03-12 16:08:14 +08:00
愚道
03da3efae7 fix pub script error 2018-03-09 19:23:21 +08:00
愚指导
97d3422043 release 2.13.13 (#9590) 2018-03-09 18:04:06 +08:00
Wei Zhu
a609518d28 Remove unsed variable 2018-03-08 17:52:58 +08:00
Wei Zhu
ef6d7a5d90 Fix upload list update logic when beforeUpload return false
Porting from 626ebf2063
2018-03-08 17:43:24 +08:00
Wei Zhu
5be1bad67f Update snapshot 2018-03-08 14:24:37 +08:00
Wei Zhu
b70fede5de correct grammar 2018-02-26 20:36:53 +08:00
Wei Zhu
358aa84fef Bump 2.13.12 2018-02-26 20:01:00 +08:00
Wei Zhu
6f716d1003 Add 2.13.12 change log 2018-02-26 20:00:36 +08:00
Wei Zhu
739c6ead54 Lock @types/react and @types/react-dom version 2018-02-26 19:46:55 +08:00
Wei Zhu
a7255ee885 Fix #8885 2018-02-26 19:21:24 +08:00
junjing.zhang
06ff0d44db fix lint fail - use babel-eslint-8.0.2 2018-01-03 19:06:37 +08:00
junjing.zhang
e96b0fc768 fix components/collapse test fail 2018-01-03 19:06:37 +08:00
junjing.zhang
8489fedb4c anchor scroll supports complete href link - test
anchor scroll supports complete href link, e.g. http://www.example.com/#id, not just #id
2018-01-03 19:06:37 +08:00
junjing.zhang
adf98d3c19 anchor scroll supports complete href link
anchor scroll supports complete href link, e.g. http://www.example.com/#id, not just #id
2018-01-03 19:06:37 +08:00
afc163
ba87b45903 Fix snapshot for moment@2.20 2017-12-17 18:57:10 +08:00
afc163
1e8830637f Fix submenu popup issue when specified unexisted defaultOpenKeys
close #8475
2017-12-17 18:54:31 +08:00
nikogu
2275195e15 bump 2.13.11 2017-12-02 17:47:19 +08:00
niko
dcf9d4c294 2.13.11 changelog (#8403) 2017-12-02 17:38:41 +08:00
768 changed files with 17207 additions and 190399 deletions

10
.babelrc Normal file
View File

@@ -0,0 +1,10 @@
{
"env": {
"test": {
"presets": ["es2015", "react", "stage-0"],
"plugins": [
"add-module-exports"
]
}
}
}

View File

@@ -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.

View File

@@ -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',
}
},
};

View File

@@ -18,9 +18,4 @@ module.exports = {
snapshotSerializers: [
'enzyme-to-json/serializer'
],
globals: {
'ts-jest': {
tsConfigFile: './tsconfig.test.json',
}
},
};

View File

@@ -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
}
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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 @@
## 参与共建 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](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),更好的问题更容易获得帮助。

View File

@@ -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 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
Read our [contributing guide](https://ant.design/docs/react/contributing).
`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
```

View File

@@ -19,14 +19,12 @@ Array [
"Checkbox",
"Col",
"DatePicker",
"Divider",
"Dropdown",
"Form",
"Icon",
"Input",
"InputNumber",
"Layout",
"List",
"LocaleProvider",
"message",
"Menu",

View File

@@ -1,4 +0,0 @@
// https://github.com/moment/moment/issues/3650
export default function callMoment(moment: any, ...args: any[]) {
return (moment.default || moment)(...args);
}

View 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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
},
};

View File

@@ -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 {

View File

@@ -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');

View File

@@ -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);
});
});

View File

@@ -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>

View File

@@ -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"

View File

@@ -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

View File

@@ -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 | - |

View File

@@ -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, {

View File

@@ -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 | 无 |

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

View File

@@ -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');
});
});

View File

@@ -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"

View File

@@ -1,8 +1,8 @@
---
order: 2
title:
zh-CN: 静态位置
en-US: Static Anchor
zh-CN: 固定
en-US: Fixed Anchor
---
## zh-CN

View File

@@ -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 |

View File

@@ -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;

View File

@@ -18,7 +18,7 @@ title: Anchor
| 成员 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| affix | 固定模式 | boolean | true |
| affix | 固定模式 | boolean | false |
| bounds | 锚点区域边界 | number | 5(px) |
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | number | |
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | |

View File

@@ -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 {

View File

@@ -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);
}

View File

@@ -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 />

View File

@@ -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);

View File

@@ -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&lt;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&lt;{ 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 |

View File

@@ -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>

View File

@@ -22,7 +22,6 @@ const dataSource = ['12345', '23456', '34567'];
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| allowClear | 支持清除, 单选模式有效 | boolean | false |
| autoFocus | 自动获取焦点 | boolean | false |
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false |
| children (自动完成的数据源) | 自动完成的数据源 | React.ReactElement<OptionProps> / Array&lt;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() | 获取焦点 |

View File

@@ -7,8 +7,6 @@
@autocomplete-prefix-cls: ~"@{select-prefix-cls}-auto-complete";
.@{autocomplete-prefix-cls} {
.reset-component;
&.@{select-prefix-cls} {
.@{select-prefix-cls} {
&-selection {

View File

@@ -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"

View File

@@ -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>
);
}

View File

@@ -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,
});

View File

@@ -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);

View File

@@ -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>

View File

@@ -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();

View File

@@ -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 ? (

View File

@@ -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';

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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"
>

View File

@@ -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);
});
});

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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);
````

View File

@@ -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` | `''` |

View File

@@ -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}
/>
);

View File

@@ -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' } | '' |

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import PropTypes from 'prop-types';
export interface BreadcrumbItemProps {

View File

@@ -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();
});

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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"

View File

@@ -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>
`;

View File

@@ -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();
});
});

View File

@@ -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;

View File

@@ -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>
);
}
}

View File

@@ -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>

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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;
}
& > & {

View File

@@ -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

View File

@@ -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);
});
});

View File

@@ -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);

View File

@@ -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;

View File

@@ -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}

View File

@@ -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>
);
}
}

View File

@@ -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}

View File

@@ -1,2 +0,0 @@
import ar_EG from '../../date-picker/locale/ar_EG';
export default ar_EG;

View File

@@ -1,2 +0,0 @@
import is_IS from '../../date-picker/locale/is_IS';
export default is_IS;

View File

@@ -1,2 +0,0 @@
import ku_IQ from '../../date-picker/locale/ku_IQ';
export default ku_IQ;

View File

@@ -1,2 +0,0 @@
import uk_UA from '../../date-picker/locale/uk_UA';
export default uk_UA;

View File

@@ -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,

View File

@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import classNames from 'classnames';
export interface CardGridProps {

View File

@@ -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>
);
};

View File

@@ -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>
`;

View File

@@ -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);
});
});

View File

@@ -24,9 +24,3 @@ ReactDOM.render(
</Card>
, mountNode);
````
<style>
.code-box-demo p {
margin: 0;
}
</style>

View File

@@ -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);
````

View File

@@ -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>

View File

@@ -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);
````

View File

@@ -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);
````

View 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