mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-09 10:59:19 +08:00
Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5400cacd13 | ||
|
|
ee8ac670b9 | ||
|
|
449db1499b | ||
|
|
b0c7a714ad | ||
|
|
8457267dad | ||
|
|
24bd14d843 | ||
|
|
f93e2a8df0 | ||
|
|
3c9ccccf61 | ||
|
|
27232a8561 | ||
|
|
26c5c8e11c | ||
|
|
7dc0328c60 | ||
|
|
f703e00c0f | ||
|
|
f206cc4c90 | ||
|
|
c073e78074 | ||
|
|
ad808953fd | ||
|
|
ae8f3c5b56 | ||
|
|
88d428bcc4 | ||
|
|
7879421ec2 | ||
|
|
d4b5b701bd | ||
|
|
926425d8ec | ||
|
|
0e6ac6bc4c | ||
|
|
be9ed0388c | ||
|
|
d6288e5994 | ||
|
|
524a421d72 | ||
|
|
4da0ae4f42 | ||
|
|
02422417d6 | ||
|
|
01f5b61982 | ||
|
|
e7cf2a4f3f | ||
|
|
ed7d82f4cd | ||
|
|
8fa50cfddc | ||
|
|
751b597df1 | ||
|
|
850e713e7f | ||
|
|
e64f04cee5 | ||
|
|
8dcdd12bef | ||
|
|
cbec9c5db1 | ||
|
|
9cc05c530b | ||
|
|
b75201485d | ||
|
|
88d470220b | ||
|
|
51dae474cc | ||
|
|
5d2a2cc39b | ||
|
|
64e549be9d | ||
|
|
19be7db53f | ||
|
|
563f8120cd | ||
|
|
1903990315 | ||
|
|
733a4cdc40 | ||
|
|
45d2182137 | ||
|
|
0fa41ebfb9 | ||
|
|
451ef78778 | ||
|
|
d0f2ff83b6 | ||
|
|
9afec1a638 | ||
|
|
5aafe0d8de | ||
|
|
df4509bbda | ||
|
|
156242053f | ||
|
|
5c29fe41f7 | ||
|
|
db68af8e72 | ||
|
|
c04707d3e3 | ||
|
|
c32256c204 | ||
|
|
228b7328d3 | ||
|
|
3b08a6479c | ||
|
|
0baef0627e | ||
|
|
74932b5de9 | ||
|
|
ec3f20936e | ||
|
|
2df6476572 | ||
|
|
4d2bdfd93d | ||
|
|
a91a7208a6 | ||
|
|
2d0f532f73 | ||
|
|
0d013be7fa | ||
|
|
5aea5b24ef | ||
|
|
0ec4276eab | ||
|
|
4844d92709 | ||
|
|
e4974ac72a | ||
|
|
0a48c62dcb | ||
|
|
9b81fe86d9 | ||
|
|
64899c5da2 | ||
|
|
a7b384112e | ||
|
|
5782253a0f | ||
|
|
c72612435e | ||
|
|
8dd48e0e26 | ||
|
|
6bf9ac4e04 | ||
|
|
f98005a696 | ||
|
|
e6dd9a93d0 | ||
|
|
985d20ad80 | ||
|
|
6c16d738ee | ||
|
|
b9cba392c9 | ||
|
|
8f01552e0f | ||
|
|
b9863f044c | ||
|
|
0acbba9838 | ||
|
|
1fde7de404 | ||
|
|
52e649a9fb | ||
|
|
6d91290f95 | ||
|
|
7042e09a99 | ||
|
|
7af9a01a40 | ||
|
|
b39d96ec75 | ||
|
|
9360c02129 | ||
|
|
d8ea555ee8 | ||
|
|
a3962d5869 | ||
|
|
03b4edee4a | ||
|
|
1e95ad9bad | ||
|
|
b08dd6d1f9 | ||
|
|
224281f425 | ||
|
|
8895776fad | ||
|
|
ebe2379a95 | ||
|
|
5cebea6b47 | ||
|
|
954c3a13f1 | ||
|
|
b6f9ac4058 | ||
|
|
0a0e14d610 | ||
|
|
616ecf1980 | ||
|
|
ef720db420 |
@@ -39,6 +39,7 @@ const eslintrc = {
|
||||
'jsx-a11y/no-static-element-interactions': 0,
|
||||
'jsx-a11y/anchor-has-content': 0,
|
||||
'react/no-danger': 0,
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"newlineAfterBlock": false,
|
||||
"maxCharPerLine": false,
|
||||
"excludedFiles": [
|
||||
"components/layout/style/mixin.less",
|
||||
"components/grid/style/mixin.less",
|
||||
"components/style/core/base.less",
|
||||
"components/style/core/iconfont.less",
|
||||
"components/style/core/normalize.less",
|
||||
|
||||
@@ -9,6 +9,47 @@ If you want to read change logs before `2.0.0`, please visit [GitHub](https://gi
|
||||
|
||||
---
|
||||
|
||||
## 2.4.2
|
||||
|
||||
`2016-11-13`
|
||||
|
||||
* Fix `Dropdown.Button` cannot popup menu.[#3815](https://github.com/ant-design/ant-design/issues/3815)
|
||||
|
||||
## 2.4.1
|
||||
|
||||
`2016-11-11`
|
||||
|
||||
* Fix `2.4.0` missing index files.
|
||||
|
||||
## 2.4.0
|
||||
|
||||
`2016-11-11`
|
||||
|
||||
* Adjust components structure.
|
||||
* New [Anchor](https://ant.design/components/anchor) Component.
|
||||
* Fix less variables `@font-size-base` and `@text-color`, add `@font-size-lg` `@text-color-secondary`.
|
||||
* Add new props `selectedKeys` for `Transfer` component [#3729]. (https://github.com/ant-design/ant-design/issues/3729)
|
||||
* Add `Tag` selected status.
|
||||
* Fix `Dropdown.Button` not support `visible` and `onVisibleChange`. [#3779](https://github.com/ant-design/ant-design/issues/3779)
|
||||
* Fix `Now` button of `DatePicker[showTime]`. [#3748](https://github.com/ant-design/ant-design/issues/3748)
|
||||
* Fix style of `Steps` in vertical mode. [#3760](https://github.com/ant-design/ant-design/issues/3760)
|
||||
* Fix style compatibility of `Spin` in IE10+.[#3755](https://github.com/ant-design/ant-design/issues/3755)
|
||||
* Fix default style of `Carousel` component.
|
||||
* Fix focus logic of `Mention` component. [#3801](https://github.com/ant-design/ant-design/issues/3801)
|
||||
* Fix animate bug of `Progress` component. [#3784](https://github.com/ant-design/ant-design/issues/3784)
|
||||
* Fix focus bug of `Select` component. [#3778](https://github.com/ant-design/ant-design/issues/3778)
|
||||
* Fix `TimePicker` not support `format="HH"` bug. [#3793](https://github.com/ant-design/ant-design/issues/3793)
|
||||
* Improve perfermance of `Table` selection. [#3757](https://github.com/ant-design/ant-design/pull/3757)
|
||||
* Improve Carousel default UI style.
|
||||
* Improve style of `Checkbox` and `Radio`. [#3590](https://github.com/ant-design/ant-design/issues/3590)
|
||||
* Fix style of DatePickek, Form, Table.
|
||||
|
||||
## 2.3.2
|
||||
|
||||
`2016-11-09`
|
||||
|
||||
* Fix dead loop while using `getFieldProps`.
|
||||
|
||||
## 2.3.1
|
||||
|
||||
`2016-11-07`
|
||||
|
||||
@@ -9,6 +9,46 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 2.4.2
|
||||
|
||||
`2016-11-13`
|
||||
|
||||
* 修复 `Dropdown.Button` 不弹出的问题。[#3815](https://github.com/ant-design/ant-design/issues/3815)
|
||||
|
||||
## 2.4.1
|
||||
|
||||
`2016-11-11`
|
||||
|
||||
* 修复 `2.4.0` 组件 index 文件丢失的问题。
|
||||
|
||||
## 2.4.0
|
||||
|
||||
`2016-11-11`
|
||||
|
||||
* 调整了组件的导航结构。
|
||||
* 新增 [Anchor](https://ant.design/components/anchor) 锚点组件。
|
||||
* 整理了样式变量,修复 `@font-size-base` 和 `@text-color` 在部分组件无效的问题,新增 `@font-size-lg` `@text-color-secondary`,并移除了部分无用的变量。
|
||||
* `Transfer` 组件新增了受控属性 `selectedKeys`。[#3729](https://github.com/ant-design/ant-design/issues/3729)
|
||||
* `Tag` 新增选中状态。
|
||||
* 修复 `Dropdown.Button` 不支持 `visible` 和 `onVisibleChange` 的问题。[#3779](https://github.com/ant-design/ant-design/issues/3779)
|
||||
* 修复 `DatePicker[showTime]`` 的 `此刻` 按钮。[#3748](https://github.com/ant-design/ant-design/issues/3748)
|
||||
* 修复 `Steps` 竖直方向的样式。[#3760](https://github.com/ant-design/ant-design/issues/3760)
|
||||
* 修复 `Spin` 组件在 IE10+ 的样式问题。[#3755](https://github.com/ant-design/ant-design/issues/3755)
|
||||
* 修复 `Mention` 组件的 focus 逻辑. [#3801](https://github.com/ant-design/ant-design/issues/3801)
|
||||
* 修复 `Progress` 组件的动画问题。[#3784](https://github.com/ant-design/ant-design/issues/3784)
|
||||
* 修复 `Select` 搜索时的丢失焦点问题。[#3778](https://github.com/ant-design/ant-design/issues/3778)
|
||||
* 修复 `TimePicker` 不支持 `format="HH"` 等格式的问题。[#3793](https://github.com/ant-design/ant-design/issues/3793)
|
||||
* 优化了 `Table` 选择的性能。[#3757](https://github.com/ant-design/ant-design/pull/3757)
|
||||
* 优化 `Carousel` 的默认样式。
|
||||
* 优化 `Checkbox` 和 `Radio` 的样式。[#3590](https://github.com/ant-design/ant-design/issues/3590)
|
||||
* 修复 `DatePicker`、`Form`、`Table` 等组件的样式细节。
|
||||
|
||||
## 2.3.2
|
||||
|
||||
`2016-11-09`
|
||||
|
||||
* 修复使用 `getFieldProps` 会导致死循环的问题。
|
||||
|
||||
## 2.3.1
|
||||
|
||||
`2016-11-07`
|
||||
|
||||
@@ -97,6 +97,7 @@ tsconfig.json
|
||||
- [Development tool](http://ant-tool.github.io/)
|
||||
- [React components](http://react-component.github.io/)
|
||||
- [Mobile UI](http://mobile.ant.design)
|
||||
- [Motion](https://motion.ant.design)
|
||||
- [React style guide](https://github.com/react-component/react-component.github.io/blob/master/docs/zh-cn/component-code-style.md)
|
||||
- [React component design guide](https://github.com/react-component/react-component.github.io/blob/master/docs/zh-cn/component-design.md)
|
||||
- [Developer Instruction](https://github.com/ant-design/ant-design/wiki/Development)
|
||||
@@ -106,6 +107,7 @@ tsconfig.json
|
||||
- [CodePen boilerplate](http://codepen.io/benjycui/pen/KgPZrE?editors=001) for bug reports
|
||||
- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design)
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome all contributions, please read our [CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) first. You can submit any ideas as [pull requests](https://github.com/ant-design/ant-design/pulls) or as a [GitHub issue](https://github.com/ant-design/ant-design/issues). If you'd like to improve code, check out the [Development Instruction](https://github.com/ant-design/ant-design/wiki/Development) and have a good time! :)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Other
|
||||
type: Navigation
|
||||
title: Affix
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 固钉
|
||||
type: Other
|
||||
type: Navigation
|
||||
title: Affix
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Feedback
|
||||
title: Alert
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 警告提示
|
||||
type: Views
|
||||
type: Feedback
|
||||
title: Alert
|
||||
---
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
}
|
||||
|
||||
&-icon {
|
||||
font-size: 14px;
|
||||
font-size: @font-size-lg;
|
||||
top: 9px;
|
||||
left: 16px;
|
||||
position: absolute;
|
||||
@@ -71,7 +71,7 @@
|
||||
cursor: pointer;
|
||||
|
||||
.@{iconfont-css-prefix}-cross {
|
||||
color: @legend-color;
|
||||
color: @text-color-secondary;
|
||||
transition: color .3s ease;
|
||||
&:hover {
|
||||
color: #404040;
|
||||
@@ -113,7 +113,7 @@
|
||||
}
|
||||
|
||||
&-with-description &-message {
|
||||
font-size: 14px;
|
||||
font-size: @font-size-lg;
|
||||
color: @heading-color;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
|
||||
93
components/anchor/AnchorLink.tsx
Normal file
93
components/anchor/AnchorLink.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import AnchorHelper, { scrollTo } from './anchorHelper';
|
||||
|
||||
export interface AnchorLinkProps {
|
||||
href: string;
|
||||
onClick: (href: string) => void;
|
||||
active?: boolean;
|
||||
prefixCls?: string;
|
||||
children?: any;
|
||||
title?: Element;
|
||||
bounds: number;
|
||||
target?: () => HTMLElement | Window;
|
||||
affix?: boolean;
|
||||
}
|
||||
|
||||
export default class AnchorLink extends React.Component<AnchorLinkProps, any> {
|
||||
static contextTypes = {
|
||||
anchorHelper: React.PropTypes.any,
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
anchorHelper: React.PropTypes.any,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
href: '#',
|
||||
prefixCls: 'ant-anchor',
|
||||
};
|
||||
|
||||
context: {
|
||||
anchorHelper: AnchorHelper;
|
||||
};
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
}
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
anchorHelper: this.context.anchorHelper,
|
||||
};
|
||||
}
|
||||
|
||||
renderAnchorLink = (child) => {
|
||||
const { href } = child.props;
|
||||
if (href) {
|
||||
this.context.anchorHelper.addLink(href);
|
||||
return React.cloneElement(child, {
|
||||
onClick: this.context.anchorHelper.scrollTo,
|
||||
prefixCls: this.props.prefixCls,
|
||||
});
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
scrollTo = (e) => {
|
||||
const { onClick, href } = this.props;
|
||||
const { anchorHelper } = this.context;
|
||||
e.preventDefault();
|
||||
if (onClick) {
|
||||
onClick(href);
|
||||
} else {
|
||||
e.stopPreventDefault();
|
||||
const scrollToFn = anchorHelper ? anchorHelper.scrollTo : scrollTo;
|
||||
scrollToFn(href);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, href, children, title, bounds, affix } = this.props;
|
||||
const { anchorHelper } = this.context;
|
||||
const active = affix && anchorHelper && anchorHelper.getCurrentAnchor(bounds) === href;
|
||||
const cls = classNames({
|
||||
[`${prefixCls}-link`]: true,
|
||||
[`${prefixCls}-link-active`]: active,
|
||||
});
|
||||
return (
|
||||
<div className={cls}>
|
||||
<a
|
||||
ref={(component) => component && active && anchorHelper ? anchorHelper.setActiveAnchor(component) : null}
|
||||
className={`${prefixCls}-link-title`}
|
||||
onClick={this.scrollTo}
|
||||
href={href}
|
||||
title={typeof title === 'string' ? title : ''}
|
||||
>
|
||||
{title}
|
||||
</a>
|
||||
{React.Children.map(children, this.renderAnchorLink)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
107
components/anchor/anchorHelper.tsx
Normal file
107
components/anchor/anchorHelper.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import getScroll from '../_util/getScroll';
|
||||
import getRequestAnimationFrame from '../_util/getRequestAnimationFrame';
|
||||
|
||||
export const reqAnimFrame = getRequestAnimationFrame();
|
||||
|
||||
export const easeInOutCubic = (t, b, c, d) => {
|
||||
const cc = c - b;
|
||||
t /= d / 2;
|
||||
if (t < 1) {
|
||||
return cc / 2 * t * t * t + b;
|
||||
}
|
||||
return cc / 2 * ((t -= 2) * t * t + 2) + b;
|
||||
};
|
||||
|
||||
export function getDefaultTarget() {
|
||||
return typeof window !== 'undefined' ?
|
||||
window : null;
|
||||
}
|
||||
|
||||
export function getOffsetTop(element): number {
|
||||
if (!element) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!element.getClientRects().length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const rect = element.getBoundingClientRect();
|
||||
|
||||
if ( rect.width || rect.height ) {
|
||||
const doc = element.ownerDocument;
|
||||
const docElem = doc.documentElement;
|
||||
return rect.top - docElem.clientTop;
|
||||
}
|
||||
|
||||
return rect.top;
|
||||
}
|
||||
|
||||
export function scrollTo(href, target = getDefaultTarget) {
|
||||
const scrollTop = getScroll(target(), true);
|
||||
const targetElement = document.querySelector(href);
|
||||
if (!targetElement) {
|
||||
return;
|
||||
}
|
||||
const offsetTop = getOffsetTop(targetElement);
|
||||
const targetScrollTop = scrollTop + offsetTop;
|
||||
const startTime = Date.now();
|
||||
const frameFunc = () => {
|
||||
const timestamp = Date.now();
|
||||
const time = timestamp - startTime;
|
||||
window.scrollTo(window.pageXOffset, easeInOutCubic(time, scrollTop, targetScrollTop, 450));
|
||||
if (time < 450) {
|
||||
reqAnimFrame(frameFunc);
|
||||
}
|
||||
};
|
||||
reqAnimFrame(frameFunc);
|
||||
history.pushState(null, undefined, href);
|
||||
}
|
||||
|
||||
class AnchorHelper {
|
||||
private links: Array<string>;
|
||||
private currentAnchor: HTMLElement | null;
|
||||
private _activeAnchor: string;
|
||||
|
||||
constructor() {
|
||||
this.links = [];
|
||||
this.currentAnchor = null;
|
||||
this._activeAnchor = '';
|
||||
}
|
||||
|
||||
addLink(link) {
|
||||
if (this.links.indexOf(link) === -1) {
|
||||
this.links.push(link);
|
||||
}
|
||||
}
|
||||
|
||||
getCurrentActiveAnchor(): HTMLElement | null {
|
||||
return this.currentAnchor;
|
||||
}
|
||||
|
||||
setActiveAnchor(component) {
|
||||
this.currentAnchor = component;
|
||||
}
|
||||
|
||||
getCurrentAnchor(bounds = 5) {
|
||||
let activeAnchor = '';
|
||||
this.links.forEach(section => {
|
||||
const target = document.querySelector(section);
|
||||
if (target) {
|
||||
const top = getOffsetTop(target);
|
||||
const bottom = top + target.clientHeight;
|
||||
if ((top <= bounds) && (bottom >= -bounds)) {
|
||||
activeAnchor = section;
|
||||
}
|
||||
}
|
||||
});
|
||||
this._activeAnchor = activeAnchor || this._activeAnchor;
|
||||
return this._activeAnchor;
|
||||
}
|
||||
|
||||
scrollTo(href, target = getDefaultTarget) {
|
||||
scrollTo(href, target);
|
||||
}
|
||||
}
|
||||
|
||||
export default AnchorHelper;
|
||||
36
components/anchor/demo/basic.md
Normal file
36
components/anchor/demo/basic.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
order: 0
|
||||
title:
|
||||
zh-CN: 基本
|
||||
en-US: Basic
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法。
|
||||
|
||||
## en-US
|
||||
|
||||
The simplest usage.
|
||||
|
||||
```jsx
|
||||
import { Anchor } from 'antd';
|
||||
const { Link } = Anchor;
|
||||
|
||||
ReactDOM.render(
|
||||
<Anchor>
|
||||
<Link href="#components-anchor-demo-basic" title="Basic demo" />
|
||||
<Link href="#components-anchor-demo-fixed" title="Fixed demo" />
|
||||
<Link href="#API" title="API">
|
||||
<Link href="#Anchor-Props" title="Anchor Props" />
|
||||
<Link href="#Link-Props" title="Link Props" />
|
||||
</Link>
|
||||
</Anchor>
|
||||
, mountNode);
|
||||
```
|
||||
|
||||
<style>
|
||||
.code-box-demo .ant-affix {
|
||||
z-index: 11;
|
||||
}
|
||||
</style>
|
||||
30
components/anchor/demo/fixed.md
Normal file
30
components/anchor/demo/fixed.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 固定
|
||||
en-US: Fixed Anchor
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
不浮动,状态不随页面滚动变化。
|
||||
|
||||
## en-US
|
||||
|
||||
Do not change state when page is scrolling.
|
||||
|
||||
```jsx
|
||||
import { Anchor } from 'antd';
|
||||
const { Link } = Anchor;
|
||||
|
||||
ReactDOM.render(
|
||||
<Anchor affix={false}>
|
||||
<Link href="#components-anchor-demo-basic" title="Basic demo" />
|
||||
<Link href="#components-anchor-demo-fixed" title="Fixed demo" />
|
||||
<Link href="#API" title="API">
|
||||
<Link href="#Anchor-Props" title="Anchor Props" />
|
||||
<Link href="#Link-Props" title="Link Props" />
|
||||
</Link>
|
||||
</Anchor>
|
||||
, mountNode);
|
||||
```
|
||||
29
components/anchor/index.en-US.md
Normal file
29
components/anchor/index.en-US.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
category: Components
|
||||
type: Other
|
||||
cols: 1
|
||||
title: Anchor
|
||||
---
|
||||
|
||||
Hyperlinks to scroll on one page.
|
||||
|
||||
## When To Use
|
||||
|
||||
For displaying anchor hyperlinks on page, and jump between them.
|
||||
|
||||
## API
|
||||
|
||||
### Anchor Props
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|--------------|-----------------------|----------|--------------|
|
||||
| offsetTop | Pixels to offset from top when calculating position of scroll | Number | 0 |
|
||||
| offsetBottom | Pixels to offset from bottom when calculating position of scroll | Number | - |
|
||||
| bounds | Bounding distance of anchor area | Number | 5(px) |
|
||||
|
||||
### Link Props
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|-------------|----------------|--------------------|--------------|
|
||||
| href | target of hyperlink | String | |
|
||||
| title | content of hyperlink | React.Node | |
|
||||
130
components/anchor/index.tsx
Normal file
130
components/anchor/index.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import AnchorLink from './AnchorLink';
|
||||
import Affix from '../affix';
|
||||
import AnchorHelper, { getDefaultTarget } from './anchorHelper';
|
||||
|
||||
export interface AnchorProps {
|
||||
target: () => HTMLElement | Window;
|
||||
children: React.ReactNode;
|
||||
prefixCls?: string;
|
||||
offsetTop?: number;
|
||||
bounds?: number;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
affix?: boolean;
|
||||
}
|
||||
|
||||
export default class Anchor extends React.Component<AnchorProps, any> {
|
||||
static Link = AnchorLink;
|
||||
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-anchor',
|
||||
affix: true,
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
anchorHelper: React.PropTypes.any,
|
||||
};
|
||||
|
||||
refs: {
|
||||
ink?: any;
|
||||
};
|
||||
|
||||
private scrollEvent: any;
|
||||
private anchorHelper: AnchorHelper;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
activeAnchor: null,
|
||||
};
|
||||
this.anchorHelper = new AnchorHelper();
|
||||
}
|
||||
|
||||
handleScroll = () => {
|
||||
this.setState({
|
||||
activeAnchor: this.anchorHelper.getCurrentAnchor(this.props.bounds),
|
||||
});
|
||||
}
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
anchorHelper: this.anchorHelper,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.handleScroll();
|
||||
this.updateInk();
|
||||
this.scrollEvent = addEventListener((this.props.target || getDefaultTarget)(), 'scroll', this.handleScroll);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.scrollEvent) {
|
||||
this.scrollEvent.remove();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.updateInk();
|
||||
}
|
||||
|
||||
updateInk = () => {
|
||||
const activeAnchor = this.anchorHelper.getCurrentActiveAnchor();
|
||||
if (activeAnchor) {
|
||||
this.refs.ink.style.top = `${activeAnchor.offsetTop + activeAnchor.clientHeight / 2 - 4.5}px`;
|
||||
}
|
||||
}
|
||||
|
||||
renderAnchorLink = (child) => {
|
||||
const { href } = child.props;
|
||||
if (href) {
|
||||
this.anchorHelper.addLink(href);
|
||||
return React.cloneElement(child, {
|
||||
onClick: this.anchorHelper.scrollTo,
|
||||
prefixCls: this.props.prefixCls,
|
||||
bounds: this.props.bounds,
|
||||
affix: this.props.affix,
|
||||
});
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, offsetTop, style, className = '', affix } = this.props;
|
||||
const { activeAnchor } = this.state;
|
||||
const inkClass = classNames({
|
||||
[`${prefixCls}-ink-ball`]: true,
|
||||
visible: !!activeAnchor,
|
||||
});
|
||||
|
||||
const wrapperClass = classNames({
|
||||
[`${prefixCls}-wrapper`]: true,
|
||||
[className]: !!className,
|
||||
});
|
||||
|
||||
const anchorClass = classNames({
|
||||
[`${prefixCls}`]: true,
|
||||
'fixed': !affix,
|
||||
});
|
||||
|
||||
const anchorContent = (
|
||||
<div className={wrapperClass} style={style}>
|
||||
<div className={anchorClass}>
|
||||
<div className={`${prefixCls}-ink`} >
|
||||
<span className={inkClass} ref="ink" />
|
||||
</div>
|
||||
{React.Children.map(this.props.children, this.renderAnchorLink)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return affix === false ? anchorContent : (
|
||||
<Affix offsetTop={offsetTop}>
|
||||
{anchorContent}
|
||||
</Affix>
|
||||
);
|
||||
}
|
||||
}
|
||||
30
components/anchor/index.zh-CN.md
Normal file
30
components/anchor/index.zh-CN.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 锚点
|
||||
cols: 1
|
||||
type: Other
|
||||
title: Anchor
|
||||
---
|
||||
|
||||
用于跳转到页面指定位置。
|
||||
|
||||
## 何时使用
|
||||
|
||||
需要展现当前页面上可供跳转的锚点链接,以及快速在锚点之间跳转。
|
||||
|
||||
## API
|
||||
|
||||
### Anchor Props
|
||||
|
||||
| 成员 | 说明 | 类型 | 默认值 |
|
||||
|-------------|----------------|--------------------|--------------|
|
||||
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | Number | |
|
||||
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | Number | |
|
||||
| bounds | 锚点区域边界 | Number | 5(px) |
|
||||
|
||||
### Link Props
|
||||
|
||||
| 成员 | 说明 | 类型 | 默认值 |
|
||||
|-------------|----------------|--------------------|--------------|
|
||||
| href | 锚点链接 | String | |
|
||||
| title | 文字内容 | React.Node | |
|
||||
70
components/anchor/style/index.less
Normal file
70
components/anchor/style/index.less
Normal file
@@ -0,0 +1,70 @@
|
||||
@import "../../style/themes/default";
|
||||
|
||||
.@{ant-prefix} {
|
||||
&-anchor {
|
||||
position: relative;
|
||||
&-wrapper {
|
||||
padding: 6px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
&-ink {
|
||||
position: absolute;
|
||||
width: 9px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
&:before {
|
||||
content: ' ';
|
||||
position: relative;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-color: @border-color-split;
|
||||
margin: 0 auto;
|
||||
}
|
||||
&-ball {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 9px;
|
||||
border: 3px solid @primary-color;
|
||||
background-color: white;
|
||||
transition: top .3s ease-in-out;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
&.visible {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.fixed &-ink &-ink-ball {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-anchor-link {
|
||||
padding: 4px 0 4px 16px;
|
||||
line-height: 1;
|
||||
|
||||
&-title {
|
||||
display: block;
|
||||
position: relative;
|
||||
transition: all .3s;
|
||||
color: @text-color;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&-active > &-title {
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
& > & {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
cols: 1
|
||||
title: AutoComplete
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 自动完成
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
cols: 1
|
||||
title: AutoComplete
|
||||
---
|
||||
|
||||
@@ -19,7 +19,9 @@ import { BackTop } from 'antd';
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<BackTop />
|
||||
Scroll down to see the bottom right <strong>gray</strong> button.
|
||||
Scroll down to see the bottom-right
|
||||
<strong style={{ color: 'rgba(64, 64, 64, 0.6)' }}> gray </strong>
|
||||
button.
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
|
||||
@@ -22,7 +22,9 @@ ReactDOM.render(
|
||||
<BackTop>
|
||||
<div className="ant-back-top-inner">UP</div>
|
||||
</BackTop>
|
||||
Scroll down to see the bottom right <strong>blue</strong> button.
|
||||
Scroll down to see the bottom-right
|
||||
<strong style={{ color: '#57c5f7' }}> blue </strong>
|
||||
button.
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Other
|
||||
type: Navigation
|
||||
title: BackTop
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Other
|
||||
type: Navigation
|
||||
subtitle: 回到顶部
|
||||
title: BackTop
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Badge
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 徽标数
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Badge
|
||||
---
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
height: 20px;
|
||||
border-radius: 10px;
|
||||
min-width: 20px;
|
||||
background: @error-color;
|
||||
background: @highlight-color;
|
||||
border: 1px solid transparent;
|
||||
color: #fff;
|
||||
line-height: 18px;
|
||||
text-align: center;
|
||||
padding: 0 6px;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
white-space: nowrap;
|
||||
transform-origin: -10% center;
|
||||
z-index: 10;
|
||||
@@ -42,7 +42,7 @@
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
border-radius: 100%;
|
||||
background: @error-color;
|
||||
background: @highlight-color;
|
||||
z-index: 10;
|
||||
box-shadow: 0 0 0 1px #fff;
|
||||
}
|
||||
@@ -109,15 +109,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
a & {
|
||||
&-count:hover {
|
||||
background: tint(@error-color, 20%);
|
||||
}
|
||||
&-count:active {
|
||||
background: shade(@error-color, 5%);
|
||||
}
|
||||
}
|
||||
|
||||
.@{number-prefix-cls} {
|
||||
overflow: hidden;
|
||||
&-only {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@breadcrumb-prefix-cls: ~"@{ant-prefix}-breadcrumb";
|
||||
|
||||
.@{breadcrumb-prefix-cls} {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
font-size: @font-size-base;
|
||||
|
||||
a {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Basic
|
||||
type: General
|
||||
title: Button
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Basic
|
||||
type: General
|
||||
title: Button
|
||||
subtitle: 按钮
|
||||
---
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
|
||||
&.disabled,
|
||||
&[disabled] {
|
||||
cursor: @cursor-disabled;
|
||||
cursor: not-allowed;
|
||||
> * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
cols: 1
|
||||
title: Calendar
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
subtitle: 日历
|
||||
cols: 1
|
||||
title: Calendar
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
.@{full-calendar-prefix-cls} {
|
||||
font-size: @font-size-base;
|
||||
line-height: 1.5;
|
||||
line-height: @line-height-base;
|
||||
outline: none;
|
||||
border-top: 1px solid @border-color-base;
|
||||
|
||||
&-month-select {
|
||||
margin-left: 5px;
|
||||
@@ -30,8 +32,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
outline: none;
|
||||
border-top: 1px solid @legend-border-color;
|
||||
&-date-panel {
|
||||
position: relative;
|
||||
outline: none;
|
||||
@@ -201,7 +201,7 @@
|
||||
}
|
||||
|
||||
&-fullscreen &-today &-value {
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Card
|
||||
cols: 1
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Card
|
||||
subtitle: 卡片
|
||||
cols: 1
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
padding: 0 24px;
|
||||
|
||||
&-title {
|
||||
font-size: 14px;
|
||||
font-size: @font-size-lg;
|
||||
display: inline-block;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Carousel
|
||||
---
|
||||
|
||||
@@ -29,13 +29,10 @@ For more info on the parameters, refer to the https://github.com/akiran/react-sl
|
||||
<style>
|
||||
.ant-carousel .slick-slide {
|
||||
text-align: center;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
background: #71B5DE;
|
||||
height: 160px;
|
||||
line-height: 160px;
|
||||
background: #364d79;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
#components-carousel-demo-vertical .ant-carousel {
|
||||
margin-right: 35px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Carousel
|
||||
subtitle: 走马灯
|
||||
---
|
||||
@@ -30,13 +30,10 @@ subtitle: 走马灯
|
||||
<style>
|
||||
.ant-carousel .slick-slide {
|
||||
text-align: center;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
background: #71B5DE;
|
||||
height: 160px;
|
||||
line-height: 130px;
|
||||
background: #506b9e;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
#components-carousel-demo-vertical .ant-carousel {
|
||||
margin-right: 35px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -138,14 +138,9 @@
|
||||
}
|
||||
|
||||
// Dots
|
||||
|
||||
.slick-slider {
|
||||
padding-bottom: 45px;
|
||||
}
|
||||
|
||||
.slick-dots {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
bottom: 6px;
|
||||
list-style: none;
|
||||
display: block;
|
||||
text-align: center;
|
||||
@@ -156,62 +151,48 @@
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin: 0 5px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
margin: 0 2px;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
button {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
display: block;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
cursor: pointer;
|
||||
background: #000;
|
||||
opacity: 0.3;
|
||||
display: inline-block;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 7px;
|
||||
outline: none;
|
||||
line-height: 0;
|
||||
font-size: 0;
|
||||
color: transparent;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
transition: all .3s;
|
||||
&:hover,
|
||||
&:focus {
|
||||
outline: none;
|
||||
&:before {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
content: "•";
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 18px;
|
||||
font-family: arial, sans-serif;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
color: gray;
|
||||
transition: all .3s;
|
||||
opacity: 0.25;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
&.slick-active button:before {
|
||||
color: black;
|
||||
opacity: 0.75;
|
||||
&.slick-active button {
|
||||
background: #fff;
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 3px rgba(0, 0, 0, .25);
|
||||
&:hover,
|
||||
&:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{ant-prefix}-carousel-vertical {
|
||||
.slick-slider {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.slick-dots {
|
||||
width: 20px;
|
||||
bottom: auto;
|
||||
right: -35px;
|
||||
top: 0;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: Cascader
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: Cascader
|
||||
subtitle: 级联选择
|
||||
---
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
z-index: 2;
|
||||
background: #fff;
|
||||
top: 50%;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
color: #ccc;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
@@ -63,7 +63,7 @@
|
||||
cursor: pointer;
|
||||
transition: color 0.3s ease, opacity 0.15s ease;
|
||||
&:hover {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
height: 12px;
|
||||
margin-top: -6px;
|
||||
line-height: 12px;
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
.iconfont-size-under-12px(9px);
|
||||
&:before {
|
||||
transition: transform 0.2s ease;
|
||||
@@ -95,7 +95,7 @@
|
||||
}
|
||||
}
|
||||
&-menus {
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
background: #fff;
|
||||
position: absolute;
|
||||
z-index: @zindex-dropdown;
|
||||
@@ -173,14 +173,14 @@
|
||||
&:after {
|
||||
.iconfont-font("\e61f");
|
||||
.iconfont-size-under-12px(8px);
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
& &-keyword {
|
||||
color: @error-color;
|
||||
color: @highlight-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: Checkbox
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 多选框
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: Checkbox
|
||||
---
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
&:hover,
|
||||
&-focused {
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: #bbb;
|
||||
border-color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,14 +92,8 @@
|
||||
.@{checkbox-prefix-cls}-checked,
|
||||
.@{checkbox-prefix-cls}-indeterminate {
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: @primary-color;
|
||||
background-color: @primary-color;
|
||||
}
|
||||
.@{checkbox-prefix-cls}-wrapper:hover &,
|
||||
&:hover {
|
||||
.@{checkbox-inner-prefix-cls} {
|
||||
border-color: @primary-color;
|
||||
}
|
||||
border-color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +116,7 @@
|
||||
|
||||
& + span {
|
||||
color: #ccc;
|
||||
cursor: @cursor-disabled;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
import { Col } from '../layout';
|
||||
import { Col } from '../grid';
|
||||
export default Col;
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
import '../../style/index.less';
|
||||
import '../../layout/style/index.less';
|
||||
import '../../grid/style/index.less';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Collapse
|
||||
cols: 1
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Data Display
|
||||
title: Collapse
|
||||
subtitle: 折叠面板
|
||||
cols: 1
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
padding-left: 32px;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
.collapse-close();
|
||||
.iconfont-mixin();
|
||||
position: absolute;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
line-height: 40px;
|
||||
|
||||
@@ -57,16 +57,22 @@ export default function createPicker(TheCalendar) {
|
||||
this.setState({ tempValue });
|
||||
},
|
||||
|
||||
// Clear temp value when hide picker panel
|
||||
// Clear temp value and trigger onChange when hide DatePicker[showTime] panel
|
||||
handleOpenChange(open) {
|
||||
const { showTime, onOpenChange } = this.props;
|
||||
const { tempValue } = this.state;
|
||||
if (!open) {
|
||||
if (showTime && tempValue) {
|
||||
this.handleChange(tempValue);
|
||||
}
|
||||
this.setState({
|
||||
tempValue: undefined,
|
||||
// tricky code to avoid triggering onChange multiple times
|
||||
// when click `Now` button
|
||||
let tempValue;
|
||||
this.setState(prevState => {
|
||||
tempValue = prevState.tempValue;
|
||||
return {
|
||||
tempValue: undefined,
|
||||
};
|
||||
}, () => {
|
||||
if (showTime && tempValue) {
|
||||
this.handleChange(tempValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (onOpenChange) {
|
||||
|
||||
@@ -7,18 +7,26 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法。
|
||||
最简单的用法,在浮层中可以选择或者输入日期。
|
||||
|
||||
## en-US
|
||||
|
||||
The most basic usage.
|
||||
Basic use case. Users can select or input a date in panel.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
function onChange(date, dateString) {
|
||||
console.log(date, dateString);
|
||||
}
|
||||
|
||||
ReactDOM.render(<DatePicker onChange={onChange} />, mountNode);
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker onChange={onChange} /><br />
|
||||
<MonthPicker onChange={onChange} /><br />
|
||||
<RangePicker onChange={onChange} />
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -1,28 +1,23 @@
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 指定不可选择日期
|
||||
en-US: Specify the date that cannot be selected
|
||||
zh-CN: 不可选择日期和时间
|
||||
en-US: Disabled Date & Time
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
设置 `disabledDate` 方法,来确定不可选时段。
|
||||
设置 `disabledTime` 方法,来确定 showTime 的 RangePicker 的不可选时间段。
|
||||
|
||||
如上例:不可选择今天之后的日期。
|
||||
可用 `disabledDate` 和 `disabledTime` 分别禁止选择部分日期和时间,其中 `disabledTime` 需要和 `showTime` 一起使用。
|
||||
|
||||
## en-US
|
||||
|
||||
Specify unselectable period by `disabledDate`.
|
||||
|
||||
As in the example above: you can't select a date later than today.
|
||||
Disabled part of dates and time by `disabledDate` and `disabledTime` respectively, and `disabledTime` only works with `showTime`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
function newArray(start, end) {
|
||||
function range(start, end) {
|
||||
const result = [];
|
||||
for (let i = start; i < end; i++) {
|
||||
result.push(i);
|
||||
@@ -31,20 +26,33 @@ function newArray(start, end) {
|
||||
}
|
||||
|
||||
|
||||
const disabledDate = function (current) {
|
||||
// can not select days after today
|
||||
return current && current.valueOf() > Date.now();
|
||||
};
|
||||
function disabledDate(current) {
|
||||
// can not select days before today and today
|
||||
return current && current.valueOf() < Date.now();
|
||||
}
|
||||
|
||||
function disabledTime(time, type) {
|
||||
console.log('disabledTime', time, type);
|
||||
function disabledDateTime() {
|
||||
return {
|
||||
disabledHours() {
|
||||
return range(0, 60).splice(4, 20);
|
||||
},
|
||||
disabledMinutes() {
|
||||
return range(30, 60);
|
||||
},
|
||||
disabledSeconds() {
|
||||
return [55, 56];
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function disabledRangeTime(_, type) {
|
||||
if (type === 'start') {
|
||||
return {
|
||||
disabledHours() {
|
||||
return newArray(0, 60).splice(4, 20);
|
||||
return range(0, 60).splice(4, 20);
|
||||
},
|
||||
disabledMinutes() {
|
||||
return newArray(30, 60);
|
||||
return range(30, 60);
|
||||
},
|
||||
disabledSeconds() {
|
||||
return [55, 56];
|
||||
@@ -53,10 +61,10 @@ function disabledTime(time, type) {
|
||||
}
|
||||
return {
|
||||
disabledHours() {
|
||||
return newArray(0, 60).splice(20, 4);
|
||||
return range(0, 60).splice(20, 4);
|
||||
},
|
||||
disabledMinutes() {
|
||||
return newArray(0, 31);
|
||||
return range(0, 31);
|
||||
},
|
||||
disabledSeconds() {
|
||||
return [55, 56];
|
||||
@@ -64,10 +72,12 @@ function disabledTime(time, type) {
|
||||
};
|
||||
}
|
||||
|
||||
ReactDOM.render(<div>
|
||||
<DatePicker disabledDate={disabledDate} />
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker disabledDate={disabledDate} disabledTime={disabledDateTime} showTime />
|
||||
<br />
|
||||
<RangePicker showTime disabledDate={disabledDate} disabledTime={disabledTime} />
|
||||
</div>
|
||||
, mountNode);
|
||||
<RangePicker disabledDate={disabledDate} disabledTime={disabledRangeTime} showTime />
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 5
|
||||
order: 4
|
||||
title:
|
||||
zh-CN: 禁用
|
||||
en-US: Disabled
|
||||
@@ -16,8 +16,18 @@ A disabled state of the `DatePicker`.
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
const dateFormat = 'YYYY-MM-DD';
|
||||
ReactDOM.render(
|
||||
<DatePicker defaultValue={moment('2015-06-06', 'YYYY-MM-DD')} disabled />
|
||||
, mountNode);
|
||||
<div>
|
||||
<DatePicker defaultValue={moment('2015-06-06', dateFormat)} disabled /><br />
|
||||
<MonthPicker defaultValue={moment('2015-06', 'YYYY-MM')} disabled /><br />
|
||||
<RangePicker
|
||||
defaultValue={[moment('2015-06-06', dateFormat), moment('2015-06-06', dateFormat)]}
|
||||
disabled
|
||||
/>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
34
components/date-picker/demo/format.md
Normal file
34
components/date-picker/demo/format.md
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 日期格式
|
||||
en-US: Date Format
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `format` 属性,可以自定义日期显示格式。
|
||||
|
||||
## en-US
|
||||
|
||||
We can set the date format by `format`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
const dateFormat = 'YYYY/MM/DD';
|
||||
const monthFormat = 'YYYY/MM';
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker defaultValue={moment('2015/01/01', dateFormat)} format={dateFormat} /><br />
|
||||
<MonthPicker defaultValue={moment('2015/01', monthFormat)} format={monthFormat} /><br />
|
||||
<RangePicker
|
||||
defaultValue={[moment('2015/01/01', dateFormat), moment('2015/01/01', dateFormat)]}
|
||||
format={dateFormat}
|
||||
/><br />
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 日期格式
|
||||
en-US: Date format
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `format` 属性,可以自定义你需要的日期显示格式,如 `YYYY/MM/DD`。
|
||||
|
||||
## en-US
|
||||
|
||||
By using `format`, you can customize the format(such as `YYYY/MM/DD`) the date is displayed in.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
const format = 'YYYY/MM/DD';
|
||||
ReactDOM.render(
|
||||
<DatePicker defaultValue={moment('2015/01/01', format)} format={format} />
|
||||
, mountNode);
|
||||
````
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 10
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 国际化
|
||||
en-US: Locale
|
||||
@@ -7,24 +7,26 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
通过 `locale` 语言, 默认支持 `en_US`,`zh_CN`。
|
||||
通过 `locale` 设置语言, 默认支持 `en_US`,`zh_CN`。
|
||||
|
||||
moment 会自动使用当前时区,如果需要使用别的时区,则需要自行设置,设置方法请参考 [下面的文档](/components/date-picker/#DatePicker)。
|
||||
moment 会自动使用当前时区,如果需要使用别的时区,则需要自行设置,设置方法请参考示例代码中的注释。
|
||||
|
||||
## en-US
|
||||
|
||||
Use locale to set the language. `en_US`, `zh_CN` are supported by default.
|
||||
|
||||
moment will use your time zone automatically. If you want to set other time zone, please set it by yourself. [More](/components/date-picker/#DatePicker)
|
||||
moment will use your time zone automatically. If you want to set other time zone, please set it by yourself.
|
||||
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import enUS from 'antd/lib/date-picker/locale/en_US';
|
||||
import moment from 'moment-timezone/moment-timezone';
|
||||
|
||||
// It's recommended to set moment locale and time zone globally in entry file,
|
||||
// otherwise, you need to set it by `value` or `defaultValue`.
|
||||
// moment.locale('en');
|
||||
|
||||
// The following data is copied from https://github.com/moment/moment-timezone/blob/develop/data/packed/latest.json
|
||||
// moment.tz.add('Europe/London|GMT BST BDST|0 -10 -20|0101010101010101010101010101010101010101010101010121212121210101210101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2axa0 Rc0 1fA0 14M0 1fc0 1g00 1co0 1dc0 1co0 1oo0 1400 1dc0 19A0 1io0 1io0 WM0 1o00 14o0 1o00 17c0 1io0 17c0 1fA0 1a00 1lc0 17c0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1cM0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1io0 1qM0 Dc0 2Rz0 Dc0 1zc0 Oo0 1zc0 Rc0 1wo0 17c0 1iM0 FA0 xB0 1fA0 1a00 14o0 bb0 LA0 xB0 Rc0 1wo0 11A0 1o00 17c0 1fA0 1a00 1fA0 1cM0 1fA0 1a00 17c0 1fA0 1a00 1io0 17c0 1lc0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1a00 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1tA0 IM0 90o0 U00 1tA0 U00 1tA0 U00 1tA0 U00 1tA0 WM0 1qM0 WM0 1qM0 WM0 1tA0 U00 1tA0 U00 1tA0 11z0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 14o0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|10e6');
|
||||
// moment.tz.setDefault('Europe/London')
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
order: 9
|
||||
title:
|
||||
zh-CN: 月选择器
|
||||
en-US: MonthPicker
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `MonthPicker` 实现月选择器。
|
||||
|
||||
## en-US
|
||||
|
||||
You can get a month selector by using `MonthPicker`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
const MonthPicker = DatePicker.MonthPicker;
|
||||
ReactDOM.render(
|
||||
<MonthPicker defaultValue={moment('2015-12', 'YYYY-MM')} />
|
||||
, mountNode);
|
||||
````
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 日期范围二
|
||||
en-US: Date range, case 2
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `RangePicker` 实现日期范围选择有更好的交互体验。
|
||||
|
||||
## en-US
|
||||
|
||||
By using `RangePicker` to specify a date range, you can achieve a better interactive experience.
|
||||
|
||||
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
function onChange(dates, dateStrings) {
|
||||
console.log('From: ', dates[0], ', to: ', dates[1]);
|
||||
console.log('From: ', dateStrings[0], ', to: ', dateStrings[1]);
|
||||
}
|
||||
ReactDOM.render(<div>
|
||||
<RangePicker style={{ width: 200 }} onChange={onChange} />
|
||||
<br />
|
||||
<RangePicker showTime format="YYYY/MM/DD HH:mm:ss" onChange={onChange} />
|
||||
</div>, mountNode);
|
||||
````
|
||||
@@ -1,27 +1,48 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 三种大小
|
||||
en-US: Three sizes
|
||||
en-US: Three Sizes
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
三种大小的输入框,大的用在表单中,中的为默认。
|
||||
三种大小的输入框,若不设置,则为 `default`。
|
||||
|
||||
## en-US
|
||||
|
||||
The input box comes in three sizes. `large` is used in the form, while the medium size is the default.
|
||||
The input box comes in three sizes. `default` will be used if `size` is omitted.
|
||||
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import { DatePicker, Radio } from 'antd';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker size="large" />
|
||||
<DatePicker />
|
||||
<DatePicker size="small" />
|
||||
</div>
|
||||
, mountNode);
|
||||
class PickerSizesDemo extends React.Component {
|
||||
state = {
|
||||
size: 'default',
|
||||
};
|
||||
|
||||
handleSizeChange = (e) => {
|
||||
this.setState({ size: e.target.value });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { size } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Radio.Group value={size} onChange={this.handleSizeChange}>
|
||||
<Radio.Button value="large">Large</Radio.Button>
|
||||
<Radio.Button value="default">Default</Radio.Button>
|
||||
<Radio.Button value="small">Small</Radio.Button>
|
||||
</Radio.Group><br /><br />
|
||||
<DatePicker size={size} /><br />
|
||||
<MonthPicker size={size} /><br />
|
||||
<RangePicker size={size} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<PickerSizesDemo />, mountNode);
|
||||
````
|
||||
|
||||
@@ -1,69 +1,81 @@
|
||||
---
|
||||
order: 7
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 日期范围一
|
||||
en-US: Date range, case 1
|
||||
zh-CN: 自定义日期范围选择
|
||||
en-US: Customized Range Picker
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以设置 `disabledDate` 方法,来约束开始和结束日期。
|
||||
当 `RangePicker` 无法满足业务需求时,可以使用两个 `DatePicker` 实现类似的功能。
|
||||
> * 通过设置 `disabledDate` 方法,来约束开始和结束日期。
|
||||
> * 通过 `open` `onOpenChange` 来优化交互。
|
||||
|
||||
## en-US
|
||||
|
||||
You can use the `disabledDate` property to limit the start and end dates.
|
||||
|
||||
When `RangePicker` is not satisfied your requirements, try to implement similar functionality with two `DatePicker`.
|
||||
> * Use the `disabledDate` property to limit the start and end dates.
|
||||
> * Imporve user experience with `open` `onOpenChange`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
|
||||
const DateRange = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
startValue: null,
|
||||
endValue: null,
|
||||
endOpen: false,
|
||||
};
|
||||
},
|
||||
disabledStartDate(startValue) {
|
||||
if (!startValue || !this.state.endValue) {
|
||||
class DateRange extends React.Component {
|
||||
state = {
|
||||
startValue: null,
|
||||
endValue: null,
|
||||
endOpen: false,
|
||||
};
|
||||
|
||||
disabledStartDate = (startValue) => {
|
||||
const endValue = this.state.endValue;
|
||||
if (!startValue || !endValue) {
|
||||
return false;
|
||||
}
|
||||
return startValue.valueOf() > this.state.endValue.valueOf();
|
||||
},
|
||||
disabledEndDate(endValue) {
|
||||
if (!endValue || !this.state.startValue) {
|
||||
return startValue.valueOf() > endValue.valueOf();
|
||||
}
|
||||
|
||||
disabledEndDate = (endValue) => {
|
||||
const startValue = this.state.startValue;
|
||||
if (!endValue || !startValue) {
|
||||
return false;
|
||||
}
|
||||
return endValue.valueOf() <= this.state.startValue.valueOf();
|
||||
},
|
||||
onChange(field, value) {
|
||||
return endValue.valueOf() <= startValue.valueOf();
|
||||
}
|
||||
|
||||
onChange = (field, value) => {
|
||||
this.setState({
|
||||
[field]: value,
|
||||
});
|
||||
},
|
||||
onStartChange(value) {
|
||||
}
|
||||
|
||||
onStartChange = (value) => {
|
||||
this.onChange('startValue', value);
|
||||
},
|
||||
onEndChange(value) {
|
||||
}
|
||||
|
||||
onEndChange = (value) => {
|
||||
this.onChange('endValue', value);
|
||||
},
|
||||
handleStartOpenChange(open) {
|
||||
}
|
||||
|
||||
handleStartOpenChange = (open) => {
|
||||
if (!open) {
|
||||
this.setState({ endOpen: true });
|
||||
}
|
||||
},
|
||||
handleEndOpenChange(open) {
|
||||
}
|
||||
|
||||
handleEndOpenChange = (open) => {
|
||||
this.setState({ endOpen: open });
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
const { startValue, endValue, endOpen } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<DatePicker
|
||||
disabledDate={this.disabledStartDate}
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value={this.state.startValue}
|
||||
value={startValue}
|
||||
placeholder="Start"
|
||||
onChange={this.onStartChange}
|
||||
onOpenChange={this.handleStartOpenChange}
|
||||
@@ -72,18 +84,16 @@ const DateRange = React.createClass({
|
||||
disabledDate={this.disabledEndDate}
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value={this.state.endValue}
|
||||
value={endValue}
|
||||
placeholder="End"
|
||||
onChange={this.onEndChange}
|
||||
open={this.state.endOpen}
|
||||
open={endOpen}
|
||||
onOpenChange={this.handleEndOpenChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<DateRange />
|
||||
, mountNode);
|
||||
ReactDOM.render(<DateRange />, mountNode);
|
||||
````
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
order: 4
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 日期时间选择
|
||||
en-US: To choose time
|
||||
en-US: Choose Time
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
@@ -11,10 +11,11 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
This property provide an additional time selection. When `showTime` is an Object, its properties will be passed on to `TimePicker`, which is a built-in function.
|
||||
This property provide an additional time selection. When `showTime` is an Object, its properties will be passed on to built-in `TimePicker`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
function onChange(value, dateString) {
|
||||
console.log('Selected Time: ', value);
|
||||
@@ -22,6 +23,16 @@ function onChange(value, dateString) {
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<DatePicker showTime format="YYYY-MM-DD HH:mm:ss" placeholder="Select Time" onChange={onChange} />
|
||||
, mountNode);
|
||||
<div>
|
||||
<DatePicker
|
||||
showTime={{ format: 'HH:mm' }} format="YYYY-MM-DD HH:mm"
|
||||
placeholder="Select Time" onChange={onChange}
|
||||
/><br />
|
||||
<RangePicker
|
||||
showTime={{ format: 'HH:mm' }} format="YYYY-MM-DD HH:mm"
|
||||
placeholder={['Start Time', 'End Time']} onChange={onChange}
|
||||
/>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: DatePicker
|
||||
---
|
||||
|
||||
To select/input a date.
|
||||
To select or input a date. There are three kinds of picker:
|
||||
* DatePicker
|
||||
* MonthPicker
|
||||
* RangePicker
|
||||
|
||||
## When To Use
|
||||
|
||||
@@ -12,7 +15,7 @@ By clicking the input box, you can select a date from a popup calendar.
|
||||
|
||||
## API
|
||||
|
||||
Note: Part of locale of DatePicker, MonthPicker, RangePicker is read from value. So, please set the locale of moment correctly.
|
||||
**Note:** Part of locale of DatePicker, MonthPicker, RangePicker is read from value. So, please set the locale of moment correctly.
|
||||
|
||||
```jsx
|
||||
import moment from 'moment';
|
||||
@@ -50,6 +53,7 @@ The following APIs are shared by DatePicker, MonthPicker, RangePicker.
|
||||
| open | open state of picker | bool | - |
|
||||
| onOpenChange | a callback function, can be executed whether the popup calendar is popped up or closed | function(status) | - |
|
||||
| showTime | to provide an additional time selection | Object/Boolean | [TimePicker Options](/components/time-picker/#api) |
|
||||
| disabledTime | to specify the time that cannot be selected | function(date) | - |
|
||||
|
||||
### MonthPicker
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
title: DatePicker
|
||||
subtitle: 日期选择框
|
||||
---
|
||||
|
||||
输入或选择日期的控件。
|
||||
输入或选择日期的控件,包括以下三种形式。
|
||||
* DatePicker
|
||||
* MonthPicker
|
||||
* RangePicker
|
||||
|
||||
## 何时使用
|
||||
|
||||
@@ -13,7 +16,7 @@ subtitle: 日期选择框
|
||||
|
||||
## API
|
||||
|
||||
注意:DatePicker、MonthPicker、RangePicker 部分 locale 是从 value 中读取,所以请先正确设置 moment 的 locale。
|
||||
**注意:**DatePicker、MonthPicker、RangePicker 部分 locale 是从 value 中读取,所以请先正确设置 moment 的 locale。
|
||||
|
||||
```jsx
|
||||
import moment from 'moment';
|
||||
@@ -51,6 +54,7 @@ moment.locale('zh-cn');
|
||||
| open | 控制弹层是否展开 | bool | - |
|
||||
| onOpenChange | 弹出日历和关闭日历的回调 | function(status) | 无 |
|
||||
| showTime | 增加时间选择功能 | Object or Boolean | [TimePicker Options](/components/time-picker/#api) |
|
||||
| disabledTime | 不可选择的时间 | function(date) | 无 |
|
||||
|
||||
### MonthPicker
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
padding: 0 2px;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
.@{calendar-prefix-cls}-next-year-btn {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
font-family: Arial, "Hiragino Sans GB", "Microsoft Yahei", "Microsoft Sans Serif", sans-serif;
|
||||
padding: 0 5px;
|
||||
font-size: 16px;
|
||||
@@ -168,7 +168,7 @@
|
||||
&-date {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
border-radius: @border-radius-sm;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@@ -281,7 +281,7 @@
|
||||
|
||||
.@{calendar-prefix-cls}-clear-btn:after {
|
||||
.iconfont-font("\e62e");
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
color: #ccc;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
@@ -291,7 +291,7 @@
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-clear-btn:hover:after {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-ok-btn {
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
.@{calendar-prefix-cls}-decade-panel-decade {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
.@{calendar-prefix-cls}-month-panel-month {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
right: 7px;
|
||||
background: #fff;
|
||||
top: 50%;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
color: #ccc;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
@@ -53,7 +53,7 @@
|
||||
cursor: pointer;
|
||||
transition: color 0.3s ease, opacity 0.15s ease;
|
||||
&:hover {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,14 +69,14 @@
|
||||
height: 12px;
|
||||
line-height: 12px;
|
||||
right: 8px;
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
top: 50%;
|
||||
margin-top: -6px;
|
||||
&:after {
|
||||
content: "\e6bb";
|
||||
font-family: "anticon";
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
font-size: @font-size-base;
|
||||
color: @text-color-secondary;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
vertical-align: bottom;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-range-picker-separator {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-range {
|
||||
@@ -53,7 +53,7 @@
|
||||
float: right;
|
||||
.@{calendar-prefix-cls} {
|
||||
&-time-picker-inner {
|
||||
margin-left: 21px;
|
||||
margin-left: 3%;
|
||||
border-left: 1px solid @border-color-split;
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@
|
||||
text-align: center;
|
||||
height: @input-box-height;
|
||||
line-height: @input-box-height;
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
&-right .@{calendar-prefix-cls}-date-input-wrap {
|
||||
@@ -164,6 +164,7 @@
|
||||
&.@{calendar-prefix-cls}-time {
|
||||
.@{calendar-timepicker-prefix-cls} {
|
||||
height: 207px;
|
||||
width: 97%;
|
||||
top: 68px;
|
||||
z-index: 2; // cover .ant-calendar-range .ant-calendar-in-range-cell > div (z-index: 1)
|
||||
&-panel {
|
||||
@@ -183,8 +184,6 @@
|
||||
border-top: 1px solid @border-color-split;
|
||||
}
|
||||
&-select {
|
||||
width: 71px;
|
||||
|
||||
ul {
|
||||
max-height: 206px;
|
||||
}
|
||||
@@ -209,3 +208,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-range.@{calendar-prefix-cls}-show-time-picker {
|
||||
.@{calendar-prefix-cls}-body {
|
||||
border-top-color: transparent;
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,16 @@
|
||||
position: relative;
|
||||
outline: none;
|
||||
list-style: none;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
text-align: left;
|
||||
background-color: #fff;
|
||||
background-clip: padding-box;
|
||||
line-height: 1.5;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
&-combobox {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-1-column,
|
||||
@@ -29,7 +33,7 @@
|
||||
width: 100%;
|
||||
}
|
||||
&-2-columns &-select {
|
||||
width: 115px;
|
||||
width: 50%;
|
||||
}
|
||||
&-1-column &-select,
|
||||
&-2-columns &-select {
|
||||
@@ -45,12 +49,12 @@
|
||||
|
||||
&-select {
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
border: 1px solid @border-color-split;
|
||||
border-width: 0 1px;
|
||||
margin-left: -1px;
|
||||
box-sizing: border-box;
|
||||
width: 77px;
|
||||
width: 33.6%;
|
||||
overflow: hidden;
|
||||
position: relative; // Fix chrome weird render bug
|
||||
|
||||
@@ -108,7 +112,7 @@
|
||||
color: @btn-disable-color;
|
||||
&:hover {
|
||||
background: transparent;
|
||||
cursor: @cursor-disabled;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,7 +123,7 @@
|
||||
padding: 0 2px;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
.@{calendar-prefix-cls}-year-panel-year {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
|
||||
@@ -6,6 +6,20 @@ import warning from '../_util/warning';
|
||||
import getLocale from '../_util/getLocale';
|
||||
declare const require: Function;
|
||||
|
||||
function getColumns({ showHour, showMinute, showSecond }) {
|
||||
let column = 0;
|
||||
if (showHour) {
|
||||
column += 1;
|
||||
}
|
||||
if (showMinute) {
|
||||
column += 1;
|
||||
}
|
||||
if (showSecond) {
|
||||
column += 1;
|
||||
}
|
||||
return column;
|
||||
}
|
||||
|
||||
export default function wrapPicker(Picker, defaultFormat?) {
|
||||
const PickerWrapper = React.createClass({
|
||||
getDefaultProps() {
|
||||
@@ -68,11 +82,13 @@ export default function wrapPicker(Picker, defaultFormat?) {
|
||||
const rcTimePickerProps = {
|
||||
format: timeFormat,
|
||||
showSecond: timeFormat.indexOf('ss') >= 0,
|
||||
showMinute: timeFormat.indexOf('mm') >= 0,
|
||||
showHour: timeFormat.indexOf('HH') >= 0,
|
||||
};
|
||||
const columns = getColumns(rcTimePickerProps);
|
||||
const timePickerCls = classNames({
|
||||
[`${prefixCls}-time-picker-1-column`]: !(rcTimePickerProps.showSecond || rcTimePickerProps.showHour),
|
||||
[`${prefixCls}-time-picker-2-columns`]: rcTimePickerProps.showSecond !== rcTimePickerProps.showHour,
|
||||
[`${prefixCls}-time-picker-1-column`]: columns === 1,
|
||||
[`${prefixCls}-time-picker-2-columns`]: columns === 2,
|
||||
});
|
||||
const timePicker = props.showTime ? (
|
||||
<TimePickerPanel
|
||||
|
||||
@@ -34,17 +34,30 @@ export default class DropdownButton extends React.Component<DropdownButtonProps,
|
||||
};
|
||||
|
||||
render() {
|
||||
const [{ type, overlay, trigger, align, children, className, onClick, prefixCls, disabled }, restProps] =
|
||||
splitObject(this.props,
|
||||
['type', 'overlay', 'trigger', 'align', 'children', 'className', 'onClick', 'prefixCls', 'disabled']);
|
||||
const [{ type, overlay, trigger, align, children, className, onClick, prefixCls,
|
||||
disabled, visible, onVisibleChange }, restProps] = splitObject(this.props,
|
||||
['type', 'overlay', 'trigger', 'align', 'children', 'className', 'onClick',
|
||||
'prefixCls', 'disabled', 'visible', 'onVisibleChange']);
|
||||
const cls = classNames({
|
||||
[prefixCls]: true,
|
||||
[className]: !!className,
|
||||
});
|
||||
|
||||
const dropdownProps = {
|
||||
align,
|
||||
overlay,
|
||||
trigger: disabled ? [] : trigger,
|
||||
onVisibleChange,
|
||||
};
|
||||
|
||||
if ('visible' in this.props) {
|
||||
(dropdownProps as any).visible = visible;
|
||||
}
|
||||
|
||||
return (
|
||||
<ButtonGroup {...restProps} className={cls}>
|
||||
<Button type={type} onClick={onClick} disabled={disabled}>{children}</Button>
|
||||
<Dropdown align={align} overlay={overlay} trigger={disabled ? [] : trigger}>
|
||||
<Dropdown {...dropdownProps}>
|
||||
<Button type={type} disabled={disabled}>
|
||||
<Icon type="down" />
|
||||
</Button>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Views
|
||||
type: Navigation
|
||||
title: Dropdown
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 下拉菜单
|
||||
type: Views
|
||||
type: Navigation
|
||||
title: Dropdown
|
||||
---
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
top: -9999px;
|
||||
z-index: @zindex-dropdown;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
font-weight: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
@@ -53,15 +53,15 @@
|
||||
padding: 7px 16px;
|
||||
margin: 0;
|
||||
clear: both;
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
font-weight: normal;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
> a {
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
display: block;
|
||||
padding: 7px 16px;
|
||||
margin: -7px -16px;
|
||||
@@ -108,7 +108,7 @@
|
||||
position: absolute;
|
||||
content: "\e61f";
|
||||
right: 16px;
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
.iconfont-size-under-12px(9px);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
}
|
||||
|
||||
.@{dropdown-prefix-cls}-link {
|
||||
font-size: 12px;
|
||||
font-size: @font-size-base;
|
||||
.@{iconfont-css-prefix}-down {
|
||||
.iconfont-size-under-12px(9px);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
import { PropTypes } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import createDOMForm from 'rc-form/lib/createDOMForm';
|
||||
import PureRenderMixin from 'rc-util/lib/PureRenderMixin';
|
||||
import omit from 'omit.js';
|
||||
import warning from 'warning';
|
||||
import assign from 'object-assign';
|
||||
import warning from '../_util/warning';
|
||||
import FormItem from './FormItem';
|
||||
import createDOMForm from 'rc-form/lib/createDOMForm';
|
||||
import { FIELD_META_PROP } from './constants';
|
||||
|
||||
export interface FormCreateOption {
|
||||
@@ -121,14 +121,14 @@ export default class Form extends React.Component<FormProps, any> {
|
||||
};
|
||||
},
|
||||
componentWillMount() {
|
||||
this.getFieldProps = this.deprecatedGetFieldProps;
|
||||
this.__getFieldProps = this.props.form.getFieldProps;
|
||||
},
|
||||
deprecatedGetFieldProps(name, option) {
|
||||
warning(
|
||||
false,
|
||||
'`getFieldProps` is not recommended, please use `getFieldDecorator` instead'
|
||||
);
|
||||
return this.getFieldProps(name, option);
|
||||
return this.__getFieldProps(name, option);
|
||||
},
|
||||
render() {
|
||||
this.props.form.getFieldProps = this.deprecatedGetFieldProps;
|
||||
|
||||
@@ -22,25 +22,27 @@ Because the width of label is not fixed, you may need to adjust it by customizin
|
||||
import { Form, Row, Col, Input, Button, Icon } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const AdvancedSearchForm = Form.create()(React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
expand: false,
|
||||
};
|
||||
},
|
||||
handleSearch(e) {
|
||||
class AdvancedSearchForm extends React.Component {
|
||||
state = {
|
||||
expand: false,
|
||||
};
|
||||
|
||||
handleSearch = (e) => {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
console.log('Received values of form: ', values);
|
||||
});
|
||||
},
|
||||
handleReset() {
|
||||
}
|
||||
|
||||
handleReset = () => {
|
||||
this.props.form.resetFields();
|
||||
},
|
||||
toggle() {
|
||||
}
|
||||
|
||||
toggle = () => {
|
||||
const { expand } = this.state;
|
||||
this.setState({ expand: !expand });
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const formItemLayout = {
|
||||
@@ -86,10 +88,17 @@ const AdvancedSearchForm = Form.create()(React.createClass({
|
||||
</Row>
|
||||
</Form>
|
||||
);
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<AdvancedSearchForm />, mountNode);
|
||||
const WrappedAdvancedSearchForm = Form.create()(AdvancedSearchForm);
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<WrappedAdvancedSearchForm />
|
||||
<div className="search-result-list">Search Result List</div>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
||||
|
||||
````css
|
||||
@@ -105,4 +114,13 @@ ReactDOM.render(<AdvancedSearchForm />, mountNode);
|
||||
#components-form-demo-advanced-search .ant-form-horizontal {
|
||||
max-width: none;
|
||||
}
|
||||
#components-form-demo-advanced-search .search-result-list {
|
||||
margin-top: 16px;
|
||||
border: 1px dashed #e9e9e9;
|
||||
border-radius: 6px;
|
||||
background-color: #fafafa;
|
||||
min-height: 200px;
|
||||
text-align: center;
|
||||
padding-top: 80px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -14,25 +14,33 @@ title:
|
||||
Add or remove form items dynamically.
|
||||
|
||||
````jsx
|
||||
import { Form, Input, Button } from 'antd';
|
||||
import { Form, Input, Icon, Button } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
|
||||
let uuid = 0;
|
||||
let Demo = React.createClass({
|
||||
class DynamicFieldSet extends React.Component {
|
||||
componentWillMount() {
|
||||
this.props.form.setFieldsValue({
|
||||
keys: [0],
|
||||
});
|
||||
},
|
||||
remove(k) {
|
||||
}
|
||||
|
||||
remove = (k) => {
|
||||
const { form } = this.props;
|
||||
// can use data-binding to get
|
||||
const keys = form.getFieldValue('keys');
|
||||
// We need at least one passenger
|
||||
if (keys.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// can use data-binding to set
|
||||
form.setFieldsValue({
|
||||
keys: keys.filter(key => key !== k),
|
||||
});
|
||||
},
|
||||
add() {
|
||||
}
|
||||
|
||||
add = () => {
|
||||
uuid++;
|
||||
const { form } = this.props;
|
||||
// can use data-binding to get
|
||||
@@ -43,51 +51,72 @@ let Demo = React.createClass({
|
||||
form.setFieldsValue({
|
||||
keys: nextKeys,
|
||||
});
|
||||
},
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
console.log('Received values of form: ', values);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator, getFieldValue } = this.props.form;
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 18 },
|
||||
labelCol: { span: 4 },
|
||||
wrapperCol: { span: 20 },
|
||||
};
|
||||
const formItemLayoutWithOutLabel = {
|
||||
wrapperCol: { span: 20, offset: 4 },
|
||||
};
|
||||
|
||||
const formItems = getFieldValue('keys').map((k) => {
|
||||
const keys = getFieldValue('keys');
|
||||
const formItems = keys.map((k, index) => {
|
||||
return (
|
||||
<Form.Item {...formItemLayout} label={`good friend${k}:`} key={k}>
|
||||
{getFieldDecorator(`name${k}`, {
|
||||
<FormItem
|
||||
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
|
||||
label={index === 0 ? 'Passengers' : ''}
|
||||
required={false}
|
||||
key={k}
|
||||
>
|
||||
{getFieldDecorator(`names-${k}`, {
|
||||
validateTrigger: ['onChange', 'onBlur'],
|
||||
rules: [{
|
||||
required: true,
|
||||
whitespace: true,
|
||||
message: "Your good friend's name",
|
||||
message: "Please input passenger's name or delete this field.",
|
||||
}],
|
||||
})(
|
||||
<Input style={{ width: '60%', marginRight: 8 }} />
|
||||
)}
|
||||
<Button onClick={() => this.remove(k)}>Remove</Button>
|
||||
</Form.Item>
|
||||
<Icon
|
||||
className="delete-button"
|
||||
type="minus-circle-o"
|
||||
disabled={keys.length === 1}
|
||||
onClick={() => this.remove(k)}
|
||||
/>
|
||||
</FormItem>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<Form horizontal onSubmit={this.handleSubmit}>
|
||||
<Form horizontal>
|
||||
{formItems}
|
||||
<Form.Item wrapperCol={{ span: 18, offset: 6 }}>
|
||||
<Button onClick={this.add} style={{ marginRight: 8 }}>Add good friend</Button>
|
||||
<Button type="primary" htmlType="submit">Submit</Button>
|
||||
</Form.Item>
|
||||
<FormItem {...formItemLayoutWithOutLabel}>
|
||||
<Button type="dashed" onClick={this.add} style={{ width: '60%' }}>
|
||||
<Icon type="plus" /> Add
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Demo = Form.create()(Demo);
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
const WrappedDynamicFieldSet = Form.create()(DynamicFieldSet);
|
||||
ReactDOM.render(<WrappedDynamicFieldSet />, mountNode);
|
||||
````
|
||||
|
||||
````css
|
||||
#components-form-demo-dynamic-form-item .delete-button {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
font-size: 24px;
|
||||
color: #999;
|
||||
}
|
||||
#components-form-demo-dynamic-form-item .delete-button[disabled] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
````
|
||||
|
||||
@@ -125,7 +125,7 @@ const Demo = Form.create()(React.createClass({
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Upload"
|
||||
help="longgggggggggggggggggggggggggggggggggg"
|
||||
extra="longgggggggggggggggggggggggggggggggggg"
|
||||
>
|
||||
{getFieldDecorator('upload', {
|
||||
valuePropName: 'fileList',
|
||||
@@ -139,7 +139,7 @@ const Demo = Form.create()(React.createClass({
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem wrapperCol={{ span: 12, offset: 7 }}>
|
||||
<FormItem wrapperCol={{ span: 12, offset: 6 }}>
|
||||
<Button type="primary" htmlType="submit">Submit</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
|
||||
@@ -17,47 +17,49 @@ title:
|
||||
import { Form, InputNumber } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const RawForm = React.createClass({
|
||||
getInitialState() {
|
||||
function validatePrimeNumber(number) {
|
||||
if (number === 11) {
|
||||
return {
|
||||
number: {
|
||||
value: 11,
|
||||
},
|
||||
validateStatus: 'success',
|
||||
errorMsg: null,
|
||||
};
|
||||
},
|
||||
handleNumberChange(value) {
|
||||
}
|
||||
return {
|
||||
validateStatus: 'error',
|
||||
errorMsg: 'The prime between 8 and 12 is 11!',
|
||||
};
|
||||
}
|
||||
|
||||
class RawForm extends React.Component {
|
||||
state = {
|
||||
number: {
|
||||
value: 11,
|
||||
},
|
||||
};
|
||||
|
||||
handleNumberChange = (value) => {
|
||||
this.setState({
|
||||
number: {
|
||||
...this.validatePrimeNumber(value),
|
||||
...validatePrimeNumber(value),
|
||||
value,
|
||||
},
|
||||
});
|
||||
},
|
||||
validatePrimeNumber(number) {
|
||||
if (number === 11) {
|
||||
return {
|
||||
validateStatus: 'success',
|
||||
errorMsg: null,
|
||||
};
|
||||
}
|
||||
return {
|
||||
validateStatus: 'error',
|
||||
errorMsg: 'The prime number between 8 to 12 is 11!',
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 8 },
|
||||
labelCol: { span: 7 },
|
||||
wrapperCol: { span: 12 },
|
||||
};
|
||||
const number = this.state.number;
|
||||
const tips = 'A prime is a natural number greater than 1 that has no positive divisors other than 1 and itself.';
|
||||
return (
|
||||
<Form horizontal>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="Prime num between 8 & 12"
|
||||
label="Prime between 8 & 12"
|
||||
validateStatus={number.validateStatus}
|
||||
help={number.errorMsg}
|
||||
help={number.errorMsg || tips}
|
||||
>
|
||||
<InputNumber
|
||||
min={8}
|
||||
@@ -68,8 +70,8 @@ const RawForm = React.createClass({
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<RawForm />, mountNode);
|
||||
````
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
category: Components
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
cols: 1
|
||||
title: Form
|
||||
---
|
||||
@@ -70,16 +70,15 @@ If the form has been decorated by `Form.create` then it has `this.props.form` pr
|
||||
| validateFieldsAndScroll | This function is similar to `validateFields`, but after validation, if the target field is not in visible area of form, form will be automatically scrolled to the target field area. | same as `validateFields` |
|
||||
| getFieldError | Get the error of a field. | Function(name) |
|
||||
| isFieldValidating | Check if the specified field is being validated. | Function(name) |
|
||||
| resetFields | Reset the specified fields' value and status. If you don't specify a parameter, all the fields will be reset. | Function([names: string[]]) |
|
||||
| resetFields | Reset the specified fields' value(to `initialValue`) and status. If you don't specify a parameter, all the fields will be reset. | Function([names: string[]]) |
|
||||
| getFieldDecorator | Two-way binding for form, please read below for details. | |
|
||||
|
||||
### this.props.form.getFieldDecorator(id, options)
|
||||
|
||||
After wrapped by `getFieldDecorator`, `value` `onChange` props will be added to form controls,the flow of form data will be handled by Form which will cause:
|
||||
After wrapped by `getFieldDecorator`, `value`(or other property defined by `valuePropName`) `onChange`(or other property defined by `trigger`) props will be added to form controls,the flow of form data will be handled by Form which will cause:
|
||||
|
||||
|
||||
1. You don't need to use `onChange` and should not add `value` `onChange` to controls. (There are warnings after `antd@2.0`)
|
||||
2. You can not set default value via `defaultValue` prop, you should use `initialValue` in `getFieldDecorator` instead.
|
||||
1. You don't need to use `onChange` to collect data, but you still can listen to `onChange`(and so on) events.
|
||||
2. You can not set value of form control via `value` `defaultValue` prop, and you should set default value with `initialValue` in `getFieldDecorator` instead.
|
||||
3. You don't need to call `setState` manully, please use `this.props.form.setFieldsValue` to change value programmatically.
|
||||
|
||||
#### Special attention
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
category: Components
|
||||
subtitle: 表单
|
||||
type: Form Controls
|
||||
type: Data Entry
|
||||
cols: 1
|
||||
title: Form
|
||||
---
|
||||
@@ -72,15 +72,15 @@ CustomizedForm = Form.create({})(CustomizedForm);
|
||||
| validateFieldsAndScroll | 与 `validateFields` 相似,但校验完后,如果校验不通过的菜单域不在可见范围内,则自动滚动进可见范围 | 参考 `validateFields` |
|
||||
| getFieldError | 获取某个输入控件的 Error | Function(name) |
|
||||
| isFieldValidating | 判断一个输入控件是否在校验状态 | Function(name) |
|
||||
| resetFields | 重置一组输入控件的值与状态,如不传入参数,则重置所有组件 | Function([names: string[]]) |
|
||||
| resetFields | 重置一组输入控件的值(为 `initialValue`)与状态,如不传入参数,则重置所有组件 | Function([names: string[]]) |
|
||||
| getFieldDecorator | 用于和表单进行双向绑定,详见下方描述 | |
|
||||
|
||||
### this.props.form.getFieldDecorator(id, options)
|
||||
|
||||
经过 `getFieldDecorator` 包装的控件,表单控件会自动添加 `value` `onChange` 等属性,数据同步将被 Form 接管,这会导致以下结果:
|
||||
经过 `getFieldDecorator` 包装的控件,表单控件会自动添加 `value`(或 `valuePropName` 指定的其他属性) `onChange`(或 `trigger` 指定的其他属性),数据同步将被 Form 接管,这会导致以下结果:
|
||||
|
||||
1. 你不再需要用 `onChange` 来做同步,也不应该给控件单独添加 `value` `onChange` 等属性。(2.0 后会在控制台进行警告)
|
||||
2. 你不能用控件的 `defaultValue` 属性来设置默认值,请用 `getFieldDecorator` 里的 `initialValue`。
|
||||
1. 你不再需要用 `onChange` 来做同步,但还是可以继续监听 `onChange` 等事件。
|
||||
2. 你不能用控件的 `value` `defaultValue` 等属性来设置表单域的值,默认值可以用 `getFieldDecorator` 里的 `initialValue`。
|
||||
3. 你不需要用 `setState`,可以使用 `this.props.form.setFieldsValue` 来动态改变表单值。
|
||||
|
||||
#### 特别注意
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@import "../../style/mixins/index";
|
||||
@import "../../input/style/mixin";
|
||||
@import "../../button/style/mixin";
|
||||
@import "../../layout/style/mixin";
|
||||
@import "../../grid/style/mixin";
|
||||
@import "./mixin";
|
||||
|
||||
@form-prefix-cls: ~"@{ant-prefix}-form";
|
||||
@@ -32,7 +32,7 @@ input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
&[disabled],
|
||||
&.disabled {
|
||||
cursor: @cursor-disabled;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ input[type="checkbox"] {
|
||||
.@{ant-prefix}-checkbox-inline,
|
||||
.@{ant-prefix}-checkbox-vertical {
|
||||
&.disabled {
|
||||
cursor: @cursor-disabled;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ input[type="checkbox"] {
|
||||
.@{ant-prefix}-checkbox {
|
||||
&.disabled {
|
||||
label {
|
||||
cursor: @cursor-disabled;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ input[type="checkbox"] {
|
||||
.@{form-prefix-cls}-item {
|
||||
font-size: @font-size-base;
|
||||
margin-bottom: @form-item-margin-bottom;
|
||||
color: #666;
|
||||
color: @text-color;
|
||||
vertical-align: top;
|
||||
|
||||
// nested FormItem
|
||||
@@ -116,7 +116,7 @@ input[type="checkbox"] {
|
||||
|
||||
.@{form-prefix-cls}-explain,
|
||||
.@{form-prefix-cls}-extra {
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-text {
|
||||
@@ -292,7 +292,7 @@ form {
|
||||
.square(@input-height-lg);
|
||||
line-height: @input-height-lg;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-size: @font-size-lg;
|
||||
animation: zoomIn .3s @ease-out-back;
|
||||
.iconfont-font("");
|
||||
}
|
||||
@@ -361,7 +361,10 @@ form {
|
||||
.@{ant-prefix}-input-number,
|
||||
.@{ant-prefix}-time-picker-input {
|
||||
border-color: @warning-color;
|
||||
.active(@warning-color);
|
||||
&-focused,
|
||||
&:focus {
|
||||
.active(@warning-color);
|
||||
}
|
||||
&:not([disabled]):hover {
|
||||
border-color: @warning-color;
|
||||
}
|
||||
@@ -380,6 +383,9 @@ form {
|
||||
.@{ant-prefix}-select {
|
||||
&-selection {
|
||||
border-color: @error-color;
|
||||
}
|
||||
|
||||
&-focused &-selection {
|
||||
.active(@error-color);
|
||||
}
|
||||
|
||||
@@ -402,22 +408,25 @@ form {
|
||||
.@{ant-prefix}-input-number,
|
||||
.@{ant-prefix}-time-picker-input {
|
||||
border-color: @error-color;
|
||||
.active(@error-color);
|
||||
&-focused,
|
||||
&:focus {
|
||||
.active(@error-color);
|
||||
}
|
||||
&:not([disabled]):hover {
|
||||
border-color: @error-color;
|
||||
}
|
||||
}
|
||||
.@{ant-prefix}-mention-wrapper,
|
||||
.@{ant-prefix}-mention-wrapper.active {
|
||||
.@{ant-prefix}-mention-wrapper {
|
||||
.@{ant-prefix}-mention-editor {
|
||||
border-color: @error-color;
|
||||
.active(@error-color);
|
||||
&:not([disabled]):hover,
|
||||
&:not([disabled]):focus {
|
||||
&,
|
||||
&:not([disabled]):hover {
|
||||
border-color: @error-color;
|
||||
.active(@error-color);
|
||||
}
|
||||
}
|
||||
&.active .@{ant-prefix}-mention-editor,
|
||||
.@{ant-prefix}-mention-editor:not([disabled]):focus {
|
||||
.active(@error-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,7 +435,7 @@ form {
|
||||
display: inline-block;
|
||||
animation: loadingCircle 1s infinite linear;
|
||||
content: "\e6ae";
|
||||
color: #999;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@ import '../../style/index.less';
|
||||
import './index.less';
|
||||
|
||||
// style dependencies
|
||||
import '../../layout/style';
|
||||
import '../../grid/style';
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
// 输入框的不同校验状态
|
||||
.@{ant-prefix}-input {
|
||||
&,
|
||||
&:hover,
|
||||
&:focus {
|
||||
&:hover {
|
||||
border-color: @border-color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
.active(@border-color);
|
||||
}
|
||||
|
||||
@@ -50,11 +52,11 @@
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 20px;
|
||||
font-size: 14px;
|
||||
font-size: @font-size-lg;
|
||||
line-height: inherit;
|
||||
color: @legend-color;
|
||||
color: @text-color-secondary;
|
||||
border: 0;
|
||||
border-bottom: 1px solid @legend-border-color;
|
||||
border-bottom: 1px solid @border-color-base;
|
||||
}
|
||||
|
||||
label {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
---
|
||||
category: Components
|
||||
type: Basic
|
||||
type: Layout
|
||||
cols: 1
|
||||
title: Layout
|
||||
title: Grid
|
||||
---
|
||||
|
||||
24 Grids System。
|
||||
|
||||
## Design concept
|
||||
|
||||
<div class="layout-demo">
|
||||
<div class="grid-demo">
|
||||
<div class="ant-row demo-row">
|
||||
<div class="ant-col-24 demo-col demo-col-1">
|
||||
100%
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user