mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-16 22:32:29 +08:00
Compare commits
151 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e051e8ae32 | ||
|
|
9558aa2c64 | ||
|
|
d10639590b | ||
|
|
0283819565 | ||
|
|
5e89806520 | ||
|
|
91882a2376 | ||
|
|
5ed813bdca | ||
|
|
259fb98d87 | ||
|
|
5fba136826 | ||
|
|
5be40a9c7f | ||
|
|
f99a77b3e5 | ||
|
|
0c8c2ec727 | ||
|
|
2e0c67f214 | ||
|
|
0a543b30f6 | ||
|
|
2b381e55c0 | ||
|
|
6827a33112 | ||
|
|
31d0f2093c | ||
|
|
0dbfa049a1 | ||
|
|
98ce55fcab | ||
|
|
70669371c0 | ||
|
|
c8a1885b0d | ||
|
|
2f0ad39dcc | ||
|
|
f45a3ed1e9 | ||
|
|
4f6824dc27 | ||
|
|
95e754ad60 | ||
|
|
aa17690b65 | ||
|
|
c1bd5d4ecb | ||
|
|
81dad0452f | ||
|
|
a05b4e6747 | ||
|
|
b98a8cef88 | ||
|
|
50682fadf1 | ||
|
|
7d131a3b64 | ||
|
|
afacd6c07a | ||
|
|
6c8a7b7944 | ||
|
|
4a08e0188d | ||
|
|
3bdacbc9bc | ||
|
|
f9929c25ce | ||
|
|
a243d32dff | ||
|
|
c9be22adf3 | ||
|
|
59625b1c3f | ||
|
|
b15a4e3165 | ||
|
|
058af3cb0d | ||
|
|
d70637022d | ||
|
|
4d81deb1bc | ||
|
|
7f909e750b | ||
|
|
9294dba6a5 | ||
|
|
55ab71853f | ||
|
|
489cc44a59 | ||
|
|
28d0cf86ea | ||
|
|
777692a207 | ||
|
|
af83b2aade | ||
|
|
1688a8724b | ||
|
|
680a5b7120 | ||
|
|
d03d6721bf | ||
|
|
0e3dbc69a7 | ||
|
|
d7e1794711 | ||
|
|
fc55cf6919 | ||
|
|
8dff727a27 | ||
|
|
ea93dabefc | ||
|
|
8b6153686e | ||
|
|
d0532db3d7 | ||
|
|
1a961f2adc | ||
|
|
7cb1fb02b8 | ||
|
|
4b00e05cfb | ||
|
|
d15121493f | ||
|
|
972c3f3d41 | ||
|
|
16c4ce09d7 | ||
|
|
fb1e1cc8fc | ||
|
|
d8ad0b1993 | ||
|
|
248f1bd00f | ||
|
|
09855467b5 | ||
|
|
faf0c8b9da | ||
|
|
c3e57af521 | ||
|
|
a84ce59d31 | ||
|
|
23b8099449 | ||
|
|
9cab6543ac | ||
|
|
13fc8c9a3a | ||
|
|
7a72f4ad4e | ||
|
|
7a5ba669e7 | ||
|
|
9c28420468 | ||
|
|
7a53b39af2 | ||
|
|
b94bca7cf1 | ||
|
|
c4c834b529 | ||
|
|
c40655d3a6 | ||
|
|
dff87da25a | ||
|
|
5a87d219d7 | ||
|
|
ec916e5f72 | ||
|
|
4500f2e9ee | ||
|
|
ff31a5b555 | ||
|
|
6799ee278f | ||
|
|
9b3b20ae3e | ||
|
|
e78d424854 | ||
|
|
4ba3cd847d | ||
|
|
0fc1cebd5b | ||
|
|
a3d4e7a696 | ||
|
|
a8bae305db | ||
|
|
f294bf4674 | ||
|
|
e5c8e71ea6 | ||
|
|
7d4f0cfc51 | ||
|
|
67dd935045 | ||
|
|
3e1483ae8f | ||
|
|
016d911274 | ||
|
|
e07e7d03eb | ||
|
|
a2f40306b8 | ||
|
|
288d5ff2bc | ||
|
|
1ab292e335 | ||
|
|
af53f393bf | ||
|
|
23b8c44d39 | ||
|
|
3ea39835b1 | ||
|
|
ff2c26f7eb | ||
|
|
7fc830394d | ||
|
|
8abe21bccb | ||
|
|
bb6c922eab | ||
|
|
c4f4745a83 | ||
|
|
f8257d2756 | ||
|
|
45f06e25f0 | ||
|
|
1f59ab5370 | ||
|
|
37e053aa37 | ||
|
|
da36159669 | ||
|
|
d9b2b51558 | ||
|
|
5675faf621 | ||
|
|
4b359a8fbc | ||
|
|
a91b9a3457 | ||
|
|
2650d81a49 | ||
|
|
6ba61fc41e | ||
|
|
9c312ecd94 | ||
|
|
9d60a87855 | ||
|
|
863ecbd6d4 | ||
|
|
f35a81a862 | ||
|
|
b346949e97 | ||
|
|
85fcb20e43 | ||
|
|
070a8ce62a | ||
|
|
701282e2db | ||
|
|
8e95892b04 | ||
|
|
d94997a1dc | ||
|
|
52ca21feec | ||
|
|
3cf6696dad | ||
|
|
c8e1d300bf | ||
|
|
9d2a0f5d5b | ||
|
|
87d1843bff | ||
|
|
1c46bbe1a6 | ||
|
|
8357b525f2 | ||
|
|
bf72bc349a | ||
|
|
fcdea2931b | ||
|
|
d3a592764c | ||
|
|
93006bc348 | ||
|
|
3ba785630b | ||
|
|
b1d7b7b15f | ||
|
|
5827e45f52 | ||
|
|
9468b24b62 | ||
|
|
7e2633a5dc |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -23,6 +23,7 @@ nohup.out
|
||||
_site
|
||||
_data
|
||||
dist
|
||||
lib
|
||||
/lib
|
||||
elasticsearch-*
|
||||
config/base.yaml
|
||||
typings
|
||||
|
||||
9
404.html
9
404.html
@@ -1,9 +0,0 @@
|
||||
<script>
|
||||
var prefix = /^\/components/.test(location.pathname) ? location.pathname.replace(/^\//, '').split('/').join('-') : '';
|
||||
var scrollToString = location.hash ? '?scrollTo=' + prefix + location.hash : '';
|
||||
if (location.pathname === '/changelog') {
|
||||
location.href = '/#/docs/react/changelog' + scrollToString;
|
||||
} else {
|
||||
location.href = '/#' + location.pathname.replace(/\/$/, '') + scrollToString;
|
||||
}
|
||||
</script>
|
||||
38
CHANGELOG.md
38
CHANGELOG.md
@@ -8,6 +8,43 @@ timeline: true
|
||||
你也可以查看 GitHub 上的 [发布日志](https://github.com/ant-design/ant-design/releases)。
|
||||
|
||||
---
|
||||
|
||||
## 1.3.2
|
||||
|
||||
`2016-06-06`
|
||||
|
||||
- 修复全局模式下引用 antd,IE8 环境报错的问题。 [#1970](https://github.com/ant-design/ant-design/issues/1970)
|
||||
|
||||
## 1.3.1
|
||||
|
||||
`2016-06-06`
|
||||
|
||||
- 修复 `Message` `Notification` 找不到的问题。 [#1968](https://github.com/ant-design/ant-design/issues/1968)
|
||||
|
||||
## 1.3.0
|
||||
|
||||
`2016-06-02`
|
||||
|
||||
- Transfer 组件增加 `rowKey` 属性,可自定义数据源主键。 [#1900](https://github.com/ant-design/ant-design/issues/1900)
|
||||
- Tag 组件 `default` 类型的样式增加边框,防止淹没在背景中。 [#1910](https://github.com/ant-design/ant-design/issues/1910)
|
||||
- Table
|
||||
- 修复筛选为单选时仍旧展示多选框的问题。 [#1880](https://github.com/ant-design/ant-design/issues/1880)
|
||||
- 修复 fixed left 的固定列会覆盖 rowSelection 的 Checkbox 的问题。 [#1829](https://github.com/ant-design/ant-design/issues/1829)
|
||||
- 升级 rc-table 依赖
|
||||
- 修复了 fixed 列中数据重复展示以及一些错位问题。 [#1898](https://github.com/ant-design/ant-design/issues/1898)
|
||||
- `dataIndex` 支持内嵌属性的写法。 [react-component/table#46](https://github.com/react-component/table/issues/46)
|
||||
- 修复了 v1.2.0 新增加的组件属性的 TypeScript 定义。 [#1933](https://github.com/ant-design/ant-design/issues/1933)
|
||||
- Form 修复 label中冒号的国际化问题,采用样式实现冒号,不再需要手动输入冒号。 [#1877](https://github.com/ant-design/ant-design/issues/1877)
|
||||
- 修复 DatePicker 组件点击『此刻』失效的问题,并进行了一些代码优化。 [#1902](https://github.com/ant-design/ant-design/issues/1902)
|
||||
- 升级 rc-upload 依赖,修复了 IE10 中第二次上传同一文件不触发 `onChange` 的问题。 [058af3c](https://github.com/ant-design/ant-design/commit/b15a4e3165be5e4db995d3fe75d4d557c7f21c61)
|
||||
- 文档使用 [bisheng](https://github.com/benjycui/bisheng) 重构。
|
||||
|
||||
## 1.2.1
|
||||
|
||||
`2016-05-27`
|
||||
|
||||
- 修复一个 Select 组件的文字重复问题。
|
||||
|
||||
## 1.2.0
|
||||
|
||||
`2016-05-26`
|
||||
@@ -108,7 +145,6 @@ timeline: true
|
||||
- Progress.Circle 使用方式改为 `<Progress type="circle" />`。
|
||||
- Spin 的 `spining` 属性更正为 `spinning`。
|
||||
- Alert 的 type `warn` 重命名为 `warning`。[#1225](https://github.com/ant-design/ant-design/issues/1225)
|
||||
- `notification.warn`、`message.warn` 修改为 `notification.warning` 和 `message.warning`。[#1225](https://github.com/ant-design/ant-design/issues/1225)
|
||||
- Tree 的 `onExpand` 参数从 `function(node, expanded, expandedKeys)` 调整为 `function(expandedKeys, {expanded, node})`。
|
||||
|
||||
### Bug 修复
|
||||
|
||||
18
README.md
18
README.md
@@ -8,6 +8,10 @@
|
||||
|
||||
An enterprise-class UI design language and React-based implementation.
|
||||
|
||||
## :loudspeaker: Document Translation Recruitment
|
||||
|
||||
We are now working on translate components document to English, and we need some translator and reviewer. https://github.com/ant-design/ant-design/issues/1471
|
||||
|
||||
## Features
|
||||
|
||||
- An enterprise-class design language and high quality UI style.
|
||||
@@ -68,9 +72,15 @@ Normal browsers and Internet Explorer 8+.
|
||||
|
||||
## TypeScript
|
||||
|
||||
```js
|
||||
///<reference path='./node_modules/antd/type-definitions/antd.d.ts'/>
|
||||
...
|
||||
tsconfig.json
|
||||
|
||||
```
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"jsx": "preserve"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Links
|
||||
@@ -86,7 +96,7 @@ Normal browsers and Internet Explorer 8+.
|
||||
- [Developer Instruction](https://github.com/ant-design/ant-design/wiki/Development)
|
||||
- [Versioning Release Note](https://github.com/ant-design/ant-design/wiki/%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)
|
||||
|
||||
- [CodePen boilerplate](http://codepen.io/anon/pen/wGOWGW?editors=001) for bug reports
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { createElement } from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import isCssAnimationSupported from '../util/isCssAnimationSupported';
|
||||
import isCssAnimationSupported from '../_util/isCssAnimationSupported';
|
||||
|
||||
function getNumberArray(num) {
|
||||
return num ?
|
||||
|
||||
@@ -42,6 +42,15 @@ export default class Button extends React.Component {
|
||||
icon: React.PropTypes.string,
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.clickedTimeout) {
|
||||
clearTimeout(this.clickedTimeout);
|
||||
}
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
}
|
||||
|
||||
clearButton = (button) => {
|
||||
button.className = button.className.replace(` ${this.props.prefixCls}-clicked`, '');
|
||||
}
|
||||
@@ -50,7 +59,7 @@ export default class Button extends React.Component {
|
||||
// Add click effect
|
||||
const buttonNode = findDOMNode(this);
|
||||
this.clearButton(buttonNode);
|
||||
setTimeout(() => buttonNode.className += ` ${this.props.prefixCls}-clicked`, 10);
|
||||
this.clickedTimeout = setTimeout(() => buttonNode.className += ` ${this.props.prefixCls}-clicked`, 10);
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = setTimeout(() => this.clearButton(buttonNode), 500);
|
||||
|
||||
|
||||
@@ -35,6 +35,20 @@
|
||||
color: @color;
|
||||
background-color: @background;
|
||||
border-color: @border;
|
||||
// a inside Button which only work in Chrome
|
||||
// http://stackoverflow.com/a/17253457
|
||||
> a:only-child {
|
||||
color: currentColor;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-group-base(@btnClassName) {
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
---
|
||||
order: 0
|
||||
title: 典型卡片
|
||||
title:
|
||||
zh-CN: 典型卡片
|
||||
en-US: Basic card
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
包含标题、内容、操作区域。
|
||||
|
||||
## en-US
|
||||
|
||||
A basic card containing a title, content and an extra corner content.
|
||||
|
||||
````jsx
|
||||
import { Card } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Card title="卡片标题" extra={<a href="#">更多</a>} style={{ width: 300 }}>
|
||||
<p>卡片的内容</p>
|
||||
<p>卡片的内容</p>
|
||||
<p>卡片的内容</p>
|
||||
<Card title="Card title" extra={<a href="#">More</a>} style={{ width: 300 }}>
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
, mountNode);
|
||||
````
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
---
|
||||
order: 1
|
||||
title: 无边框
|
||||
title:
|
||||
zh-CN: 无边框
|
||||
en-US: No border
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
在灰色背景上使用无边框的卡片。
|
||||
|
||||
## en-US
|
||||
|
||||
A borderless card on a gray background.
|
||||
|
||||
````jsx
|
||||
import { Card } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<div style={{ background: '#ECECEC', padding: '30px' }}>
|
||||
<Card title="卡片标题" bordered={false} style={{ width: 300 }}>
|
||||
<p>卡片的内容</p>
|
||||
<p>卡片的内容</p>
|
||||
<p>卡片的内容</p>
|
||||
<Card title="Card title" bordered={false} style={{ width: 300 }}>
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
</div>
|
||||
, mountNode);
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
---
|
||||
order: 4
|
||||
title: 栅格卡片
|
||||
title:
|
||||
zh-CN: 栅格卡片
|
||||
en-US: Grid card
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
在系统概览页面常常和栅格进行配合。
|
||||
|
||||
## en-US
|
||||
|
||||
Cards usually cooperate with grid layout in overview page.
|
||||
|
||||
````jsx
|
||||
import { Card, Col, Row } from 'antd';
|
||||
|
||||
@@ -12,13 +20,13 @@ ReactDOM.render(
|
||||
<div style={{ background: '#ECECEC', padding: '30px' }}>
|
||||
<Row>
|
||||
<Col span="8">
|
||||
<Card title="卡片标题" bordered={false}>卡片的内容</Card>
|
||||
<Card title="Card title" bordered={false}>Card content</Card>
|
||||
</Col>
|
||||
<Col span="8">
|
||||
<Card title="卡片标题" bordered={false}>卡片的内容</Card>
|
||||
<Card title="Card title" bordered={false}>Card content</Card>
|
||||
</Col>
|
||||
<Col span="8">
|
||||
<Card title="卡片标题" bordered={false}>卡片的内容</Card>
|
||||
<Card title="Card title" bordered={false}>Card content</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
@@ -26,7 +34,7 @@ ReactDOM.render(
|
||||
````
|
||||
|
||||
````css
|
||||
/* 增加 16px 栅格间距 */
|
||||
/* Increase grid spacing of 16px */
|
||||
.code-box-demo .row {
|
||||
margin-left: -8px;
|
||||
margin-right: -8px;
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
---
|
||||
order: 5
|
||||
title: 预加载的卡片
|
||||
title:
|
||||
zh-CN: 预加载的卡片
|
||||
en-US: Loading card
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
数据读入前会有文本块样式。
|
||||
|
||||
## en-US
|
||||
|
||||
Shows a loading indicator while the contents of the card are being fetched.
|
||||
|
||||
````jsx
|
||||
import { Card } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Card loading title="卡片标题" style={{ width: '34%' }}>
|
||||
<Card loading title="Card title" style={{ width: '34%' }}>
|
||||
Whatever content
|
||||
</Card>
|
||||
, mountNode);
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
---
|
||||
order: 3
|
||||
title: 更灵活的内容展示
|
||||
title:
|
||||
zh-CN: 更灵活的内容展示
|
||||
en-US: Customized content
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以调整默认边距,设定宽度。
|
||||
|
||||
## en-US
|
||||
|
||||
Customizing default width and margin.
|
||||
|
||||
|
||||
````jsx
|
||||
import { Card } from 'antd';
|
||||
|
||||
@@ -14,7 +23,7 @@ ReactDOM.render(
|
||||
<img alt="example" width="100%" src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png" />
|
||||
</div>
|
||||
<div className="custom-card">
|
||||
<h3>欧美街拍</h3>
|
||||
<h3>Europe Street beat</h3>
|
||||
<p>www.instagram.com</p>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
---
|
||||
order: 2
|
||||
title: 简洁卡片
|
||||
title:
|
||||
zh-CN: 简洁卡片
|
||||
en-US: Simple card
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
只包含内容区域。
|
||||
|
||||
## en-US
|
||||
|
||||
A simple card only containing a content area.
|
||||
|
||||
````jsx
|
||||
import { Card } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Card style={{ width: 300 }}>
|
||||
<p>卡片的内容</p>
|
||||
<p>卡片的内容</p>
|
||||
<p>卡片的内容</p>
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
, mountNode);
|
||||
````
|
||||
|
||||
24
components/card/index.en-US.md
Normal file
24
components/card/index.en-US.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
category: Components
|
||||
type: Presentation
|
||||
title: Card
|
||||
---
|
||||
|
||||
Common card container.
|
||||
|
||||
## When to use
|
||||
|
||||
The most basic card container. You can use it to contain text, lists, pictures and paragraphs.
|
||||
|
||||
## API
|
||||
|
||||
```html
|
||||
<Card title="Card title">Card content</Card>
|
||||
```
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|----------|----------------|----------|--------------|
|
||||
| title | Card title | React.Element | - |
|
||||
| extra | Corner content of card | React.Element | - |
|
||||
| bordered | Whether a border is set | Boolean | true |
|
||||
| bodyStyle | Custom style for content area | Object | - |
|
||||
@@ -1,9 +1,8 @@
|
||||
---
|
||||
category: Components
|
||||
chinese: 卡片
|
||||
type: Presentation
|
||||
cols: 1
|
||||
english: Card
|
||||
title: Card
|
||||
subtitle: 卡片
|
||||
---
|
||||
|
||||
通用卡片容器。
|
||||
@@ -50,25 +50,6 @@ export default function createPicker(TheCalendar) {
|
||||
'ant-calendar-month': MonthCalendar === TheCalendar,
|
||||
});
|
||||
|
||||
let pickerChangeHandler = {
|
||||
onChange: this.handleChange,
|
||||
};
|
||||
|
||||
let calendarHandler = {
|
||||
onOk: this.handleChange,
|
||||
};
|
||||
|
||||
if (props.showTime) {
|
||||
pickerChangeHandler.onChange = (value) => {
|
||||
// Click clear button
|
||||
if (value === null) {
|
||||
this.handleChange(value);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
calendarHandler = {};
|
||||
}
|
||||
|
||||
const calendar = (
|
||||
<TheCalendar
|
||||
formatter={props.getFormatter()}
|
||||
@@ -80,7 +61,7 @@ export default function createPicker(TheCalendar) {
|
||||
dateInputPlaceholder={placeholder}
|
||||
prefixCls="ant-calendar"
|
||||
className={calendarClassName}
|
||||
{...calendarHandler} />
|
||||
/>
|
||||
);
|
||||
|
||||
// default width for showTime
|
||||
@@ -102,7 +83,7 @@ export default function createPicker(TheCalendar) {
|
||||
getCalendarContainer={props.getCalendarContainer}
|
||||
onOpen={props.toggleOpen}
|
||||
onClose={props.toggleOpen}
|
||||
{...pickerChangeHandler}
|
||||
onChange={this.handleChange}
|
||||
>
|
||||
{
|
||||
({ value }) => {
|
||||
|
||||
@@ -128,5 +128,6 @@
|
||||
.@{calendar-prefix-cls}-today-btn {
|
||||
margin: 8px 12px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,9 +162,15 @@ export default class FormItem extends React.Component {
|
||||
[`${props.prefixCls}-item-required`]: required,
|
||||
});
|
||||
|
||||
// remove user input colon
|
||||
let label = props.label;
|
||||
if (typeof props.label === 'string') {
|
||||
label = props.label.replace(/:|:$/, '');
|
||||
}
|
||||
|
||||
return props.label ? (
|
||||
<label htmlFor={props.id || this.getId()} className={className} key="label">
|
||||
{props.label}
|
||||
{label}
|
||||
</label>
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -16,19 +16,19 @@ ReactDOM.render(
|
||||
<Row gutter={16}>
|
||||
<Col sm={8}>
|
||||
<FormItem
|
||||
label="搜索名称:"
|
||||
label="搜索名称"
|
||||
labelCol={{ span: 10 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<Input placeholder="请输入搜索名称" size="default" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="较长搜索名称:"
|
||||
label="较长搜索名称"
|
||||
labelCol={{ span: 10 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<DatePicker size="default" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="搜索名称:"
|
||||
label="搜索名称"
|
||||
labelCol={{ span: 10 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<Input placeholder="请输入搜索名称" size="default" />
|
||||
@@ -36,19 +36,19 @@ ReactDOM.render(
|
||||
</Col>
|
||||
<Col sm={8}>
|
||||
<FormItem
|
||||
label="搜索名称:"
|
||||
label="搜索名称"
|
||||
labelCol={{ span: 10 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<Input placeholder="请输入搜索名称" size="default" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="较长搜索名称:"
|
||||
label="较长搜索名称"
|
||||
labelCol={{ span: 10 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<DatePicker size="default" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="搜索名称:"
|
||||
label="搜索名称"
|
||||
labelCol={{ span: 10 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<Input placeholder="请输入搜索名称" size="default" />
|
||||
@@ -56,19 +56,19 @@ ReactDOM.render(
|
||||
</Col>
|
||||
<Col sm={8}>
|
||||
<FormItem
|
||||
label="搜索名称:"
|
||||
label="搜索名称"
|
||||
labelCol={{ span: 10 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<Input placeholder="请输入搜索名称" size="default" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="较长搜索名称:"
|
||||
label="较长搜索名称"
|
||||
labelCol={{ span: 10 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<DatePicker size="default" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="搜索名称:"
|
||||
label="搜索名称"
|
||||
labelCol={{ span: 10 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<Input placeholder="请输入搜索名称" size="default" />
|
||||
|
||||
@@ -21,7 +21,7 @@ ReactDOM.render(
|
||||
<Form horizontal>
|
||||
<FormItem
|
||||
id="control-input"
|
||||
label="输入框:"
|
||||
label="输入框"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<Input id="control-input" placeholder="Please enter..." />
|
||||
@@ -29,7 +29,7 @@ ReactDOM.render(
|
||||
|
||||
<FormItem
|
||||
id="control-textarea"
|
||||
label="文本域:"
|
||||
label="文本域"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<Input type="textarea" id="control-textarea" rows="3" />
|
||||
@@ -37,7 +37,7 @@ ReactDOM.render(
|
||||
|
||||
<FormItem
|
||||
id="select"
|
||||
label="Select 选择器:"
|
||||
label="Select 选择器"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 14 }}>
|
||||
<Select id="select" size="large" defaultValue="lucy" style={{ width: 200 }} onChange={handleSelectChange}>
|
||||
@@ -49,7 +49,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Checkbox 多选框:"
|
||||
label="Checkbox 多选框"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 18 }} >
|
||||
<Checkbox className="ant-checkbox-vertical">选项一</Checkbox>
|
||||
@@ -58,7 +58,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Checkbox 多选框:"
|
||||
label="Checkbox 多选框"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 18 }} >
|
||||
<Checkbox className="ant-checkbox-inline">选项一</Checkbox>
|
||||
@@ -67,7 +67,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Radio 单选框:"
|
||||
label="Radio 单选框"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 18 }} >
|
||||
<RadioGroup defaultValue="b">
|
||||
|
||||
@@ -42,12 +42,12 @@ let Demo = React.createClass({
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="用户名:">
|
||||
label="用户名">
|
||||
<Input {...getFieldProps('username', {})} type="text" autoComplete="off" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="密码:">
|
||||
label="密码">
|
||||
<Input {...getFieldProps('password', {})} type="password" autoComplete="off" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
|
||||
@@ -26,17 +26,17 @@ let Demo = React.createClass({
|
||||
<Form horizontal onSubmit={this.handleSubmit}>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="用户名:">
|
||||
label="用户名">
|
||||
<p className="ant-form-text" id="userName" name="userName">大眼萌 minion</p>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="密码:">
|
||||
label="密码">
|
||||
<Input type="password" {...getFieldProps('pass')} placeholder="请输入密码" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="您的性别:">
|
||||
label="您的性别">
|
||||
<RadioGroup {...getFieldProps('gender', { initialValue: 'female' })}>
|
||||
<Radio value="male">男的</Radio>
|
||||
<Radio value="female">女的</Radio>
|
||||
@@ -44,13 +44,13 @@ let Demo = React.createClass({
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="备注:"
|
||||
label="备注"
|
||||
help="随便写点什么">
|
||||
<Input type="textarea" placeholder="随便写" {...getFieldProps('remark')} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label={<span>卖身华府 <Tooltip title="我为秋香"><Icon type="question-circle-o" /></Tooltip> :</span>}>
|
||||
label={<span>卖身华府 <Tooltip title="我为秋香"><Icon type="question-circle-o" /></Tooltip></span>}>
|
||||
<Checkbox {...getFieldProps('agreement')}>同意</Checkbox>
|
||||
</FormItem>
|
||||
<FormItem wrapperCol={{ span: 16, offset: 6 }} style={{ marginTop: 24 }}>
|
||||
|
||||
@@ -20,12 +20,12 @@ let Demo = React.createClass({
|
||||
return (
|
||||
<Form inline onSubmit={this.handleSubmit}>
|
||||
<FormItem
|
||||
label="账户:">
|
||||
label="账户">
|
||||
<Input placeholder="请输入账户名"
|
||||
{...getFieldProps('userName')} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="密码:">
|
||||
label="密码">
|
||||
<Input type="password" placeholder="请输入密码"
|
||||
{...getFieldProps('password')} />
|
||||
</FormItem>
|
||||
|
||||
@@ -14,14 +14,14 @@ const Option = Select.Option;
|
||||
ReactDOM.render(
|
||||
<Form horizontal>
|
||||
<FormItem
|
||||
label="标签输入框:"
|
||||
label="标签输入框"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}>
|
||||
<Input addonBefore="Http://" defaultValue="mysite.com" id="site1" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="标签输入框:"
|
||||
label="标签输入框"
|
||||
labelCol={{ span: 6 }}
|
||||
validateStatus="success"
|
||||
wrapperCol={{ span: 16 }}>
|
||||
@@ -29,7 +29,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="select 标签输入框:"
|
||||
label="select 标签输入框"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}>
|
||||
<InputGroup>
|
||||
@@ -46,7 +46,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="输入身份证:"
|
||||
label="输入身份证"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}>
|
||||
<InputGroup>
|
||||
@@ -66,7 +66,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="电话号码:"
|
||||
label="电话号码"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}>
|
||||
<InputGroup>
|
||||
|
||||
@@ -44,7 +44,7 @@ let Demo = React.createClass({
|
||||
return (
|
||||
<Form horizontal onSubmit={this.handleSubmit} >
|
||||
<FormItem
|
||||
label="InputNumber 数字输入框:"
|
||||
label="InputNumber 数字输入框"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 10 }}>
|
||||
<InputNumber min={1} max={10} style={{ width: 100 }}
|
||||
@@ -53,7 +53,7 @@ let Demo = React.createClass({
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="我是标题:"
|
||||
label="我是标题"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 10 }}>
|
||||
<p className="ant-form-text" id="static" name="static">唧唧复唧唧木兰当户织呀</p>
|
||||
@@ -63,7 +63,7 @@ let Demo = React.createClass({
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Switch 开关:"
|
||||
label="Switch 开关"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 10 }}
|
||||
required>
|
||||
@@ -71,7 +71,7 @@ let Demo = React.createClass({
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Slider 滑动输入条:"
|
||||
label="Slider 滑动输入条"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 10 }}
|
||||
required>
|
||||
@@ -79,7 +79,7 @@ let Demo = React.createClass({
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Select 选择器:"
|
||||
label="Select 选择器"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
required>
|
||||
@@ -93,7 +93,7 @@ let Demo = React.createClass({
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="级联选择:"
|
||||
label="级联选择"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
required
|
||||
@@ -102,7 +102,7 @@ let Demo = React.createClass({
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="DatePicker 日期选择框:"
|
||||
label="DatePicker 日期选择框"
|
||||
labelCol={{ span: 8 }}
|
||||
required>
|
||||
<Col span="6">
|
||||
@@ -122,7 +122,7 @@ let Demo = React.createClass({
|
||||
|
||||
|
||||
<FormItem
|
||||
label="TimePicker 时间选择器:"
|
||||
label="TimePicker 时间选择器"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
required>
|
||||
@@ -130,7 +130,7 @@ let Demo = React.createClass({
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="选项:"
|
||||
label="选项"
|
||||
labelCol={{ span: 8 }}>
|
||||
<RadioGroup {...getFieldProps('rg')}>
|
||||
<RadioButton value="a">选项一</RadioButton>
|
||||
@@ -140,7 +140,7 @@ let Demo = React.createClass({
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="logo图:"
|
||||
label="logo图"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
help="提示信息要长长长长长长长长长长长长长长">
|
||||
|
||||
@@ -112,7 +112,7 @@ let BasicDemo = React.createClass({
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="用户名:"
|
||||
label="用户名"
|
||||
hasFeedback
|
||||
help={isFieldValidating('name') ? '校验中...' : (getFieldError('name') || []).join(', ')}>
|
||||
<Input {...nameProps} placeholder="实时校验,输入 JasonWood 看看" />
|
||||
@@ -120,14 +120,14 @@ let BasicDemo = React.createClass({
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="邮箱:"
|
||||
label="邮箱"
|
||||
hasFeedback>
|
||||
<Input {...emailProps} type="email" placeholder="onBlur 与 onChange 相结合" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="密码:"
|
||||
label="密码"
|
||||
hasFeedback>
|
||||
<Input {...passwdProps} type="password" autoComplete="off"
|
||||
onContextMenu={noop} onPaste={noop} onCopy={noop} onCut={noop} />
|
||||
@@ -135,7 +135,7 @@ let BasicDemo = React.createClass({
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="确认密码:"
|
||||
label="确认密码"
|
||||
hasFeedback>
|
||||
<Input {...rePasswdProps} type="password" autoComplete="off" placeholder="两次输入密码保持一致"
|
||||
onContextMenu={noop} onPaste={noop} onCopy={noop} onCut={noop} />
|
||||
@@ -143,7 +143,7 @@ let BasicDemo = React.createClass({
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="备注:">
|
||||
label="备注">
|
||||
<Input {...textareaProps} type="textarea" placeholder="随便写" id="textarea" name="textarea" />
|
||||
</FormItem>
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ let Demo = React.createClass({
|
||||
<Col span="18">
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="密码:">
|
||||
label="密码">
|
||||
<Input {...passProps} type="password"
|
||||
onContextMenu={noop} onPaste={noop} onCopy={noop} onCut={noop}
|
||||
autoComplete="off" id="pass"
|
||||
@@ -161,7 +161,7 @@ let Demo = React.createClass({
|
||||
<Col span="18">
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="确认密码:">
|
||||
label="确认密码">
|
||||
<Input {...rePassProps} type="password"
|
||||
onContextMenu={noop} onPaste={noop} onCopy={noop} onCut={noop}
|
||||
autoComplete="off" id="rePass"
|
||||
|
||||
@@ -6,7 +6,7 @@ title: 校验其他组件
|
||||
提供以下组件表单域的校验:`Select` `Radio` `DatePicker` `InputNumber` `Cascader`。在 submit 时使用 `validateFieldsAndScroll`,进行校验,可以自动把不在可见范围内的校验不通过的菜单域滚动进可见范围。
|
||||
|
||||
````jsx
|
||||
import { Select, Radio, Checkbox, Button, DatePicker, InputNumber, Form, Cascader, Icon } from 'antd';
|
||||
import { Select, Radio, Checkbox, Button, DatePicker, TimePicker, InputNumber, Form, Cascader, Icon } from 'antd';
|
||||
const Option = Select.Option;
|
||||
const RadioGroup = Radio.Group;
|
||||
const createForm = Form.create;
|
||||
@@ -84,12 +84,18 @@ let Demo = React.createClass({
|
||||
{
|
||||
required: true,
|
||||
type: 'date',
|
||||
message: '你的生日是什么呢?',
|
||||
message: '你的生日是什么呢?',
|
||||
}, {
|
||||
validator: this.checkBirthday,
|
||||
},
|
||||
],
|
||||
});
|
||||
const timeProps = getFieldProps('time', {
|
||||
getValueFromEvent: (value, timeString) => timeString,
|
||||
rules: [
|
||||
{ required: true, message: '请选择一个时间' },
|
||||
],
|
||||
});
|
||||
const primeNumberProps = getFieldProps('primeNumber', {
|
||||
rules: [{ validator: this.checkPrime }],
|
||||
});
|
||||
@@ -104,7 +110,7 @@ let Demo = React.createClass({
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="国籍:">
|
||||
label="国籍">
|
||||
<Select {...selectProps} placeholder="请选择国家" style={{ width: '100%' }}>
|
||||
<Option value="china">中国</Option>
|
||||
<Option value="use">美国</Option>
|
||||
@@ -116,7 +122,7 @@ let Demo = React.createClass({
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="喜欢的颜色:">
|
||||
label="喜欢的颜色">
|
||||
<Select {...multiSelectProps} multiple placeholder="请选择颜色" style={{ width: '100%' }}>
|
||||
<Option value="red">红色</Option>
|
||||
<Option value="orange">橙色</Option>
|
||||
@@ -128,7 +134,7 @@ let Demo = React.createClass({
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="性别:">
|
||||
label="性别">
|
||||
<RadioGroup {...radioProps}>
|
||||
<Radio value="male">男</Radio>
|
||||
<Radio value="female">女</Radio>
|
||||
@@ -138,7 +144,7 @@ let Demo = React.createClass({
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="兴趣爱好:">
|
||||
label="兴趣爱好">
|
||||
<Checkbox {...getFieldProps('eat', {
|
||||
valuePropName: 'checked',
|
||||
})}>吃饭饭</Checkbox>
|
||||
@@ -152,19 +158,25 @@ let Demo = React.createClass({
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="生日:">
|
||||
label="生日">
|
||||
<DatePicker {...birthdayProps} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="8~12间的质数:">
|
||||
label="选一个时间">
|
||||
<TimePicker {...timeProps} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="8~12间的质数">
|
||||
<InputNumber {...primeNumberProps} min={8} max={12} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="选择地址:">
|
||||
label="选择地址">
|
||||
<Cascader {...addressProps} options={address} />
|
||||
</FormItem>
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ const FormItem = Form.Item;
|
||||
ReactDOM.render(
|
||||
<Form horizontal>
|
||||
<FormItem
|
||||
label="失败校验:"
|
||||
label="失败校验"
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
validateStatus="error"
|
||||
@@ -27,7 +27,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="警告校验:"
|
||||
label="警告校验"
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
validateStatus="warning">
|
||||
@@ -35,7 +35,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="校验中:"
|
||||
label="校验中"
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
hasFeedback
|
||||
@@ -45,7 +45,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="成功校验:"
|
||||
label="成功校验"
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
hasFeedback
|
||||
@@ -54,7 +54,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="警告校验:"
|
||||
label="警告校验"
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
hasFeedback
|
||||
@@ -63,7 +63,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="失败校验:"
|
||||
label="失败校验"
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
hasFeedback
|
||||
@@ -73,7 +73,7 @@ ReactDOM.render(
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="行内校验:"
|
||||
label="行内校验"
|
||||
labelCol={{ span: 5 }}
|
||||
help>
|
||||
<Col span="6">
|
||||
|
||||
@@ -86,12 +86,13 @@ CustomizedForm = Form.create({})(CustomizedForm);
|
||||
|
||||
> 在表单中 `defaultValue` 也不应该被设置,请使用下面的 `initialValue`。
|
||||
|
||||
| 参数 | 说明 | 类型 |默认值 |
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|-----------|-----------------------------------------|-----|--------|
|
||||
| options.id | 必填输入控件唯一标志 | string | |
|
||||
| options.valuePropName | 子节点的值的属性,如 Switch 的是 'checked' | string | 'value' |
|
||||
| options.initialValue | 子节点的初始值,类型、可选值均由子节点决定 | | |
|
||||
| options.trigger | 收集子节点的值的时机 | string | 'onChange' |
|
||||
| options.getValueFromEvent | 可以把 onChange 的参数转化为控件的值,例如 DatePicker 可设为:`(date, dateString) => dateString` | function(..args) | [reference](https://github.com/react-component/form#optiongetvaluefromevent) |
|
||||
| options.validateTrigger | 校验子节点值的时机 | string | 'onChange' |
|
||||
| options.rules | 校验规则,参见 [async-validator](https://github.com/yiminghe/async-validator) | array | |
|
||||
| options.onXXX | 由于 `getFieldProps` 会占用 `onChange` 等事件(即你所设置的 `trigger` `validateTrigger`),所以如果仍需绑定事件,请在 `options` 内设置 | function | 无 |
|
||||
|
||||
@@ -84,11 +84,13 @@ input[type="checkbox"] {
|
||||
color: @label-color;
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
padding-top: 7px;
|
||||
padding-bottom: 7px;
|
||||
padding: 7px 0;
|
||||
|
||||
&:lang(en) {
|
||||
padding-right: 8px;
|
||||
&:after {
|
||||
content: ":";
|
||||
margin: 0 8px 0 2px;
|
||||
position: relative;
|
||||
top: -0.5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ english: Icon
|
||||
### 一. 方向性图标
|
||||
|
||||
```__react
|
||||
import IconSet from '../../site/component/IconSet';
|
||||
import IconSet from 'site/theme/template/IconSet';
|
||||
const icons1 = ['step-backward', 'step-forward', 'fast-backward', 'fast-forward', 'shrink', 'arrow-salt', 'down', 'up', 'left', 'right', 'caret-down', 'caret-up', 'caret-left', 'caret-right', 'caret-circle-right', 'caret-circle-left', 'caret-circle-o-right', 'caret-circle-o-left', 'circle-right', 'circle-left', 'circle-o-right', 'circle-o-left', 'double-right', 'double-left', 'verticle-right', 'verticle-left', 'forward', 'backward', 'rollback', 'enter', 'retweet', 'swap', 'swap-left', 'swap-right', 'arrow-right', 'arrow-up', 'arrow-down', 'arrow-left', 'play-circle', 'play-circle-o', 'circle-up', 'circle-down', 'circle-o-up', 'circle-o-down', 'caret-circle-o-up', 'caret-circle-o-down', 'caret-circle-up', 'caret-circle-down'];
|
||||
|
||||
ReactDOM.render(<IconSet className="icons" icons={icons1} key="icons1" />, mountNode);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- order: 3
|
||||
- title: 小数
|
||||
order: 3
|
||||
title: 小数
|
||||
---
|
||||
|
||||
和原生的数字输入框一样,value 的精度由 step 的小数位数决定。
|
||||
|
||||
@@ -10,4 +10,3 @@ import { Input } from 'antd';
|
||||
|
||||
ReactDOM.render(<Input placeholder="基本使用" />, mountNode);
|
||||
````
|
||||
|
||||
|
||||
12
components/input/demo/textarea.md
Normal file
12
components/input/demo/textarea.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
order: 5
|
||||
title: 文本域
|
||||
---
|
||||
|
||||
用于多行输入,指定 `type` 为一个特殊的 `textarea`。
|
||||
|
||||
````jsx
|
||||
import { Input } from 'antd';
|
||||
|
||||
ReactDOM.render(<Input type="textarea" rows={4} />, mountNode);
|
||||
````
|
||||
@@ -12,15 +12,13 @@ english: Input
|
||||
- 需要用户输入表单域内容时。
|
||||
- 提供组合型输入框,带搜索的输入框,还可以进行大小选择。
|
||||
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### Input
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|-----------|------------------------------------------|------------|-------|--------|
|
||||
| type | 【必须】声明 input 类型,同原生 input 标签的 type 属性 | string | | 'text' |
|
||||
| type | 【必须】声明 input 类型,同原生 input 标签的 type 属性。另外提供 `type="textarea"`。 | string | | 'text' |
|
||||
| id | id | number 或 string | | |
|
||||
| value | value 值 | any | | |
|
||||
| defaultValue | 设置初始默认值 | any | | |
|
||||
@@ -43,4 +41,4 @@ english: Input
|
||||
<Input />
|
||||
<Input />
|
||||
</Input.Group>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -9,7 +9,6 @@ title: 所有组件
|
||||
import { LocaleProvider, Pagination, DatePicker, TimePicker, Calendar,
|
||||
Popconfirm, Table, Modal, Button, Select, Transfer, Radio } from 'antd';
|
||||
import enUS from 'antd/lib/locale-provider/en_US';
|
||||
import ruRU from 'antd/lib/locale-provider/ru_RU';
|
||||
const Option = Select.Option;
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
@@ -110,7 +109,6 @@ const App = React.createClass({
|
||||
<span style={{ marginRight: 16 }}>Change locale of components: </span>
|
||||
<Radio.Group defaultValue={enUS} onChange={this.changeLocale}>
|
||||
<Radio.Button key="en" value={enUS}>English</Radio.Button>
|
||||
<Radio.Button key="ru" value={ruRU}>русский язык</Radio.Button>
|
||||
<Radio.Button key="cn">中文</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import RcMenu, { Item, Divider, SubMenu, ItemGroup } from 'rc-menu';
|
||||
import animation from '../util/openAnimation';
|
||||
import animation from '../_util/openAnimation';
|
||||
|
||||
function noop() {
|
||||
}
|
||||
|
||||
@@ -366,6 +366,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-dark&-vertical &-item-selected {
|
||||
> a,
|
||||
> a:hover {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-dark &-item-active,
|
||||
&-dark &-submenu-active,
|
||||
&-dark &-submenu-title:hover {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import Notification from 'rc-notification';
|
||||
import Icon from '../icon';
|
||||
import warning from 'warning';
|
||||
|
||||
let defaultDuration = 1.5;
|
||||
let defaultTop;
|
||||
@@ -60,7 +59,6 @@ export default {
|
||||
},
|
||||
// Departed usage, please use warning()
|
||||
warn(content, duration, onClose) {
|
||||
warning(false, 'message.warn() is departed, please use message.warning()');
|
||||
return notice(content, duration, 'warning', onClose);
|
||||
},
|
||||
warning(content, duration, onClose) {
|
||||
|
||||
@@ -19,6 +19,7 @@ english: Message
|
||||
- `message.error(content, duration)`
|
||||
- `message.info(content, duration)`
|
||||
- `message.warning(content, duration)`
|
||||
- `message.warn(content, duration)`
|
||||
- `message.loading(content, duration)`
|
||||
|
||||
组件提供了四个静态方法,参数如下:
|
||||
|
||||
@@ -31,7 +31,7 @@ Modal.error = function (props) {
|
||||
return confirm(config);
|
||||
};
|
||||
|
||||
Modal.warning = function (props) {
|
||||
Modal.warning = Modal.warn = function (props) {
|
||||
const config = {
|
||||
type: 'warning',
|
||||
iconType: 'exclamation-circle',
|
||||
|
||||
@@ -41,6 +41,7 @@ english: Modal
|
||||
- `Modal.success`
|
||||
- `Modal.error`
|
||||
- `Modal.warning`
|
||||
- `Modal.warn`
|
||||
- `Modal.confirm`
|
||||
|
||||
以上均为一个函数,参数为 object,具体属性如下:
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import Notification from 'rc-notification';
|
||||
import Icon from '../icon';
|
||||
import warning from 'warning';
|
||||
|
||||
let defaultTop = 24;
|
||||
let notificationInstance;
|
||||
@@ -95,10 +94,6 @@ const api = {
|
||||
api[type] = (args) => api.open({ ...args, icon: type });
|
||||
});
|
||||
|
||||
// warn: Departed usage, please use warning()
|
||||
api.warn = (...args) => {
|
||||
warning(false, 'notification.warn() is departed, please use notification.warning()');
|
||||
api.warning(...args);
|
||||
};
|
||||
api.warn = api.warning;
|
||||
|
||||
export default api;
|
||||
|
||||
@@ -22,6 +22,7 @@ english: Notification
|
||||
- `notification.error(config)`
|
||||
- `notification.info(config)`
|
||||
- `notification.warning(config)`
|
||||
- `notification.warn(config)`
|
||||
- `notification.close(key: String)`
|
||||
- `notification.destroy()`
|
||||
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
top: 0;
|
||||
left: 9999px;
|
||||
white-space: pre;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
> i {
|
||||
|
||||
@@ -13,18 +13,18 @@ english: Slider
|
||||
|
||||
## API
|
||||
|
||||
| 参数 | 类型 | 默认值 |说明 |
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------------|----------------|-------------|--------------|
|
||||
| range | Boolean | false | 双滑块模式
|
||||
| min | Number | 0 | 最小值
|
||||
| max | Number | 100 | 最大值
|
||||
| step | Number or null | 1 | 步长,取值必须大于 0,并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step` 为 `null`,此时 Slider 的可选值仅有 marks 标出来的部分。
|
||||
| marks | Object{Number: String|React.Component} or Object{Number: { style, label}} | {} | 刻度标记,key 的类型必须为 `Number` 且取值在闭区间 [min, max] 内,每个标签可以单独设置样式
|
||||
| dots | Boolean | false | 是否只能拖拽到刻度上
|
||||
| value | Number or [Number, Number]| | 设置当前取值。当 `range` 为 `false` 时,使用 `Number`,否则用 `[Number, Number]`
|
||||
| defaultValue | Number or [Number, Number]| 0 or [0, 0] | 设置初始取值。当 `range` 为 `false` 时,使用 `Number`,否则用 `[Number, Number]`
|
||||
| included | Boolean | true | `marks` 不为空对象时有效,值为 true 时表示值为包含关系,false 表示并列
|
||||
| disabled | Boolean | false | 值为 `true` 时,滑块为禁用状态
|
||||
| onChange | Function | NOOP | 当 Slider 的值发生改变时,会触发 onChange 事件,并把改变后的值作为参数传入。
|
||||
| onAfterChange | Function | NOOP | 与 `onmouseup` 触发时机一致,把当前值作为参数传入。
|
||||
| tipFormatter | Function or null | IDENTITY | Slider 会把当前值传给 `tipFormatter`,并在 Tooltip 中显示 `tipFormatter` 的返回值,若为 null,则隐藏 Tooltip。
|
||||
| range | 双滑块模式 | Boolean | false
|
||||
| min | 最小值 | Number | 0
|
||||
| max | 最大值 | Number | 100
|
||||
| step | 步长,取值必须大于 0,并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step` 为 `null`,此时 Slider 的可选值仅有 marks 标出来的部分。 | Number or null | 1
|
||||
| marks | 刻度标记,key 的类型必须为 `Number` 且取值在闭区间 [min, max] 内,每个标签可以单独设置样式 | Object{} | Object{Number: String or React.Component} or Object{Number: { style, label}}
|
||||
| dots | 是否只能拖拽到刻度上 | Boolean | false
|
||||
| value | 设置当前取值。当 `range` 为 `false` 时,使用 `Number`,否则用 `[Number, Number]` | Number or [Number, Number] |
|
||||
| defaultValue | 设置初始取值。当 `range` 为 `false` 时,使用 `Number`,否则用 `[Number, Number]` | Number or [Number, Number] | 0 or [0, 0]
|
||||
| included | `marks` 不为空对象时有效,值为 true 时表示值为包含关系,false 表示并列 | Boolean | true
|
||||
| disabled | 值为 `true` 时,滑块为禁用状态 | Boolean | false
|
||||
| onChange | 当 Slider 的值发生改变时,会触发 onChange 事件,并把改变后的值作为参数传入。 | Function | NOOP
|
||||
| onAfterChange | 与 `onmouseup` 触发时机一致,把当前值作为参数传入。 | Function | NOOP
|
||||
| tipFormatter | Slider 会把当前值传给 `tipFormatter`,并在 Tooltip 中显示 `tipFormatter` 的返回值,若为 null,则隐藏 Tooltip。 | Function or null | IDENTITY
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import classNames from 'classnames';
|
||||
import isCssAnimationSupported from '../util/isCssAnimationSupported';
|
||||
import isCssAnimationSupported from '../_util/isCssAnimationSupported';
|
||||
import warning from 'warning';
|
||||
|
||||
export default class Spin extends React.Component {
|
||||
|
||||
@@ -48,7 +48,16 @@
|
||||
-webkit-filter: blur(1px);
|
||||
filter: blur(1px);
|
||||
filter: ~"progid\:DXImageTransform\.Microsoft\.Blur(PixelRadius\=1, MakeShadow\=false)"; /* IE6~IE9 */
|
||||
pointer-events: none;
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
// tip
|
||||
|
||||
@@ -9,7 +9,7 @@ title: 远程加载数据
|
||||
|
||||
另外,本例也展示了筛选排序功能如何交给服务端实现,列不需要指定具体的 `onFilter` 和 `sorter` 函数,而是在把筛选和排序的参数发到服务端来处理。
|
||||
|
||||
**注意,此示例是静态数据模拟,展示数据不会变化,请打开网络面板查看请求。**
|
||||
**注意,此示例使用 [模拟接口](https://randomuser.me),展示数据可能不准确,请打开网络面板查看请求。**
|
||||
|
||||
````jsx
|
||||
import { Table } from 'antd';
|
||||
@@ -18,17 +18,20 @@ import reqwest from 'reqwest';
|
||||
const columns = [{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
filters: [
|
||||
{ text: '姓李的', value: '李' },
|
||||
{ text: '姓胡的', value: '胡' },
|
||||
],
|
||||
}, {
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
sorter: true,
|
||||
render: name => `${name.first} ${name.last}`,
|
||||
width: '20%',
|
||||
}, {
|
||||
title: '住址',
|
||||
dataIndex: 'address',
|
||||
title: '性别',
|
||||
dataIndex: 'gender',
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male' },
|
||||
{ text: 'Female', value: 'female' },
|
||||
],
|
||||
width: '20%',
|
||||
}, {
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
}];
|
||||
|
||||
const Test = React.createClass({
|
||||
@@ -46,8 +49,8 @@ const Test = React.createClass({
|
||||
pagination: pager,
|
||||
});
|
||||
this.fetch({
|
||||
pageSize: pagination.pageSize,
|
||||
currentPage: pagination.current,
|
||||
results: pagination.pageSize,
|
||||
page: pagination.current,
|
||||
sortField: sorter.field,
|
||||
sortOrder: sorter.order,
|
||||
...filters,
|
||||
@@ -57,19 +60,23 @@ const Test = React.createClass({
|
||||
console.log('请求参数:', params);
|
||||
this.setState({ loading: true });
|
||||
reqwest({
|
||||
url: '/components/table/demo/data.json',
|
||||
url: 'http://api.randomuser.me',
|
||||
method: 'get',
|
||||
data: params,
|
||||
type: 'json',
|
||||
success: (result) => {
|
||||
const pagination = this.state.pagination;
|
||||
pagination.total = result.totalCount;
|
||||
this.setState({
|
||||
loading: false,
|
||||
data: result.data,
|
||||
pagination,
|
||||
});
|
||||
data: {
|
||||
results: 10,
|
||||
...params,
|
||||
},
|
||||
type: 'json',
|
||||
}).then(data => {
|
||||
const pagination = this.state.pagination;
|
||||
// Read total count from server
|
||||
// pagination.total = data.totalCount;
|
||||
pagination.total = 200;
|
||||
this.setState({
|
||||
loading: false,
|
||||
data: data.results,
|
||||
pagination,
|
||||
});
|
||||
});
|
||||
},
|
||||
componentDidMount() {
|
||||
@@ -78,6 +85,7 @@ const Test = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Table columns={columns}
|
||||
rowKey={record => record.registered}
|
||||
dataSource={this.state.data}
|
||||
pagination={this.state.pagination}
|
||||
loading={this.state.loading}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
{
|
||||
"data": [{
|
||||
"key": "1",
|
||||
"name": "胡彦斌ajax1",
|
||||
"age": 32,
|
||||
"address": "西湖区湖底公园1号"
|
||||
}, {
|
||||
"key": "2",
|
||||
"name": "胡彦祖ajax2",
|
||||
"age": 42,
|
||||
"address": "西湖区湖底公园1号"
|
||||
}, {
|
||||
"key": "3",
|
||||
"name": "李大嘴ajax3",
|
||||
"age": 32,
|
||||
"address": "西湖区湖底公园1号"
|
||||
}, {
|
||||
"key": "4",
|
||||
"name": "李大嘴ajax4",
|
||||
"age": 32,
|
||||
"address": "西湖区湖底公园1号"
|
||||
}, {
|
||||
"key": "5",
|
||||
"name": "李大嘴ajax5",
|
||||
"age": 32,
|
||||
"address": "西湖区湖底公园1号"
|
||||
}, {
|
||||
"key": "6",
|
||||
"name": "李大嘴ajax6",
|
||||
"age": 32,
|
||||
"address": "西湖区湖底公园1号"
|
||||
}, {
|
||||
"key": "7",
|
||||
"name": "李大嘴ajax7",
|
||||
"age": 32,
|
||||
"address": "西湖区湖底公园1号"
|
||||
}, {
|
||||
"key": "8",
|
||||
"name": "李大嘴ajax8",
|
||||
"age": 32,
|
||||
"address": "西湖区湖底公园1号"
|
||||
}, {
|
||||
"key": "9",
|
||||
"name": "李大嘴ajax9",
|
||||
"age": 32,
|
||||
"address": "西湖区湖底公园1号"
|
||||
}, {
|
||||
"key": "10",
|
||||
"name": "李大嘴ajax10",
|
||||
"age": 32,
|
||||
"address": "西湖区湖底公园1号"
|
||||
}],
|
||||
"totalCount": 35,
|
||||
"pageSize": 10,
|
||||
"currentPage": 1
|
||||
}
|
||||
@@ -5,7 +5,9 @@ title: 固定头和列
|
||||
|
||||
适合同时展示有大量数据和数据列。
|
||||
|
||||
> 需要指定 scroll.x 为宽度,或者指定每列宽度 `width`,否则可能有错位问题。
|
||||
> 若未指定每列的宽度,则建议指定 scroll.x 为固定宽度。
|
||||
|
||||
> 若列头与内容不对齐,请指定每列宽度 `width`。
|
||||
|
||||
````jsx
|
||||
import { Table } from 'antd';
|
||||
@@ -13,14 +15,14 @@ import { Table } from 'antd';
|
||||
const columns = [
|
||||
{ title: '姓名', width: 100, dataIndex: 'name', key: 'name', fixed: 'left' },
|
||||
{ title: '年龄', width: 100, dataIndex: 'age', key: 'age', fixed: 'left' },
|
||||
{ title: '列1', dataIndex: 'age', key: '1' },
|
||||
{ title: '列2', dataIndex: 'age', key: '2' },
|
||||
{ title: '列3', dataIndex: 'age', key: '3' },
|
||||
{ title: '列4', dataIndex: 'age', key: '4' },
|
||||
{ title: '列5', dataIndex: 'age', key: '5' },
|
||||
{ title: '列6', dataIndex: 'age', key: '6' },
|
||||
{ title: '列7', dataIndex: 'age', key: '7' },
|
||||
{ title: '列8', dataIndex: 'age', key: '8' },
|
||||
{ title: '列1', dataIndex: 'address', key: '1', width: 150 },
|
||||
{ title: '列2', dataIndex: 'address', key: '2', width: 150 },
|
||||
{ title: '列3', dataIndex: 'address', key: '3', width: 150 },
|
||||
{ title: '列4', dataIndex: 'address', key: '4', width: 150 },
|
||||
{ title: '列5', dataIndex: 'address', key: '5', width: 150 },
|
||||
{ title: '列6', dataIndex: 'address', key: '6', width: 150 },
|
||||
{ title: '列7', dataIndex: 'address', key: '7', width: 150 },
|
||||
{ title: '列8', dataIndex: 'address', key: '8', width: 150 },
|
||||
{
|
||||
title: '操作',
|
||||
key: 'operation',
|
||||
@@ -41,7 +43,7 @@ for (let i = 0; i < 100; i++) {
|
||||
}
|
||||
|
||||
function App() {
|
||||
return <Table columns={columns} dataSource={data} scroll={{ x: 1000, y: 300 }} />;
|
||||
return <Table columns={columns} dataSource={data} scroll={{ x: true, y: 300 }} />;
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
|
||||
@@ -5,7 +5,9 @@ title: 固定列
|
||||
|
||||
对于列数很多的数据,可以固定前后的列,横向滚动查看其它数据,需要和 `scroll.x` 配合使用。
|
||||
|
||||
> 需要指定 scroll.x 为宽度,或者指定每列宽度 `width`,否则可能有错位问题。
|
||||
> 若未指定每列的宽度,则建议指定 scroll.x 为固定宽度。
|
||||
|
||||
> 若列头与内容不对齐,请指定每列宽度 `width`。
|
||||
|
||||
````jsx
|
||||
import { Table } from 'antd';
|
||||
@@ -13,14 +15,14 @@ import { Table } from 'antd';
|
||||
const columns = [
|
||||
{ title: '姓名', width: 100, dataIndex: 'name', key: 'name', fixed: 'left' },
|
||||
{ title: '年龄', width: 100, dataIndex: 'age', key: 'age', fixed: 'left' },
|
||||
{ title: '列1', dataIndex: 'age', key: '1' },
|
||||
{ title: '列2', dataIndex: 'age', key: '2' },
|
||||
{ title: '列3', dataIndex: 'age', key: '3' },
|
||||
{ title: '列4', dataIndex: 'age', key: '4' },
|
||||
{ title: '列5', dataIndex: 'age', key: '5' },
|
||||
{ title: '列6', dataIndex: 'age', key: '6' },
|
||||
{ title: '列7', dataIndex: 'age', key: '7' },
|
||||
{ title: '列8', dataIndex: 'age', key: '8' },
|
||||
{ title: '列1', dataIndex: 'address', key: '1' },
|
||||
{ title: '列2', dataIndex: 'address', key: '2' },
|
||||
{ title: '列3', dataIndex: 'address', key: '3' },
|
||||
{ title: '列4', dataIndex: 'address', key: '4' },
|
||||
{ title: '列5', dataIndex: 'address', key: '5' },
|
||||
{ title: '列6', dataIndex: 'address', key: '6' },
|
||||
{ title: '列7', dataIndex: 'address', key: '7' },
|
||||
{ title: '列8', dataIndex: 'address', key: '8' },
|
||||
{
|
||||
title: '操作',
|
||||
key: 'operation',
|
||||
@@ -34,14 +36,16 @@ const data = [{
|
||||
key: '1',
|
||||
name: '胡彦斌',
|
||||
age: 32,
|
||||
address: '西湖区湖底公园0号',
|
||||
}, {
|
||||
key: '2',
|
||||
name: '胡彦祖',
|
||||
age: 42,
|
||||
age: 40,
|
||||
address: '西湖区湖底公园1号',
|
||||
}];
|
||||
|
||||
function App() {
|
||||
return <Table columns={columns} dataSource={data} scroll={{ x: 1000 }} />;
|
||||
return <Table columns={columns} dataSource={data} scroll={{ x: true }} />;
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
|
||||
@@ -3,6 +3,7 @@ import Menu, { SubMenu, Item as MenuItem } from 'rc-menu';
|
||||
import Dropdown from '../dropdown';
|
||||
import Icon from '../icon';
|
||||
import Checkbox from '../checkbox';
|
||||
import Radio from '../radio';
|
||||
|
||||
export default class FilterMenu extends React.Component {
|
||||
static defaultProps = {
|
||||
@@ -53,22 +54,27 @@ export default class FilterMenu extends React.Component {
|
||||
}
|
||||
|
||||
renderMenuItem(item) {
|
||||
const { column } = this.props;
|
||||
const multiple = ('filterMultiple' in column) ? column.filterMultiple : true;
|
||||
return (
|
||||
<MenuItem key={item.value}>
|
||||
<Checkbox checked={this.state.selectedKeys.indexOf(item.value.toString()) >= 0} />
|
||||
{
|
||||
multiple
|
||||
? <Checkbox checked={this.state.selectedKeys.indexOf(item.value.toString()) >= 0} />
|
||||
: <Radio checked={this.state.selectedKeys.indexOf(item.value.toString()) >= 0} />
|
||||
}
|
||||
<span>{item.text}</span>
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
||||
renderMenus(items) {
|
||||
let menuItems = items.map(item => {
|
||||
return items.map(item => {
|
||||
if (item.children && item.children.length > 0) {
|
||||
const keyPathOfSelectedItem = this.state.keyPathOfSelectedItem;
|
||||
const containSelected = Object.keys(keyPathOfSelectedItem).some(key => {
|
||||
const keyPath = keyPathOfSelectedItem[key];
|
||||
return keyPath.indexOf(item.value) >= 0;
|
||||
});
|
||||
const { keyPathOfSelectedItem } = this.state;
|
||||
const containSelected = Object.keys(keyPathOfSelectedItem).some(
|
||||
key => keyPathOfSelectedItem[key].indexOf(item.value) >= 0
|
||||
);
|
||||
const subMenuCls = containSelected ? 'ant-dropdown-submenu-contain-selected' : '';
|
||||
return (
|
||||
<SubMenu title={item.text} className={subMenuCls} key={item.value.toString()}>
|
||||
@@ -78,7 +84,6 @@ export default class FilterMenu extends React.Component {
|
||||
}
|
||||
return this.renderMenuItem(item);
|
||||
});
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
handleMenuItemClick = (info) => {
|
||||
@@ -97,13 +102,11 @@ export default class FilterMenu extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let { column, locale } = this.props;
|
||||
const { column, locale } = this.props;
|
||||
// default multiple selection in filter dropdown
|
||||
let multiple = true;
|
||||
if ('filterMultiple' in column) {
|
||||
multiple = column.filterMultiple;
|
||||
}
|
||||
let menus = (
|
||||
const multiple = ('filterMultiple' in column) ? column.filterMultiple : true;
|
||||
|
||||
const menus = (
|
||||
<div className="ant-table-filter-dropdown">
|
||||
<Menu multiple={multiple}
|
||||
onClick={this.handleMenuItemClick}
|
||||
@@ -126,10 +129,8 @@ export default class FilterMenu extends React.Component {
|
||||
</div>
|
||||
);
|
||||
|
||||
let dropdownSelectedClass = '';
|
||||
if (this.props.selectedKeys.length > 0) {
|
||||
dropdownSelectedClass = 'ant-table-filter-selected';
|
||||
}
|
||||
const dropdownSelectedClass = (this.props.selectedKeys.length > 0)
|
||||
? 'ant-table-filter-selected' : '';
|
||||
|
||||
return (
|
||||
<Dropdown trigger={['click']}
|
||||
|
||||
@@ -742,7 +742,7 @@ export default class Table extends React.Component {
|
||||
table = <Spin className={spinClassName} spinning={this.props.loading}>{table}</Spin>;
|
||||
return (
|
||||
<div className={`${emptyClass} ${className} clearfix`} style={style}>
|
||||
{<Spin className={spinClassName} spinning={this.props.loading}>{table}</Spin>}
|
||||
{table}
|
||||
{this.renderPagination()}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -76,19 +76,18 @@ const columns = [{
|
||||
| footer | 表格底部自定义渲染函数 | Function(currentPageData) | |
|
||||
| scroll | 横向或纵向支持滚动,也可用于指定滚动区域的宽高度:`{{ x: true, y: 300 }}` | Object | - |
|
||||
|
||||
|
||||
### Column
|
||||
|
||||
列描述数据对象,是 columns 中的一项。
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|-----------|----------------------------|-----------------|---------|
|
||||
| title | 列头显示文字 | String or React.Element | |
|
||||
| key | React 需要的 key,建议设置 | String | |
|
||||
| dataIndex | 列数据在数据项中对应的 key | String | |
|
||||
| render | 生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return里面可以设置表格[行/列合并](#demo-colspan-rowspan) | Function(text, record, index) {} | |
|
||||
| filters | 表头的筛选菜单项 | Array | |
|
||||
| onFilter | 本地模式下,确定筛选的运行函数 | Function | |
|
||||
| title | 列头显示文字 | String or React.Element | - |
|
||||
| key | React 需要的 key,建议设置 | String | - |
|
||||
| dataIndex | 列数据在数据项中对应的 key,支持 `a.b.c` 的嵌套写法 | String | - |
|
||||
| render | 生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return里面可以设置表格[行/列合并](#demo-colspan-rowspan) | Function(text, record, index) {} | - |
|
||||
| filters | 表头的筛选菜单项 | Array | - |
|
||||
| onFilter | 本地模式下,确定筛选的运行函数 | Function | - |
|
||||
| filterMultiple | 是否多选 | Boolean | true |
|
||||
| sorter | 排序函数,本地排序使用一个函数,需要服务端排序可设为 true | Function or Boolean | - |
|
||||
| colSpan | 表头列合并,设置为 0 时,不渲染 | Number | |
|
||||
@@ -111,7 +110,6 @@ const columns = [{
|
||||
| onSelect | 用户手动选择/取消选择某列的回调 | Function(record, selected, selectedRows) | - |
|
||||
| onSelectAll | 用户手动选择/取消选择所有列的回调 | Function(selected, selectedRows, changeRows) | - |
|
||||
|
||||
|
||||
## 注意
|
||||
|
||||
按照 React 的[规范](http://facebook.github.io/react/docs/multiple-components.html#dynamic-children),所有的组件数组必须绑定 key。在 Table 中,`dataSource` 和 `columns` 里的数据值都需要指定 `key` 值。对于 `dataSource` 默认将每列数据的 `key` 属性作为唯一的标识。
|
||||
|
||||
@@ -266,6 +266,10 @@
|
||||
box-shadow: none;
|
||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||
|
||||
&-item > label + span {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
&-sub {
|
||||
border-radius: @border-radius-base;
|
||||
border: 1px solid @border-color-base;
|
||||
@@ -313,12 +317,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-expand-icon-th {
|
||||
width: 34px;
|
||||
}
|
||||
|
||||
&-row {
|
||||
&-expand-icon {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
text-align: center;
|
||||
line-height: 15px;
|
||||
border: 1px solid @border-color-split;
|
||||
@@ -362,6 +370,10 @@
|
||||
|
||||
&-scroll {
|
||||
overflow: auto;
|
||||
table {
|
||||
width: auto;
|
||||
min-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&-body-inner {
|
||||
@@ -387,6 +399,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-fixed-left,
|
||||
&-fixed-right,
|
||||
&-scroll {
|
||||
th,
|
||||
td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
&-fixed-left &-fixed,
|
||||
&-fixed-right &-fixed {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&-fixed-left {
|
||||
left: 0;
|
||||
box-shadow: @shadow-1-right;
|
||||
@@ -414,6 +440,12 @@
|
||||
table {
|
||||
border-radius: 0 @border-radius-base 0 0;
|
||||
}
|
||||
// hide expand row content in right-fixed Table
|
||||
// https://github.com/ant-design/ant-design/issues/1898
|
||||
.@{table-prefix-cls}-expanded-row {
|
||||
color: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
&&-scroll-position-left &-fixed-left {
|
||||
|
||||
@@ -41,7 +41,7 @@ const App = React.createClass({
|
||||
{tag.name}
|
||||
</Tag>
|
||||
)}
|
||||
<Button size="small" type="primary" onClick={this.addTag}>添加标签</Button>
|
||||
<Button size="small" type="dashed" onClick={this.addTag}>+ 添加标签</Button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: @border-radius-base;
|
||||
background: #f3f3f3;
|
||||
border: 1px solid @border-color-split;
|
||||
background: #f7f7f7;
|
||||
font-size: @font-size-base;
|
||||
transition: all 0.3s @ease-in-out-circ;
|
||||
vertical-align: middle;
|
||||
@@ -53,6 +54,7 @@
|
||||
&-green,
|
||||
&-yellow,
|
||||
&-red {
|
||||
border: 0;
|
||||
&,
|
||||
a,
|
||||
a:hover,
|
||||
|
||||
@@ -19,3 +19,6 @@ english: Tooltip
|
||||
|-----------|------------------------------------------|------------|--------|
|
||||
| placement | 气泡框位置,可选 `top` `left` `right` `bottom` `topLeft` `topRight` `bottomLeft` `bottomRight` `leftTop` `leftBottom` `rightTop` `rightBottom` | string | top |
|
||||
| title | 提示文字 | string/React.Element | 无 |
|
||||
| getTooltipContainer | 浮层渲染父节点。默认渲染到 body 上 | Function(triggerNode) | () => document.body |
|
||||
|
||||
更多 API 可参考:https://github.com/react-component/tooltip
|
||||
|
||||
@@ -41,6 +41,7 @@ export default class Transfer extends React.Component {
|
||||
notFoundContent: PropTypes.node,
|
||||
body: PropTypes.func,
|
||||
footer: PropTypes.func,
|
||||
rowKey: PropTypes.func,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@@ -61,8 +62,15 @@ export default class Transfer extends React.Component {
|
||||
});
|
||||
}
|
||||
splitDataSource(props) {
|
||||
const { targetKeys, dataSource } = props;
|
||||
const { targetKeys } = props;
|
||||
let { dataSource } = props;
|
||||
|
||||
if (props.rowKey) {
|
||||
dataSource = dataSource.map(record => {
|
||||
record.key = props.rowKey(record);
|
||||
return record;
|
||||
});
|
||||
}
|
||||
let leftDataSource = [...dataSource];
|
||||
let rightDataSource = [];
|
||||
|
||||
|
||||
@@ -29,3 +29,14 @@ english: Transfer
|
||||
| searchPlaceholder | 搜索框的默认值 | String | '请输入搜索内容' |
|
||||
| notFoundContent | 当列表为空时显示的内容 | React.node | '列表为空' |
|
||||
| footer | 底部渲染函数 | Function(props) | |
|
||||
|
||||
|
||||
## 注意
|
||||
|
||||
按照 React 的[规范](http://facebook.github.io/react/docs/multiple-components.html#dynamic-children),所有的组件数组必须绑定 key。在 Transfer 中,`dataSource`里的数据值需要指定 `key` 值。对于 `dataSource` 默认将每列数据的 `key` 属性作为唯一的标识。
|
||||
|
||||
如果你的数据没有这个属性,务必使用 `rowKey` 来指定数据列的主键。
|
||||
```jsx
|
||||
// 比如你的数据主键是 uid
|
||||
return <Transfer rowKey={record => record.uid} />;
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import RcTree from 'rc-tree';
|
||||
import animation from '../util/openAnimation';
|
||||
import animation from '../_util/openAnimation';
|
||||
|
||||
export default class Tree extends React.Component {
|
||||
static TreeNode = RcTree.TreeNode;
|
||||
|
||||
@@ -157,6 +157,7 @@ ReactDOM.render(<ExtendPalettes key="palettes" />, mountNode);
|
||||
`````__react
|
||||
const Values = require('values.js');
|
||||
const CopyToClipboard = require('react-copy-to-clipboard');
|
||||
const antd = require('antd');
|
||||
const Button = antd.Button;
|
||||
const InputNumber = antd.InputNumber;
|
||||
const Slider = antd.Slider;
|
||||
|
||||
@@ -7,7 +7,7 @@ title: 可收起展开的侧边导航
|
||||
|
||||
````jsx
|
||||
import { Menu, Breadcrumb, Icon } from 'antd';
|
||||
import BrowserDemo from 'site/component/BrowserDemo';
|
||||
import BrowserDemo from 'site/theme/template/BrowserDemo';
|
||||
const SubMenu = Menu.SubMenu;
|
||||
|
||||
const AsideCollapse = React.createClass({
|
||||
|
||||
@@ -9,7 +9,7 @@ title: 侧边导航
|
||||
|
||||
````jsx
|
||||
import { Menu, Breadcrumb, Icon } from 'antd';
|
||||
import BrowserDemo from 'site/component/BrowserDemo';
|
||||
import BrowserDemo from 'site/theme/template/BrowserDemo';
|
||||
const SubMenu = Menu.SubMenu;
|
||||
|
||||
ReactDOM.render(
|
||||
|
||||
@@ -9,7 +9,7 @@ title: 吊顶规范
|
||||
|
||||
````jsx
|
||||
import { Menu, Breadcrumb } from 'antd';
|
||||
import BrowserDemo from 'site/component/BrowserDemo';
|
||||
import BrowserDemo from 'site/theme/template/BrowserDemo';
|
||||
|
||||
ReactDOM.render(
|
||||
<BrowserDemo>
|
||||
|
||||
@@ -7,7 +7,7 @@ title: 顶部导航 + 侧边栏
|
||||
|
||||
````jsx
|
||||
import { Menu, Breadcrumb, Icon } from 'antd';
|
||||
import BrowserDemo from 'site/component/BrowserDemo';
|
||||
import BrowserDemo from 'site/theme/template/BrowserDemo';
|
||||
const SubMenu = Menu.SubMenu;
|
||||
|
||||
ReactDOM.render(
|
||||
|
||||
@@ -11,7 +11,7 @@ title: 顶部导航
|
||||
|
||||
````jsx
|
||||
import { Menu, Breadcrumb } from 'antd';
|
||||
import BrowserDemo from 'site/component/BrowserDemo';
|
||||
import BrowserDemo from 'site/theme/template/BrowserDemo';
|
||||
|
||||
ReactDOM.render(
|
||||
<BrowserDemo>
|
||||
|
||||
@@ -11,6 +11,7 @@ english: Motion
|
||||
|
||||
`````__react
|
||||
const cssAnimation = require('css-animation');
|
||||
const antd = require('antd');
|
||||
const Select = antd.Select;
|
||||
const Option = Select.Option;
|
||||
const OptGroup = Select.OptGroup;
|
||||
|
||||
2009
index.d.ts
vendored
Normal file
2009
index.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
39
index.js
39
index.js
@@ -1,28 +1,31 @@
|
||||
/* eslint no-console:0 */
|
||||
// this file is not used if use https://github.com/ant-design/babel-plugin-antd
|
||||
|
||||
import {
|
||||
Rate, Affix, DatePicker, Tooltip, Tag, Carousel, Tabs, Modal, Dropdown, Progress, Popover, Select,
|
||||
Breadcrumb, Popconfirm, Pagination, Steps, InputNumber, Switch, Checkbox, Table, Collapse, message,
|
||||
Slider, QueueAnim, Radio, notification, Alert, Validation, Tree, TreeSelect, Upload,
|
||||
Badge, Menu, Timeline, Button, Icon, Row, Col, Spin, Form, Input, Calendar, TimePicker,
|
||||
Card, LocaleProvider, Transfer, Cascader,
|
||||
} from 'antd';
|
||||
function camelCase(name) {
|
||||
return name.charAt(0).toUpperCase() +
|
||||
name.slice(1).replace(/-(\w)/g, (m, n) => {
|
||||
return n.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
// copy from above
|
||||
const antd = {
|
||||
Rate, Affix, DatePicker, Tooltip, Tag, Carousel, Tabs, Modal, Dropdown, Progress, Popover, Select,
|
||||
Breadcrumb, Popconfirm, Pagination, Steps, InputNumber, Switch, Checkbox, Table, Collapse, message,
|
||||
Slider, QueueAnim, Radio, notification, Alert, Validation, Tree, TreeSelect, Upload,
|
||||
Badge, Menu, Timeline, Button, Icon, Row, Col, Spin, Form, Input, Calendar, TimePicker,
|
||||
Card, LocaleProvider, Transfer, Cascader,
|
||||
};
|
||||
const req = require.context('./components', true, /^\.\/[^_][\w-]+\/(style\/)?index\.jsx?$/);
|
||||
|
||||
req.keys().forEach((mod) => {
|
||||
const v = req(mod);
|
||||
const match = mod.match(/^\.\/([^_][\w-]+)\/index\.jsx?$/);
|
||||
if (match && match[1]) {
|
||||
if (match[1] === 'message' || match[1] === 'notification') {
|
||||
// message & notification should not be capitalized
|
||||
exports[match[1]] = v;
|
||||
} else {
|
||||
exports[camelCase(match[1])] = v;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (typeof console !== 'undefined' && console.warn) {
|
||||
console.warn(`you are using prebuild antd,
|
||||
console.warn(`You are using prebuilt antd,
|
||||
please use https://github.com/ant-design/babel-plugin-antd to reduce app bundle size.`);
|
||||
}
|
||||
}
|
||||
|
||||
export default antd;
|
||||
|
||||
28
package.json
28
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "antd",
|
||||
"version": "1.2.1",
|
||||
"version": "1.3.2",
|
||||
"title": "Ant Design",
|
||||
"description": "一个 UI 设计语言",
|
||||
"homepage": "http://ant.design/",
|
||||
@@ -29,7 +29,7 @@
|
||||
"files": [
|
||||
"dist",
|
||||
"lib",
|
||||
"type-definitions"
|
||||
"index.d.ts"
|
||||
],
|
||||
"typings": "type-definitions/antd.d.ts",
|
||||
"license": "MIT",
|
||||
@@ -40,6 +40,7 @@
|
||||
"gregorian-calendar": "~4.1.0",
|
||||
"gregorian-calendar-format": "~4.1.0",
|
||||
"normalize.css": "^4.1.1",
|
||||
"nunjucks": "^2.4.2",
|
||||
"rc-animate": "~2.0.4",
|
||||
"rc-calendar": "~5.5.4",
|
||||
"rc-cascader": "~0.9.9",
|
||||
@@ -57,25 +58,29 @@
|
||||
"rc-radio": "~2.0.0",
|
||||
"rc-rate": "~1.1.1",
|
||||
"rc-select": "~6.4.0",
|
||||
"rc-slider": "~3.6.2",
|
||||
"rc-slider": "~3.7.0",
|
||||
"rc-steps": "~2.1.3",
|
||||
"rc-switch": "~1.4.2",
|
||||
"rc-table": "~4.0.6",
|
||||
"rc-table": "~4.1.1",
|
||||
"rc-tabs": "~5.9.1",
|
||||
"rc-time-picker": "~1.1.4",
|
||||
"rc-tooltip": "~3.3.2",
|
||||
"rc-tree": "~1.3.1",
|
||||
"rc-tree-select": "~1.7.2",
|
||||
"rc-upload": "~1.12.0",
|
||||
"rc-upload": "~1.13.0",
|
||||
"rc-util": "~3.1.3",
|
||||
"react-slick": "~0.12.0",
|
||||
"warning": "~2.1.0"
|
||||
"warning": "~3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"antd-tools": "^0.8.0",
|
||||
"babel-eslint": "^6.0.2",
|
||||
"babel-jest": "^12.0.2",
|
||||
"babel-plugin-antd": "^0.4.0",
|
||||
"bisheng": "^0.5.0",
|
||||
"bisheng-plugin-description": "^0.1.1",
|
||||
"bisheng-plugin-react": "^0.1.0",
|
||||
"bisheng-plugin-toc": "0.2.0",
|
||||
"dom-scroll-into-view": "^1.1.0",
|
||||
"enquire.js": "^2.1.1",
|
||||
"es6-shim": "^0.35.0",
|
||||
@@ -104,6 +109,7 @@
|
||||
"react": "^15.0.0",
|
||||
"react-addons-test-utils": "^15.0.0",
|
||||
"react-copy-to-clipboard": "^4.0.1",
|
||||
"react-document-title": "^2.0.1",
|
||||
"react-dom": "^15.0.0",
|
||||
"react-github-button": "^0.1.1",
|
||||
"react-intl": "^2.0.1",
|
||||
@@ -118,11 +124,11 @@
|
||||
"dist": "antd-tools run dist",
|
||||
"compile": "antd-tools run compile",
|
||||
"clean": "antd-tools run clean",
|
||||
"start": "antd-tools run start",
|
||||
"site": "antd-tools run site",
|
||||
"pre-deploy": "cp CNAME _site && rsync -R components/*/demo/*.json _site",
|
||||
"deploy": "antd-tools run update-self && antd-tools run deploy",
|
||||
"just-deploy": "antd-tools run just-deploy",
|
||||
"start": "bisheng start -c ./site/bisheng.config.js",
|
||||
"site": "bisheng build -c ./site/bisheng.config.js",
|
||||
"pre-deploy": "mkdir -p _site && cp CNAME _site",
|
||||
"deploy": "tnpm run clean && tnpm i && tnpm run just-deploy",
|
||||
"just-deploy": "tnpm run pre-deploy && bisheng gh-pages -c ./site/bisheng.config.js",
|
||||
"lint": "npm run srclint && npm run demolint && npm run lesshint",
|
||||
"srclint": "RUN_ENV=SRC eslint components test site scripts ./*.js --ext '.js,.jsx'",
|
||||
"demolint": "RUN_ENV=DEMO eslint components/*/demo/*.md --ext '.md'",
|
||||
|
||||
50
site/bisheng-plugin-antd/lib/browser.js
Normal file
50
site/bisheng-plugin-antd/lib/browser.js
Normal file
@@ -0,0 +1,50 @@
|
||||
const React = require('react');
|
||||
const Link = require('react-router').Link;
|
||||
const toReactComponent = require('jsonml-to-react-component');
|
||||
const JsonML = require('jsonml.js/lib/utils');
|
||||
const VideoPlayer = require('./VideoPlayer');
|
||||
const ImagePreview = require('./ImagePreview');
|
||||
|
||||
function isHeading(node) {
|
||||
return /h[1-6]/i.test(JsonML.getTagName(node));
|
||||
}
|
||||
|
||||
module.exports = () => {
|
||||
return {
|
||||
converters: [
|
||||
[(node) => JsonML.isElement(node) && isHeading(node), (node, index) => {
|
||||
const children = JsonML.getChildren(node);
|
||||
return React.createElement(JsonML.getTagName(node), {
|
||||
key: index,
|
||||
id: children,
|
||||
...JsonML.getAttributes(node),
|
||||
}, [
|
||||
<span key="title">{children.map((child) => toReactComponent(child))}</span>,
|
||||
<a href={`#${children}`} className="anchor" key="anchor">#</a>,
|
||||
]);
|
||||
}],
|
||||
[(node) => JsonML.isElement(node) && JsonML.getTagName(node) === 'video', (node, index) =>
|
||||
<VideoPlayer video={JsonML.getAttributes(node)} key={index} />,
|
||||
],
|
||||
[(node) => JsonML.isElement(node) && JsonML.getTagName(node) === 'a' && !(
|
||||
JsonML.getAttributes(node).class ||
|
||||
(JsonML.getAttributes(node).href &&
|
||||
JsonML.getAttributes(node).href.indexOf('http') === 0) ||
|
||||
/^#/.test(JsonML.getAttributes(node).href)
|
||||
), (node, index) => {
|
||||
return <Link to={JsonML.getAttributes(node).href} key={index}>{toReactComponent(JsonML.getChildren(node)[0])}</Link>;
|
||||
}],
|
||||
[(node) => {
|
||||
return JsonML.isElement(node) &&
|
||||
JsonML.getTagName(node) === 'p' &&
|
||||
JsonML.getTagName(JsonML.getChildren(node)[0]) === 'img' &&
|
||||
/preview-img/gi.test(JsonML.getAttributes(JsonML.getChildren(node)[0]).class);
|
||||
}, (node, index) => {
|
||||
const imgs = JsonML.getChildren(node)
|
||||
.filter((img) => JsonML.isElement(img) && Object.keys(JsonML.getAttributes(img)).length > 0)
|
||||
.map((img) => JsonML.getAttributes(img));
|
||||
return <ImagePreview imgs={imgs} key={index} />;
|
||||
}],
|
||||
],
|
||||
};
|
||||
};
|
||||
11
site/bisheng-plugin-antd/lib/node.js
Normal file
11
site/bisheng-plugin-antd/lib/node.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const path = require('path');
|
||||
const processDoc = require('./process-doc');
|
||||
const processDemo = require('./process-demo');
|
||||
|
||||
module.exports = (markdownData) => {
|
||||
const isDemo = /\/demo$/i.test(path.dirname(markdownData.meta.filename));
|
||||
if (isDemo) {
|
||||
return processDemo(markdownData);
|
||||
}
|
||||
return processDoc(markdownData);
|
||||
};
|
||||
92
site/bisheng-plugin-antd/lib/process-demo.js
Normal file
92
site/bisheng-plugin-antd/lib/process-demo.js
Normal file
@@ -0,0 +1,92 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const JsonML = require('jsonml.js/lib/utils');
|
||||
const pkgPath = path.join(process.cwd(), 'package.json');
|
||||
const pkgName = require(pkgPath).name;
|
||||
|
||||
const nunjucks = require('nunjucks');
|
||||
nunjucks.configure({ autoescape: false });
|
||||
|
||||
const babel = require('babel-core');
|
||||
const babelrc = {
|
||||
presets: ['es2015', 'react'].map((m) => {
|
||||
return require.resolve(`babel-preset-${m}`);
|
||||
}),
|
||||
};
|
||||
|
||||
const tmpl = fs.readFileSync(path.join(__dirname, 'template.html')).toString();
|
||||
|
||||
function isStyleTag(node) {
|
||||
return node && JsonML.getTagName(node) === 'style';
|
||||
}
|
||||
|
||||
function getCode(node) {
|
||||
return JsonML.getChildren(
|
||||
JsonML.getChildren(node)[0]
|
||||
)[0];
|
||||
}
|
||||
|
||||
module.exports = (markdownData) => {
|
||||
const meta = markdownData.meta;
|
||||
meta.id = meta.filename.replace(/\.md$/, '').replace(/\//g, '-');
|
||||
|
||||
const contentChildren = JsonML.getChildren(markdownData.content);
|
||||
const chineseIntroStart = contentChildren.findIndex((node) => {
|
||||
return JsonML.getTagName(node) === 'h2' &&
|
||||
JsonML.getChildren(node)[0] === 'zh-CN';
|
||||
});
|
||||
const englishIntroStart = contentChildren.findIndex((node) => {
|
||||
return JsonML.getTagName(node) === 'h2' &&
|
||||
JsonML.getChildren(node)[0] === 'en-US';
|
||||
});
|
||||
const codeIndex = contentChildren.findIndex((node) => {
|
||||
return JsonML.getTagName(node) === 'pre' &&
|
||||
JsonML.getAttributes(node).lang === 'jsx';
|
||||
});
|
||||
if (chineseIntroStart > -1 /* equal to englishIntroStart > -1 */) {
|
||||
markdownData.content = {
|
||||
'zh-CN': contentChildren.slice(chineseIntroStart + 1, englishIntroStart),
|
||||
'en-US': contentChildren.slice(englishIntroStart + 1, codeIndex),
|
||||
};
|
||||
} else {
|
||||
markdownData.content = contentChildren.slice(0, codeIndex);
|
||||
}
|
||||
|
||||
markdownData.highlightedCode = contentChildren[codeIndex].slice(0, 2);
|
||||
const preview = [
|
||||
'pre', { lang: '__react' },
|
||||
];
|
||||
const componentsPath = path.join(process.cwd(), 'components');
|
||||
preview.push([
|
||||
'code',
|
||||
getCode(contentChildren[codeIndex])
|
||||
.replace(`${pkgName}/lib`, componentsPath),
|
||||
]);
|
||||
markdownData.preview = preview;
|
||||
|
||||
const styleNode = contentChildren.filter((node) => {
|
||||
return isStyleTag(node) ||
|
||||
(JsonML.getTagName(node) === 'pre' && JsonML.getAttributes(node).lang === 'css');
|
||||
})[0];
|
||||
|
||||
if (isStyleTag(styleNode)) {
|
||||
markdownData.style = JsonML.getChildren(styleNode)[0];
|
||||
} else if (styleNode) {
|
||||
const styleTag = contentChildren.filter(isStyleTag)[0];
|
||||
markdownData.style = getCode(styleNode) + (styleTag ? JsonML.getChildren(styleTag)[0] : '');
|
||||
markdownData.highlightedStyle = JsonML.getAttributes(styleNode).highlighted;
|
||||
}
|
||||
|
||||
if (meta.iframe) {
|
||||
const html = nunjucks.renderString(tmpl, {
|
||||
id: meta.id,
|
||||
style: markdownData.style,
|
||||
script: babel.transform(getCode(markdownData.preview), babelrc).code,
|
||||
});
|
||||
const fileName = `demo-${Math.random()}.html`;
|
||||
fs.writeFile(path.join(process.cwd(), '_site', fileName), html);
|
||||
markdownData.src = path.join('/', fileName);
|
||||
}
|
||||
|
||||
return markdownData;
|
||||
};
|
||||
19
site/bisheng-plugin-antd/lib/process-doc.js
Normal file
19
site/bisheng-plugin-antd/lib/process-doc.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const JsonML = require('jsonml.js/lib/utils');
|
||||
|
||||
module.exports = (markdownData) => {
|
||||
const contentChildren = JsonML.getChildren(markdownData.content);
|
||||
const apiStartIndex = contentChildren.findIndex((node) => {
|
||||
return JsonML.getTagName(node) === 'h2' &&
|
||||
JsonML.getChildren(node)[0] === 'API';
|
||||
});
|
||||
|
||||
if (apiStartIndex > -1) {
|
||||
const content = contentChildren.slice(0, apiStartIndex);
|
||||
markdownData.content = ['section'].concat(content);
|
||||
|
||||
const api = contentChildren.slice(apiStartIndex);
|
||||
markdownData.api = ['section'].concat(api);
|
||||
}
|
||||
|
||||
return markdownData;
|
||||
};
|
||||
34
site/bisheng-plugin-antd/lib/template.html
Normal file
34
site/bisheng-plugin-antd/lib/template.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Demo</title>
|
||||
<link rel="stylesheet" href="../index.css" />
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
background: none;
|
||||
}
|
||||
{{ style }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="{{ id }}" class="code-box-demo"></div>
|
||||
<script>
|
||||
function require(module) {
|
||||
if (module === 'react-router') {
|
||||
return window.ReactRouter;
|
||||
}
|
||||
return window.parent[module];
|
||||
}
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
var mountNode = document.getElementById('{{ id }}');
|
||||
</script>
|
||||
<script src="https://npmcdn.com/react-router/umd/ReactRouter.min.js"></script>
|
||||
<script>
|
||||
{{ script }}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
35
site/bisheng.config.js
Normal file
35
site/bisheng.config.js
Normal file
@@ -0,0 +1,35 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
port: 8001,
|
||||
source: [
|
||||
'./components',
|
||||
'./docs',
|
||||
'CHANGELOG.md', // TODO: fix it in bisheng
|
||||
],
|
||||
theme: './site/theme',
|
||||
htmlTemplate: './site/theme/static/template.html',
|
||||
plugins: [
|
||||
'bisheng-plugin-description',
|
||||
'bisheng-plugin-toc?maxDepth=2',
|
||||
'bisheng-plugin-react?lang=__react',
|
||||
'./site/bisheng-plugin-antd',
|
||||
],
|
||||
webpackConfig(config) {
|
||||
config.resolve.alias = {
|
||||
antd: process.cwd(),
|
||||
site: path.join(process.cwd(), 'site'),
|
||||
};
|
||||
|
||||
config.babel.plugins.push([
|
||||
require.resolve('babel-plugin-antd'),
|
||||
{
|
||||
style: true,
|
||||
libraryName: 'antd',
|
||||
libDir: 'components',
|
||||
},
|
||||
]);
|
||||
|
||||
return config;
|
||||
},
|
||||
};
|
||||
@@ -1,18 +0,0 @@
|
||||
import './styles/highlight.less';
|
||||
import './styles/common.less';
|
||||
import './styles/markdown.less';
|
||||
import './styles/toc.less';
|
||||
import './styles/font.less';
|
||||
import './styles/resource.less';
|
||||
import './styles/clearfix.less';
|
||||
import './styles/demo.less';
|
||||
import './styles/page-nav.less';
|
||||
import './styles/footer.less';
|
||||
import './styles/preview-img.less';
|
||||
import './styles/mock-browser.less';
|
||||
import './styles/colors.less';
|
||||
import './styles/motion.less';
|
||||
import './styles/responsive.less';
|
||||
import './styles/new-version-info-modal.less';
|
||||
|
||||
import 'es6-shim';
|
||||
@@ -1,14 +0,0 @@
|
||||
.clearfix {
|
||||
zoom: 1;
|
||||
&:before,
|
||||
&:after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
font-size: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import React from 'react';
|
||||
import Header from './Header';
|
||||
import Footer from './Footer';
|
||||
|
||||
export default function App(props) {
|
||||
return (
|
||||
<div className="page-wrapper">
|
||||
<Header {...props} />
|
||||
{props.children}
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
import React, { Children, cloneElement } from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import * as utils from '../utils';
|
||||
import { getTagName, getChildren } from 'jsonml.js/lib/utils';
|
||||
import { Timeline } from 'antd';
|
||||
|
||||
export default class Article extends React.Component {
|
||||
componentDidMount() {
|
||||
this.componentDidUpdate();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
const { title, chinese, english } = this.props.content.meta;
|
||||
utils.setTitle(`${title || chinese || english} - Ant Design`);
|
||||
const links = Array.apply(null, document.querySelectorAll('.outside-link.internal'));
|
||||
if (links.length === 0) {
|
||||
return;
|
||||
}
|
||||
const checkImgUrl = 'http://alipay-rmsdeploy-dev-image.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/JdVaTbZzPxEldUi.png';
|
||||
utils.ping(checkImgUrl, status => {
|
||||
if (status === 'responded') {
|
||||
links.forEach(link => (link.style.display = 'block'));
|
||||
}
|
||||
});
|
||||
}
|
||||
getArticle(article) {
|
||||
const { content } = this.props;
|
||||
const { meta } = content;
|
||||
if (!meta.timeline) {
|
||||
return article;
|
||||
}
|
||||
const timelineItems = [];
|
||||
let temp = [];
|
||||
Children.forEach(article.props.children, (child, i) => {
|
||||
if (child.type === 'h2' && temp.length > 0) {
|
||||
timelineItems.push(<Timeline.Item key={i}>{temp}</Timeline.Item>);
|
||||
temp = [];
|
||||
}
|
||||
temp.push(child);
|
||||
});
|
||||
return cloneElement(article, {
|
||||
children: <Timeline>{timelineItems}</Timeline>,
|
||||
});
|
||||
}
|
||||
render() {
|
||||
const { content, location } = this.props;
|
||||
const jumper = content.description.filter((node) => {
|
||||
return getTagName(node) === 'h2';
|
||||
}).map((node) => {
|
||||
return (
|
||||
<li key={getChildren(node)[0]}>
|
||||
<Link to={{ pathname: location.pathname, query: { scrollTo: getChildren(node)[0] } }}>
|
||||
{utils.jsonmlToComponent(location.pathname, getChildren(node)[0])}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
const { meta, intro, description } = content;
|
||||
|
||||
return (
|
||||
<article className="markdown">
|
||||
<h1>
|
||||
{meta.title || meta.english} {meta.subtitle || meta.chinese}
|
||||
{
|
||||
!meta.subtitle ? null :
|
||||
<span className="subtitle">{meta.subtitle}</span>
|
||||
}
|
||||
</h1>
|
||||
{
|
||||
!intro ? null :
|
||||
utils.jsonmlToComponent(
|
||||
location.pathname,
|
||||
['section', { className: 'markdown' }].concat(intro)
|
||||
)
|
||||
}
|
||||
{
|
||||
(jumper.length > 0 && meta.toc !== false) ?
|
||||
<section className="toc"><ul>{jumper}</ul></section> :
|
||||
null
|
||||
}
|
||||
{
|
||||
this.getArticle(utils.jsonmlToComponent(
|
||||
location.pathname,
|
||||
['section', { className: 'markdown' }].concat(description)
|
||||
))
|
||||
}
|
||||
</article>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import classNames from 'classnames';
|
||||
import { Row, Col, Icon, Affix } from 'antd';
|
||||
import Demo from '../Demo';
|
||||
import * as utils from '../utils';
|
||||
import demosList from '../../../_data/demos-list';
|
||||
|
||||
export default class ComponentDoc extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: React.PropTypes.object,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
expandAll: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.componentDidUpdate();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
const { title, subtitle, chinese, english } = this.props.doc.meta;
|
||||
utils.setTitle(`${subtitle || chinese || ''} ${title || english} - Ant Design`);
|
||||
}
|
||||
|
||||
handleExpandToggle = () => {
|
||||
this.setState({
|
||||
expandAll: !this.state.expandAll,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { doc, location } = this.props;
|
||||
const scrollTo = location.query.scrollTo;
|
||||
const { description, meta } = doc;
|
||||
const locale = this.context.intl.locale;
|
||||
const demos = (demosList[meta.fileName.replace(`.${locale}`, '')] || [])
|
||||
.filter((demoData) => !demoData.meta.hidden);
|
||||
const expand = this.state.expandAll;
|
||||
|
||||
const isSingleCol = meta.cols === 1;
|
||||
const leftChildren = [];
|
||||
const rightChildren = [];
|
||||
demos.sort((a, b) => {
|
||||
return parseInt(a.meta.order, 10) - parseInt(b.meta.order, 10);
|
||||
}).forEach((demoData, index) => {
|
||||
if (index % 2 === 0 || isSingleCol) {
|
||||
leftChildren.push(
|
||||
<Demo {...demoData} className={scrollTo === demoData.id ? 'code-box-target' : ''}
|
||||
key={index}
|
||||
expand={expand} pathname={location.pathname} />
|
||||
);
|
||||
} else {
|
||||
rightChildren.push(
|
||||
<Demo {...demoData} className={scrollTo === demoData.id ? 'code-box-target' : ''}
|
||||
key={index}
|
||||
expand={expand} pathname={location.pathname} />
|
||||
);
|
||||
}
|
||||
});
|
||||
const expandTriggerClass = classNames({
|
||||
'code-box-expand-trigger': true,
|
||||
'code-box-expand-trigger-active': expand,
|
||||
});
|
||||
|
||||
const jumper = demos.map((demo) => {
|
||||
const title = demo.meta.title;
|
||||
const localizeTitle = typeof title === 'object' ?
|
||||
title[locale] : title;
|
||||
return (
|
||||
<li key={demo.id}>
|
||||
<Link className={demo.id === scrollTo ? 'current' : ''}
|
||||
to={{ pathname: location.pathname, query: { scrollTo: `${demo.id}` } }}>
|
||||
{localizeTitle}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<article>
|
||||
<Affix className="toc-affix" offsetTop={16}>
|
||||
<ul className="toc demos-anchor">
|
||||
{jumper}
|
||||
</ul>
|
||||
</Affix>
|
||||
<section className="markdown">
|
||||
<h1>{meta.title || meta.english} {meta.subtitle || meta.chinese}</h1>
|
||||
{
|
||||
utils.jsonmlToComponent(
|
||||
location.pathname,
|
||||
['section', { className: 'markdown' }]
|
||||
.concat(description)
|
||||
)
|
||||
}
|
||||
<h2>
|
||||
代码演示
|
||||
<Icon type="appstore" className={expandTriggerClass}
|
||||
title="展开全部代码" onClick={this.handleExpandToggle} />
|
||||
</h2>
|
||||
</section>
|
||||
<Row gutter={16}>
|
||||
<Col span={isSingleCol ? '24' : '12'}
|
||||
className={isSingleCol ?
|
||||
'code-boxes-col-1-1' :
|
||||
'code-boxes-col-2-1'
|
||||
}
|
||||
>
|
||||
{leftChildren}
|
||||
</Col>
|
||||
{
|
||||
isSingleCol ? null :
|
||||
<Col className="code-boxes-col-2-1" span="12">{rightChildren}</Col>
|
||||
}
|
||||
</Row>
|
||||
{
|
||||
utils.jsonmlToComponent(
|
||||
location.pathname,
|
||||
['section', {
|
||||
className: 'markdown api-container',
|
||||
}].concat(doc.api || [])
|
||||
)
|
||||
}
|
||||
</article>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Link } from 'react-router';
|
||||
import { getTagName, getAttributes, getChildren, isElement } from 'jsonml.js/lib/utils';
|
||||
import toReactComponent from 'jsonml-to-react-component';
|
||||
import VideoPlayer from './VideoPlayer';
|
||||
import ImagePreview from './ImagePreview';
|
||||
|
||||
function isHeading(type) {
|
||||
return /h[1-6]/i.test(type);
|
||||
}
|
||||
|
||||
export function jsonmlToComponent(pathname, jsonml) {
|
||||
return toReactComponent(jsonml, [
|
||||
[(node) => React.isValidElement(node), (node, index) => {
|
||||
return React.cloneElement(node, { key: index });
|
||||
}],
|
||||
[(node) => typeof node === 'function', (node, index) => {
|
||||
return React.cloneElement(node(React, ReactDOM), { key: index });
|
||||
}],
|
||||
[(node) => isHeading(getTagName(node)), (node, index) => {
|
||||
const children = getChildren(node);
|
||||
return React.createElement(getTagName(node), {
|
||||
key: index,
|
||||
id: children,
|
||||
...getAttributes(node),
|
||||
}, [
|
||||
<span key="title">{children.map((child) => toReactComponent(child))}</span>,
|
||||
<Link to={{ pathname, query: { scrollTo: children } }} className="anchor" key="anchor">#</Link>,
|
||||
]);
|
||||
}],
|
||||
[(node) => getTagName(node) === 'pre' && getAttributes(node).highlighted, (node, index) => {
|
||||
return React.createElement('pre', { key: index, lang: getAttributes(node).lang }, React.createElement(
|
||||
'code',
|
||||
{ dangerouslySetInnerHTML: { __html: getChildren(getChildren(node)[0])[0] } }
|
||||
));
|
||||
}],
|
||||
[(node) => getTagName(node) === 'video', (node, index) =>
|
||||
<VideoPlayer video={getAttributes(node)} key={index} />,
|
||||
],
|
||||
[(node) => isElement(node) && getTagName(node) === 'a' && !(
|
||||
getAttributes(node).class ||
|
||||
(getAttributes(node).href &&
|
||||
getAttributes(node).href.indexOf('http') === 0)
|
||||
), (node, index) => {
|
||||
return <Link to={getAttributes(node).href} key={index}>{toReactComponent(getChildren(node)[0])}</Link>;
|
||||
}],
|
||||
[(node) => {
|
||||
return isElement(node) &&
|
||||
getTagName(node) === 'p' &&
|
||||
getTagName(getChildren(node)[0]) === 'img' &&
|
||||
/preview-img/gi.test(getAttributes(getChildren(node)[0]).class);
|
||||
}, (node, index) => {
|
||||
const imgs = getChildren(node)
|
||||
.filter((img) => isElement(img) && Object.keys(getAttributes(img)).length > 0)
|
||||
.map((img) => getAttributes(img));
|
||||
return <ImagePreview imgs={imgs} key={index} />;
|
||||
}],
|
||||
]);
|
||||
}
|
||||
|
||||
export function setTitle(title) {
|
||||
document.title = title;
|
||||
}
|
||||
|
||||
export function ping(url, callback) {
|
||||
const img = new Image();
|
||||
let done;
|
||||
const finish = (status) => {
|
||||
if (!done) {
|
||||
done = true;
|
||||
img.src = '';
|
||||
callback(status);
|
||||
}
|
||||
};
|
||||
img.onload = () => finish('responded');
|
||||
img.onerror = () => finish('error');
|
||||
img.src = url;
|
||||
setTimeout(() => finish('timeout'), 1500);
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { addLocaleData, IntlProvider } from 'react-intl';
|
||||
import { Router, Route, IndexRoute, Redirect, useRouterHistory } from 'react-router';
|
||||
import antd from '../../index.js';
|
||||
import * as utils from './utils';
|
||||
import '../common/lib';
|
||||
import App from '../component/App';
|
||||
import Home from '../component/Home/index';
|
||||
import NotFound from '../component/NotFound/index';
|
||||
import practice from '../../_data/practice';
|
||||
import pattern from '../../_data/pattern';
|
||||
import reactComponents from '../../_data/react-components';
|
||||
import spec from '../../_data/spec';
|
||||
import resource from '../../_data/resource';
|
||||
import config from '../website.config';
|
||||
import enLocale from './en-US.js';
|
||||
import cnLocale from './zh-CN.js';
|
||||
import { createHashHistory } from 'history';
|
||||
|
||||
// useRouterHistory creates a composable higher-order function
|
||||
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });
|
||||
|
||||
// TODO: pack dependencies with atool build
|
||||
// Expose React, ReactDOM
|
||||
window.react = React;
|
||||
window['react-dom'] = ReactDOM;
|
||||
window.antd = antd;
|
||||
|
||||
const ReactComponents = utils.generateContainer(reactComponents);
|
||||
const Practice = utils.generateContainer(practice);
|
||||
const Pattern = utils.generateContainer(pattern);
|
||||
const Spec = utils.generateContainer(spec);
|
||||
const Resource = utils.generateContainer(resource);
|
||||
const redirects = Object.keys(config.redirects).map((from, index) => {
|
||||
return <Redirect from={from} to={config.redirects[from]} key={index} />;
|
||||
});
|
||||
|
||||
// Enable Google Analytics
|
||||
if (!location.port) {
|
||||
/* eslint-disable */
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-72788897-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
|
||||
appHistory.listen((loc) => {
|
||||
ga('send', 'pageview', loc.pathname + loc.search);
|
||||
});
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
// Polyfill
|
||||
const areIntlLocalesSupported = require('intl-locales-supported');
|
||||
const localesMyAppSupports = ['zh-CN', 'en-US'];
|
||||
|
||||
if (global.Intl) {
|
||||
// Determine if the built-in `Intl` has the locale data we need.
|
||||
if (!areIntlLocalesSupported(localesMyAppSupports)) {
|
||||
// `Intl` exists, but it doesn't have the data we need, so load the
|
||||
// polyfill and patch the constructors we need with the polyfill's.
|
||||
/* eslint-disable global-require */
|
||||
const IntlPolyfill = require('intl');
|
||||
/* eslint-enable global-require */
|
||||
Intl.NumberFormat = IntlPolyfill.NumberFormat;
|
||||
Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat;
|
||||
}
|
||||
} else {
|
||||
// No `Intl`, so use and load the polyfill.
|
||||
/* eslint-disable global-require */
|
||||
global.Intl = require('intl');
|
||||
/* eslint-enable global-require */
|
||||
}
|
||||
|
||||
|
||||
const isZhCN = (typeof localStorage !== 'undefined' && localStorage.getItem('locale') !== 'en-US');
|
||||
// (typeof localStorage !== 'undefined' && localStorage.getItem('locale') === 'zh-CN') ||
|
||||
// (navigator.language === 'zh-CN');
|
||||
const appLocale = isZhCN ? cnLocale : enLocale;
|
||||
addLocaleData(appLocale.data);
|
||||
|
||||
ReactDOM.render(
|
||||
<IntlProvider locale={appLocale.locale} messages={appLocale.messages}>
|
||||
<Router history={appHistory}>
|
||||
<Route path="/" component={App}>
|
||||
<IndexRoute component={Home} />
|
||||
<Route path="components" component={ReactComponents}>
|
||||
{utils.generateIndex(reactComponents)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(reactComponents)}
|
||||
component={utils.getChildrenWrapper(reactComponents)} />
|
||||
</Route>
|
||||
{redirects}
|
||||
<Route path="docs/react" component={ReactComponents}>
|
||||
{utils.generateIndex(reactComponents)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(reactComponents)}
|
||||
component={utils.getChildrenWrapper(reactComponents)} />
|
||||
</Route>
|
||||
<Route path="docs/practice" component={Practice}>
|
||||
{utils.generateIndex(practice)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(practice)}
|
||||
component={utils.getChildrenWrapper(practice)} />
|
||||
</Route>
|
||||
<Route path="docs/pattern" component={Pattern}>
|
||||
{utils.generateIndex(pattern)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(pattern)}
|
||||
component={utils.getChildrenWrapper(pattern)} />
|
||||
</Route>
|
||||
<Route path="docs/spec" component={Spec}>
|
||||
{utils.generateIndex(spec)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(spec)}
|
||||
component={utils.getChildrenWrapper(spec)} />
|
||||
</Route>
|
||||
<Route path="docs/resource" component={Resource}>
|
||||
{utils.generateIndex(resource)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(resource)}
|
||||
component={utils.getChildrenWrapper(resource)} />
|
||||
</Route>
|
||||
<Route path="*" component={NotFound} />
|
||||
</Route>
|
||||
</Router>
|
||||
</IntlProvider>
|
||||
, document.getElementById('react-content')
|
||||
);
|
||||
@@ -1,120 +0,0 @@
|
||||
/* eslint-disable react/prefer-stateless-function, react/no-multi-comp */
|
||||
import React from 'react';
|
||||
import { IndexRedirect } from 'react-router';
|
||||
import MainContent from '../component/MainContent';
|
||||
import Article from '../component/Article';
|
||||
import ComponentDoc from '../component/ComponentDoc';
|
||||
import demosList from '../../_data/demos-list';
|
||||
import { redirects } from '../website.config';
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.accept('../../_data/demos-list', () => {});
|
||||
}
|
||||
|
||||
function fileNameToPath(fileName) {
|
||||
const snippets = fileName
|
||||
.replace(/(\/index)?((\.zh-CN)|(\.en-US))?\.md$/i, '').split('/');
|
||||
return snippets[snippets.length - 1];
|
||||
}
|
||||
|
||||
function getMenuItems(data, locale) {
|
||||
const menuMeta = Object.keys(data)
|
||||
.map((key) => data[key])
|
||||
.map((file) => {
|
||||
if (file.localized) {
|
||||
return file[locale].meta;
|
||||
}
|
||||
return file.meta;
|
||||
});
|
||||
|
||||
const menuItems = {};
|
||||
menuMeta.sort((a, b) => {
|
||||
return parseInt(a.order, 10) - parseInt(b.order, 10);
|
||||
}).forEach((meta) => {
|
||||
const category = meta.category || 'topLevel';
|
||||
if (!menuItems[category]) {
|
||||
menuItems[category] = {};
|
||||
}
|
||||
|
||||
const type = meta.type || 'topLevel';
|
||||
if (!menuItems[category][type]) {
|
||||
menuItems[category][type] = [];
|
||||
}
|
||||
|
||||
menuItems[category][type].push(meta);
|
||||
});
|
||||
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
export function generateContainer(data) {
|
||||
return class containerWrapper extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: React.PropTypes.object,
|
||||
}
|
||||
|
||||
render() {
|
||||
const locale = this.context.intl.locale;
|
||||
const menuItems = getMenuItems(data, locale);
|
||||
return (
|
||||
<MainContent {...this.props} menuItems={menuItems} />
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function generateIndex(data) {
|
||||
const menuItems = getMenuItems(data, 'zh-CN'); // 以中文版配置为准
|
||||
const firstChild = menuItems.topLevel.topLevel.filter((item) => {
|
||||
return !item.disabled;
|
||||
})[0];
|
||||
return (
|
||||
<IndexRedirect key="index"
|
||||
to={fileNameToPath(firstChild.fileName)} />
|
||||
);
|
||||
}
|
||||
|
||||
const pathToFile = {};
|
||||
Object.keys(redirects).forEach((key) => pathToFile[redirects[key]] = key);
|
||||
pathToFile['docs/react/changelog'] = './CHANGELOG'; // TODO
|
||||
|
||||
function getDoc(data, props) {
|
||||
const trimedPathname = props.location.pathname.replace(/^\//, '');
|
||||
const processedPathname = pathToFile[trimedPathname] || trimedPathname;
|
||||
const doc = data[`${processedPathname}.md`] ||
|
||||
data[`${processedPathname}/index.md`];
|
||||
return doc;
|
||||
}
|
||||
|
||||
export function getChildrenWrapper(data) {
|
||||
return class childrenWrapper extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: React.PropTypes.object,
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const trimedPathname = props.location.pathname.replace(/^\//, '');
|
||||
const processedPathname = pathToFile[trimedPathname] || trimedPathname;
|
||||
const rawDoc = data[`${processedPathname}.md`] ||
|
||||
data[`${processedPathname}/index.md`];
|
||||
|
||||
const locale = this.context.intl.locale;
|
||||
const doc = rawDoc.localized ? rawDoc[locale] : rawDoc;
|
||||
|
||||
const hasDemos = demosList[doc.meta.fileName.replace(`.${locale}`, '')];
|
||||
return !hasDemos ?
|
||||
<Article {...props} content={doc} /> :
|
||||
<ComponentDoc {...props} doc={doc} />;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getEnterHandler(data) {
|
||||
return function handleEnter(nextState, replace) {
|
||||
const doc = getDoc(data, nextState);
|
||||
if (!doc) {
|
||||
replace('/404');
|
||||
}
|
||||
};
|
||||
}
|
||||
33
site/theme/index.js
Normal file
33
site/theme/index.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const contentTmpl = './template/Content/index';
|
||||
|
||||
module.exports = {
|
||||
categoryOrder: {
|
||||
组件: 0,
|
||||
十大原则: 0,
|
||||
设计基础: 1,
|
||||
动画: 2,
|
||||
},
|
||||
typeOrder: {
|
||||
Basic: 0,
|
||||
'Form Control': 1,
|
||||
Presentation: 2,
|
||||
Navigation: 3,
|
||||
Other: 4,
|
||||
},
|
||||
docVersions: {
|
||||
'0.9.x': 'http://09x.ant.design/',
|
||||
'0.10.x': 'http://010x.ant.design/',
|
||||
'0.11.x': 'http://011x.ant.design/',
|
||||
'0.12.x': 'http://012x.ant.design/',
|
||||
},
|
||||
routes: {
|
||||
'/': './template/Home/index',
|
||||
'/docs/practice/:children': contentTmpl,
|
||||
'/docs/pattern/:children': contentTmpl,
|
||||
'/docs/react/:children': contentTmpl,
|
||||
'/changelog': contentTmpl,
|
||||
'/components/:children': contentTmpl,
|
||||
'/docs/spec/:children': contentTmpl,
|
||||
'/docs/resource/:children': contentTmpl,
|
||||
},
|
||||
};
|
||||
@@ -34,7 +34,7 @@ a {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
div.main-container {
|
||||
padding: 0 6% 120px 4%;
|
||||
margin-left: -1px;
|
||||
background: #fff;
|
||||
@@ -39,7 +39,7 @@
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.code-box.code-box-target {
|
||||
.code-box:target {
|
||||
border: 1px solid rgba(45, 183, 245, 0.7);
|
||||
box-shadow: 0 0 4px rgba(45, 183, 245, 0.5);
|
||||
}
|
||||
@@ -70,7 +70,7 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.code-box-meta {
|
||||
.code-box-meta.markdown {
|
||||
position: relative;
|
||||
padding: 16px;
|
||||
border-radius: 0 0 6px 6px;
|
||||
@@ -80,7 +80,7 @@
|
||||
}
|
||||
|
||||
.code-box-meta h4,
|
||||
.code-box-meta p {
|
||||
section.code-box-meta p {
|
||||
margin: 0;
|
||||
width: 93%;
|
||||
}
|
||||
@@ -165,6 +165,7 @@
|
||||
opacity: 0;
|
||||
overflow: auto;
|
||||
transition: all 0.4s ease;
|
||||
border-radius: 0 0 6px 6px;
|
||||
}
|
||||
.code-box .highlight-wrapper-expand {
|
||||
max-height: 500px;
|
||||
@@ -172,8 +173,11 @@
|
||||
}
|
||||
|
||||
.code-box .highlight {
|
||||
padding: 5px;
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #fff;
|
||||
}
|
||||
&:not(:first-child) {
|
||||
border-top: 1px dashed #e9e9e9;
|
||||
}
|
||||
@@ -254,7 +258,6 @@
|
||||
width:15%;
|
||||
float:right;
|
||||
margin:12px 10px 0;
|
||||
|
||||
}
|
||||
.code-box-demo .demo-content .demo-listBox .demo-list ul li {
|
||||
height: 25px;
|
||||
@@ -342,8 +345,6 @@
|
||||
content: "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// queue-animate style, should be remove after queue-animate is remove.
|
||||
.code-box-demo .demo-header {
|
||||
width: 100%;
|
||||
@@ -90,22 +90,22 @@
|
||||
|
||||
.component-select {
|
||||
&.ant-select-dropdown {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 8px rgba(0,0,0,0.25);
|
||||
font-size: 14px;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 8px rgba(0,0,0,0.25);
|
||||
font-size: 14px;
|
||||
}
|
||||
.ant-select-dropdown-menu {
|
||||
max-height: 200px;
|
||||
max-height: 200px;
|
||||
}
|
||||
.ant-select-dropdown-menu-item {
|
||||
border-radius: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.ant-component-decs {
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
color: #aaa;
|
||||
right: 16px;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
color: #aaa;
|
||||
right: 16px;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user