Merge branches 'master' and 'master' of https://github.com/vueComponent/ant-design

This commit is contained in:
tangjinzhou 2018-04-03 18:37:34 +08:00
commit b228ac22dc
47 changed files with 1619 additions and 12 deletions

View File

@ -8,6 +8,7 @@ import Offset from './offset'
import ResponsiveMore from './responsive-more'
import Responsive from './responsive'
import Sort from './sort'
import Playfround from './playfround'
import CN from '../index.zh-CN.md'
import US from '../index.en-US.md'
const md = {
@ -53,7 +54,7 @@ Following is a brief look at how it works:
## Flex layout
Our grid systems support Flex layout to allow the elements within the parent to be aligned horizontally - left, center, right, wide arrangement, and decentralized arrangement. The Grid system also supports vertical alignment - top aligned, vertically centered, bottom-aligned. You can also define the order of elements by using \`order\`.
Flex layout uses a 24 grid layout to define the width of each "box", but does not rigidly adhere to the grid layout.
## Examples
## Examples
`,
}
export default {
@ -125,6 +126,7 @@ export default {
<ResponsiveMore/>
<Responsive/>
<Sort/>
<Playfround />
</div>
<api>
<CN slot='cn' />

View File

@ -0,0 +1,96 @@
<cn>
#### 栅格配置器
可以简单配置几种等分栅格和间距。
</cn>
<us>
#### Playground
A simple playground for column count and gutter.
</us>
```html
<template>
<div id="components-grid-demo-playground">
<div style="marginBottom:16px">
<span style="marginRight:6px">Gutter (px): </span>
<div style="width:50%">
<a-slider
:min="0"
:max="Object.keys(gutters).length - 1"
v-model="gutterKey"
:marks="this.gutters"
:step="null"
/>
</div>
<span style="marginRight:6px">Column Count:</span>
<div style="width:50%">
<a-slider
:min="0"
:max="Object.keys(colCounts).length - 1"
v-model="colCountKey"
:marks="this.colCounts"
:step="null"
/>
</div>
</div>
<a-row :gutter="gutters[gutterKey]">
<a-col v-for="(item, index) in colCounts[colCountKey]" :key="item.toString()" :span="24/colCounts[colCountKey]">
<div>Column</div>
</a-col>
</a-row>
<pre v-text="rowColHtml">
</pre>
</div>
</template>
<script>
export default {
data () {
const gutters = {}
const arr = [8, 16, 24, 32, 40, 48]
arr.forEach((value, i) => { gutters[i] = value; })
const colCounts = {}
const arr1 = [2, 3, 4, 6, 8, 12]
arr1.forEach((value, i) => { colCounts[i] = value; })
return {
gutterKey: 1,
colCountKey: 2,
colCounts,
gutters,
}
},
computed: {
rowColHtml() {
const colCount = this.colCounts[this.colCountKey]
const getter = this.gutters[this.gutterKey]
let colCode = '<Row :gutter="' + getter + '">\n'
for (let i = 0; i < colCount; i++) {
const spanNum = 24 / colCount
colCode += ' <Col :span="' + spanNum + '"/>\n'
}
colCode += '</Row>'
return colCode
}
},
}
</script>
<style scoped>
#components-grid-demo-playground [class^="ant-col-"] {
background: transparent;
border: 0;
}
#components-grid-demo-playground [class^="ant-col-"] > div {
background: #00A0E9;
height: 120px;
line-height: 120px;
font-size: 13px;
}
#components-grid-demo-playground pre {
background: #f9f9f9;
border-radius: 6px;
font-size: 13px;
padding: 8px 16px;
}
</style>
```

View File

@ -140,3 +140,9 @@ export { Table, TableColumn, TableColumnGroup }
export { default as version } from './version'
export { default as Slider } from './slider'
export { default as Progress } from './progress'
import Timeline from './timeline'
const TimelineItem = Timeline.Item
export { Timeline, TimelineItem }

View File

@ -0,0 +1,48 @@
<cn>
#### 进度圈动态展示
会动的进度条才是好进度条。
</cn>
<us>
#### Dynamic circular progress bar
A dynamic progress bar is better.
</us>
```html
<template>
<div>
<a-progress type="circle" :percent="percent" />
<a-button-group>
<a-button @click="decline" icon="minus" />
<a-button @click="increase" icon="plus" />
</a-button-group>
</div>
</template>
<script>
export default {
data () {
return {
percent: 0,
}
},
methods: {
increase() {
let percent = this.percent + 10;
if (percent > 100) {
percent = 100;
}
this.percent = percent
},
decline() {
let percent = this.percent - 10;
if (percent < 0) {
percent = 0;
}
this.percent = percent
},
},
}
</script>
```

View File

@ -0,0 +1,28 @@
<cn>
#### 小型进度圈
小一号的圈形进度。
</cn>
<us>
#### Mini size circular progress bar
A smaller circular progress bar.
</us>
```html
<template>
<div>
<a-progress type="circle" :percent="30" :width="80" />
<a-progress type="circle" :percent="70" :width="80" status="exception" />
<a-progress type="circle" :percent="100" :width="80" />
</div>
</template>
<style scoped>
.ant-progress-circle-wrap,
.ant-progress-line-wrap {
margin-right: 8px;
margin-bottom: 5px;
}
</style>
```

View File

@ -0,0 +1,27 @@
<cn>
#### 进度圈
圈形的进度。
</cn>
<us>
#### Circular progress bar
A circular progress bar.
</us>
```html
<template>
<div>
<a-progress type="circle" :percent="75" />
<a-progress type="circle" :percent="70" status="exception" />
<a-progress type="circle" :percent="100" />
</div>
</template>
<style scoped>
.ant-progress-circle-wrap,
.ant-progress-line-wrap {
margin-right: 8px;
margin-bottom: 5px;
}
</style>
```

View File

@ -0,0 +1,17 @@
<cn>
#### 仪表盘
By setting `type=dashboard`, you can get a dashboard style of progress easily.
</cn>
<us>
#### Dashboard
A standard progress bar.
</us>
```html
<template>
<div>
<a-progress type="dashboard" :percent="75" />
</div>
</template>
```

View File

@ -0,0 +1,47 @@
<cn>
#### 动态展示
会动的进度条才是好进度条。
</cn>
<us>
#### Dynamic
A dynamic progress bar is better.
</us>
```html
<template>
<div>
<a-progress :percent="percent" />
<a-button-group>
<a-button @click="decline" icon="minus" />
<a-button @click="increase" icon="plus" />
</a-button-group>
</div>
</template>
<script>
export default {
data () {
return {
percent: 0,
}
},
methods: {
increase() {
let percent = this.percent + 10;
if (percent > 100) {
percent = 100;
}
this.percent = percent
},
decline() {
let percent = this.percent - 10;
if (percent < 0) {
percent = 0;
}
this.percent = percent
},
},
}
</script>
```

View File

@ -0,0 +1,25 @@
<cn>
#### 自定义文字格式
`format` 属性指定格式。
</cn>
<us>
#### Custom text format
You can custom text format by setting `format`.
</us>
```html
<template>
<div>
<a-progress type="circle" :percent="75" :format="percent => `${percent} Days`"/>
<a-progress type="circle" :percent="100" :format="() => 'Done'" />
</div>
</template>
<style scoped>
div.ant-progress-circle,
div.ant-progress-line {
margin-right: 8px;
margin-bottom: 8px;
}
</style>
```

View File

@ -0,0 +1,69 @@
<script>
import Line from './line.md'
import Circle from './circle.md'
import LineMini from './line-mini.md'
import CircleMini from './circle-mini.md'
import CircleDynamic from './circle-dynamic.md'
import Format from './format.md'
import Dynamic from './dynamic.md'
import Dashboard from './dashboard.md'
import Segment from './segment.md'
import CN from '../index.zh-CN.md'
import US from '../index.en-US.md'
const md = {
cn: `# 进度条
展示操作的当前进度
## 何时使用
在操作需要较长时间才能完成时为用户显示该操作的当前进度和状态
- 当一个操作会打断当前界面或者需要在后台运行且耗时可能超过2秒时
- 当需要显示一个操作完成的百分比时
## 代码演示`,
us: `# Progress
If it will take a long time to complete an operation, you can use 'Progress' to show the current progress and status.
- When an operation will interrupt the current interface, or it needs to run in the background for more than 2 seconds.
- When you need to display the completion percentage of an operation.
## Examples
`,
}
export default {
category: 'Components',
subtitle: '进度条',
type: 'Feedback',
title: 'Progress',
render () {
return (
<div>
<md cn={md.cn} us={md.us}/>
<br/>
<Line />
<br/>
<Circle />
<br/>
<LineMini />
<br/>
<CircleMini />
<br/>
<CircleDynamic />
<br/>
<Format />
<br/>
<Dynamic />
<br/>
<Dashboard />
<br/>
<Segment />
<br/>
<api>
<template slot='cn'>
<CN/>
</template>
<US/>
</api>
</div>
)
},
}
</script>

View File

@ -0,0 +1,22 @@
<cn>
#### 小型进度条
适合放在较狭窄的区域内。
</cn>
<us>
#### Mini size progress bar
Appropriate for a narrow area.
</us>
```html
<template>
<div style="width: 170px">
<a-progress :percent="30" size="small" />
<a-progress :percent="50" size="small" status="active" />
<a-progress :percent="70" size="small" status="exception" />
<a-progress :percent="100" size="small" />
</div>
</template>
```

View File

@ -0,0 +1,22 @@
<cn>
#### 进度条
标准的进度条。
</cn>
<us>
#### Progress bar
A standard progress bar.
</us>
```html
<template>
<div>
<a-progress :percent="30" />
<a-progress :percent="50" status="active" />
<a-progress :percent="70" status="exception" />
<a-progress :percent="100" />
<a-progress :percent="50" :showInfo="false" />
</div>
</template>
```

View File

@ -0,0 +1,18 @@
<cn>
#### 分段进度条
标准的进度条。
</cn>
<us>
#### Progress bar with success segment
A standard progress bar.
</us>
```html
<template>
<a-tooltip title="3 done / 3 in progress / 4 to do">
<a-progress :percent="60" :successPercent="30" />
</a-tooltip>
</template>
```

View File

@ -0,0 +1,15 @@
## API
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| format | template function of the content | function(percent) | `percent => percent + '%'` |
| gapDegree `(type=circle)` | the gap degree of half circle, 0 ~ 360 | number | 0 |
| gapPosition `(type=circle)` | the gap position, options: `top` `bottom` `left` `right` | string | `top` |
| percent | to set the completion percentage | number | 0 |
| showInfo | whether to display the progress value and the status icon | boolean | true |
| status | to set the status of the Progress, options: `success` `exception` `active` | string | - |
| strokeWidth `(type=line)` | to set the width of the progress bar, unit: `px` | number | 10 |
| strokeWidth `(type=circle)` | to set the width of the circular progress bar, unit: percentage of the canvas width | number | 6 |
| type | to set the type, options: `line` `circle` `dashboard` | string | `line` |
| width `(type=circle)` | to set the canvas width of the circular progress bar, unit: `px` | number | 120 |
| successPercent | segmented success percent, works when `type="line"` | number | 0 |

View File

@ -0,0 +1,5 @@
import Progress from './progress'
export { ProgressProps } from './progress'
export default Progress

View File

@ -0,0 +1,15 @@
## API
| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| format | 内容的模板函数 | function(percent) | `percent => percent + '%'` |
| gapDegree `(type=circle)` | 圆形进度条缺口角度,可取值 0 ~ 360 | number | 0 |
| gapPosition `(type=circle)` | 圆形进度条缺口位置 | Enum{ 'top', 'bottom', 'left', 'right' } | `top` |
| percent | 百分比 | number | 0 |
| showInfo | 是否显示进度数值或状态图标 | boolean | true |
| status | 状态,可选:`success` `exception` `active` | string | - |
| strokeWidth `(type=line)` | 进度条线的宽度,单位 px | number | 10 |
| strokeWidth `(type=circle)` | 圆形进度条线的宽度,单位是进度条画布宽度的百分比 | number | 6 |
| type | 类型,可选 `line` `circle` `dashboard` | string | line |
| width `(type=circle)` | 圆形进度条画布宽度,单位 px | number | 120 |
| successPercent | 已完成的分段百分比,`type="line"` 时有效 | number | 0 |

View File

@ -0,0 +1,135 @@
import classNames from 'classnames'
import PropTypes from '../_util/vue-types'
import { getOptionProps, initDefaultProps } from '../_util/props-util'
import Icon from '../icon'
import { Circle } from '../vc-progress'
function addUnit (num, unit) {
const unitType = unit || 'px'
return num ? num + unitType : null
}
const statusColorMap = {
normal: '#108ee9',
exception: '#ff5500',
success: '#87d068',
}
export const ProgressProps = {
prefixCls: PropTypes.string,
type: PropTypes.oneOf(['line', 'circle', 'dashboard']),
percent: PropTypes.number,
successPercent: PropTypes.number,
format: PropTypes.func,
status: PropTypes.oneOf(['success', 'active', 'exception']),
showInfo: PropTypes.bool,
strokeWidth: PropTypes.number,
trailColor: PropTypes.string,
width: PropTypes.number,
gapDegree: PropTypes.number,
gapPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
size: PropTypes.oneOf(['default', 'small']),
}
export default {
name: 'Progress',
props: initDefaultProps(ProgressProps, {
type: 'line',
percent: 0,
showInfo: true,
trailColor: '#f3f3f3',
prefixCls: 'ant-progress',
size: 'default',
}),
render () {
const {
prefixCls, percent = 0, status, format, trailColor, size, successPercent,
type, strokeWidth, width, showInfo, gapDegree = 0, gapPosition,
} = getOptionProps(this)
const progressStatus = parseInt(percent.toString(), 10) >= 100 && !(status)
? 'success' : (status || 'normal')
let progressInfo
let progress
const textFormatter = format || (percentNumber => `${percentNumber}%`)
if (showInfo) {
let text
const iconType = (type === 'circle' || type === 'dashboard') ? '' : '-circle'
if (progressStatus === 'exception') {
text = format ? textFormatter(percent) : <Icon type={`cross${iconType}`} />
} else if (progressStatus === 'success') {
text = format ? textFormatter(percent) : <Icon type={`check${iconType}`} />
} else {
text = textFormatter(percent)
}
progressInfo = <span class={`${prefixCls}-text`}>{text}</span>
}
if (type === 'line') {
const percentStyle = {
width: `${percent}%`,
height: addUnit(strokeWidth) || (size === 'small' ? '6px' : '8px'),
}
const successPercentStyle = {
width: `${successPercent}%`,
height: addUnit(strokeWidth) || (size === 'small' ? '6px' : '8px'),
}
const successSegment = successPercent !== undefined
? <div class={`${prefixCls}-success-bg`} style={successPercentStyle} />
: null
progress = (
<div>
<div class={`${prefixCls}-outer`}>
<div class={`${prefixCls}-inner`}>
<div class={`${prefixCls}-bg`} style={percentStyle} />
{successSegment}
</div>
</div>
{progressInfo}
</div>
)
} else if (type === 'circle' || type === 'dashboard') {
const circleSize = width || 120
const circleStyle = {
width: addUnit(circleSize),
height: addUnit(circleSize),
fontSize: addUnit(circleSize * 0.15 + 6),
}
const circleWidth = strokeWidth || 6
const gapPos = gapPosition || type === 'dashboard' && 'bottom' || 'top'
const gapDeg = gapDegree || (type === 'dashboard' && 75)
progress = (
<div class={`${prefixCls}-inner`} style={circleStyle}>
<Circle
percent={percent}
strokeWidth={circleWidth}
trailWidth={circleWidth}
strokeColor={statusColorMap[progressStatus]}
trailColor={trailColor}
prefixCls={prefixCls}
gapDegree={gapDeg || 0}
gapPosition={gapPos}
/>
{progressInfo}
</div>
)
}
const classString = classNames(prefixCls, {
[`${prefixCls}-${type === 'dashboard' && 'circle' || type}`]: true,
[`${prefixCls}-status-${progressStatus}`]: true,
[`${prefixCls}-show-info`]: showInfo,
[`${prefixCls}-${size}`]: size,
})
const progressProps = {
on: this.$listeners,
class: classString,
}
return (
<div {...progressProps}>
{progress}
</div>
)
},
}

View File

@ -0,0 +1,2 @@
import '../../style/index.less'
import './index.less'

View File

@ -0,0 +1,167 @@
@import "../../style/themes/default";
@import "../../style/mixins/index";
@progress-prefix-cls: ~"@{ant-prefix}-progress";
.@{progress-prefix-cls} {
.reset-component;
display: inline-block;
&-line {
width: 100%;
font-size: @font-size-base;
position: relative;
}
&-small&-line,
&-small&-line &-text .@{iconfont-css-prefix} {
font-size: @font-size-sm;
}
&-outer {
display: inline-block;
width: 100%;
margin-right: 0;
padding-right: 0;
.@{progress-prefix-cls}-show-info & {
padding-right: ~"calc(2em + 8px)";
margin-right: ~"calc(-2em - 8px)";
}
}
&-inner {
display: inline-block;
width: 100%;
background-color: @progress-remaining-color;
border-radius: 100px;
vertical-align: middle;
position: relative;
}
&-circle-trail {
stroke: @progress-remaining-color;
}
&-circle-path {
stroke: @progress-default-color;
animation: ~"@{ant-prefix}-progress-appear" .3s;
}
&-success-bg,
&-bg {
border-radius: 100px;
background-color: @progress-default-color;
transition: all .4s @ease-out-circ 0s;
position: relative;
}
&-success-bg {
background-color: @success-color;
position: absolute;
top: 0;
left: 0;
}
&-text {
word-break: normal;
width: 2em;
text-align: left;
font-size: 1em;
margin-left: 8px;
vertical-align: middle;
display: inline-block;
color: @text-color-secondary;
line-height: 1;
.@{iconfont-css-prefix} {
font-size: @font-size-base;
}
}
&-status-active {
.@{progress-prefix-cls}-bg:before {
content: "";
opacity: 0;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: @component-background;
border-radius: 10px;
animation: ~"@{ant-prefix}-progress-active" 2.4s @ease-out-quint infinite;
}
}
&-status-exception {
.@{progress-prefix-cls}-bg {
background-color: @error-color;
}
.@{progress-prefix-cls}-text {
color: @error-color;
}
.@{progress-prefix-cls}-circle-path {
stroke: @error-color;
}
}
&-status-success {
.@{progress-prefix-cls}-bg {
background-color: @success-color;
}
.@{progress-prefix-cls}-text {
color: @success-color;
}
.@{progress-prefix-cls}-circle-path {
stroke: @success-color;
}
}
&-circle &-inner {
position: relative;
line-height: 1;
background-color: transparent;
}
&-circle &-text {
display: block;
position: absolute;
width: 100%;
text-align: center;
line-height: 1;
top: 50%;
transform: translateY(-50%);
left: 0;
margin: 0;
color: @text-color;
.@{iconfont-css-prefix} {
font-size: 14 / 12em;
}
}
&-circle&-status-exception {
.@{progress-prefix-cls}-text {
color: @error-color;
}
}
&-circle&-status-success {
.@{progress-prefix-cls}-text {
color: @success-color;
}
}
}
@keyframes ~"@{ant-prefix}-progress-active" {
0% {
opacity: 0.1;
width: 0;
}
20% {
opacity: 0.5;
width: 0;
}
100% {
opacity: 0;
width: 100%;
}
}

View File

@ -1,6 +1,6 @@
<script>
import Basic from './basic.md'
import InputNumber from './input-number.md'
// import InputNumber from './input-number.md'
import IconSlider from './icon-slider.md'
import TipFormatter from './tip-formatter.md'
import Event from './event.md'
@ -34,8 +34,6 @@ export default {
<br/>
<Basic />
<br />
<InputNumber />
<br />
<IconSlider />
<br />
<TipFormatter />

View File

@ -36,3 +36,5 @@ import './calendar/style'
import './date-picker/style'
import './slider/style'
import './table/style'
import './progress/style'
import './timeline/style'

View File

@ -0,0 +1,58 @@
import classNames from 'classnames'
import PropTypes from '../_util/vue-types'
import { getOptionProps, initDefaultProps, filterEmpty, getComponentFromProp } from '../_util/props-util'
import { cloneElement } from '../_util/vnode'
import TimelineItem from './TimelineItem'
import Icon from '../icon'
export const TimelineProps = {
prefixCls: PropTypes.string,
className: PropTypes.string,
/** 指定最后一个幽灵节点是否存在或内容 */
pending: PropTypes.any,
}
export default {
name: 'Timeline',
props: initDefaultProps(TimelineProps, {
prefixCls: 'ant-timeline',
}),
render () {
const { prefixCls, ...restProps } = getOptionProps(this)
const pending = getComponentFromProp(this, 'pending')
const pendingNode = typeof pending === 'boolean' ? null : pending
const classString = classNames(prefixCls, {
[`${prefixCls}-pending`]: !!pending,
})
// Remove falsy items
const falsylessItems = filterEmpty(this.$slots.default)
const items = falsylessItems.map((item, idx) => {
return cloneElement(item, {
props: {
last: falsylessItems.length - 1 === idx,
},
})
})
const pendingItem = (pending) ? (
<TimelineItem
pending={!!pending}
>
<Icon slot='dot' type='loading' />
{pendingNode}
</TimelineItem>
) : null
const timelineProps = {
props: {
...restProps,
},
class: classString,
on: this.$listeners,
}
return (
<ul {...timelineProps}>
{items}
{pendingItem}
</ul>
)
},
}

View File

@ -0,0 +1,52 @@
import classNames from 'classnames'
import PropTypes from '../_util/vue-types'
import { getOptionProps, initDefaultProps, getComponentFromProp } from '../_util/props-util'
export const TimeLineItemProps = {
prefixCls: PropTypes.string,
className: PropTypes.string,
color: PropTypes.string,
dot: PropTypes.any,
pending: PropTypes.bool,
last: PropTypes.bool,
}
export default {
name: 'TimelineItem',
props: initDefaultProps(TimeLineItemProps, {
prefixCls: 'ant-timeline',
color: 'blue',
last: false,
pending: false,
}),
render () {
const { prefixCls, color = '', last, pending, ...restProps } = getOptionProps(this)
const dot = getComponentFromProp(this, 'dot')
const itemClassName = classNames({
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-last`]: last,
[`${prefixCls}-item-pending`]: pending,
})
const dotClassName = classNames({
[`${prefixCls}-item-head`]: true,
[`${prefixCls}-item-head-custom`]: dot,
[`${prefixCls}-item-head-${color}`]: true,
})
return (
<li {...restProps} class={itemClassName}>
<div class={`${prefixCls}-item-tail`} />
<div
class={dotClassName}
style={{ borderColor: /blue|red|green/.test(color) ? null : color }}
>
{dot}
</div>
<div class={`${prefixCls}-item-content`}>
{this.$slots.default}
</div>
</li>
)
},
}

View File

@ -0,0 +1,22 @@
<cn>
#### 基本用法
基本的时间轴。
</cn>
<us>
#### Basic
Basic timeline.
</us>
```html
<template>
<a-timeline>
<a-timeline-item>Create a services site 2015-09-01</a-timeline-item>
<a-timeline-item>Solve initial network problems 2015-09-01</a-timeline-item>
<a-timeline-item>Technical testing 2015-09-01</a-timeline-item>
<a-timeline-item>Network problems being solved 2015-09-01</a-timeline-item>
</a-timeline>
</template>
```

View File

@ -0,0 +1,31 @@
<cn>
#### 圆圈颜色
圆圈颜色,绿色用于已完成、成功状态,红色表示告警或错误状态,蓝色可表示正在进行或其他默认状态。
</cn>
<us>
#### Color
Set the color of circles. `green` means completed or success status, `red` means warning or error, and `blue` means ongoing or other default status.
</us>
```html
<template>
<a-timeline>
<a-timeline-item color="green">Create a services site 2015-09-01</a-timeline-item>
<a-timeline-item color="green">Create a services site 2015-09-01</a-timeline-item>
<a-timeline-item color="red">
<p>Solve initial network problems 1</p>
<p>Solve initial network problems 2</p>
<p>Solve initial network problems 3 2015-09-01</p>
</a-timeline-item>
<a-timeline-item>
<p>Technical testing 1</p>
<p>Technical testing 2</p>
<p>Technical testing 3 2015-09-01</p>
</a-timeline-item>
</a-timeline>
</template>
```

View File

@ -0,0 +1,26 @@
<cn>
#### 自定义时间轴点
基本的时间轴。
</cn>
<us>
#### Custom
Set a node as an icon or other custom element.
</us>
```html
<template>
<a-timeline>
<a-timeline-item>Create a services site 2015-09-01</a-timeline-item>
<a-timeline-item>Solve initial network problems 2015-09-01</a-timeline-item>
<a-timeline-item color="red">
<a-icon slot="dot" type="clock-circle-o" style="fontSize: '16px'" />
Technical testing 2015-09-01
</a-timeline-item>
<a-timeline-item>Network problems being solved 2015-09-01</a-timeline-item>
</a-timeline>
</template>
```

View File

@ -0,0 +1,54 @@
<script>
import Basic from './basic.md'
import Color from './color.md'
import Pending from './pending.md'
import Custom from './custom.md'
import CN from '../index.zh-CN.md'
import US from '../index.en-US.md'
const md = {
cn: `# 时间轴
垂直展示的时间流信息
## 何时使用
在操作需要较长时间才能完成时为用户显示该操作的当前进度和状态
- 当有一系列信息需按时间排列时可正序和倒序
- 需要有一条时间轴进行视觉上的串联时
## 代码演示`,
us: `# Data Display
Vertical display timeline.
- When a series of information needs to be ordered by time (ascend or descend).
- When you need a timeline to make a visual connection.
## Examples
`,
}
export default {
category: 'Components',
subtitle: '时间轴',
type: 'Data Display',
title: 'Timeline',
render () {
return (
<div>
<md cn={md.cn} us={md.us}/>
<br/>
<Basic />
<br/>
<Color />
<br/>
<Pending />
<br/>
<Custom />
<br/>
<api>
<template slot='cn'>
<CN/>
</template>
<US/>
</api>
</div>
)
},
}
</script>

View File

@ -0,0 +1,23 @@
<cn>
#### 最后一个
当任务状态正在发生,还在记录过程中,可用幽灵节点来表示当前的时间节点。(用于时间正序排列)
</cn>
<us>
#### Last node
When the timeline is incomplete and ongoing, put a ghost node at last. set `pending={true}` or `pending={a React Element}`. Used in ascend chronological order.
</us>
```html
<template>
<a-timeline pending="Recording...">
<a-timeline-item>Create a services site 2015-09-01</a-timeline-item>
<a-timeline-item>Solve initial network problems 2015-09-01</a-timeline-item>
<a-timeline-item>Technical testing 2015-09-01</a-timeline-item>
</a-timeline>
</template>
```

View File

@ -0,0 +1,27 @@
## API
```` html
<Timeline>
<Timeline.Item>step1 2015-09-01</Timeline.Item>
<Timeline.Item>step2 2015-09-01</Timeline.Item>
<Timeline.Item>step3 2015-09-01</Timeline.Item>
<Timeline.Item>step4 2015-09-01</Timeline.Item>
</Timeline>
````
### Timeline
Timeline
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| pending | Set the last ghost node's existence or its content | boolean\|string\|slot | `false` |
### Timeline.Item
Node of timeline
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| color | Set the circle's color to `blue`, `red`, `green` or other custom colors | string | `blue` |
| dot | Customize timeline dot | string\|slot | - |

View File

@ -0,0 +1,9 @@
import Timeline from './Timeline'
export { TimelineProps } from './Timeline'
export { TimeLineItemProps } from './TimelineItem'
import TimelineItem from './TimelineItem'
Timeline.Item = TimelineItem
export default Timeline

View File

@ -0,0 +1,27 @@
## API
```` html
<Timeline>
<Timeline.Item>创建服务现场 2015-09-01</Timeline.Item>
<Timeline.Item>初步排除网络异常 2015-09-01</Timeline.Item>
<Timeline.Item>技术测试异常 2015-09-01</Timeline.Item>
<Timeline.Item>网络异常正在修复 2015-09-01</Timeline.Item>
</Timeline>
````
### Timeline
时间轴。
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| pending | 指定最后一个幽灵节点是否存在或内容 | boolean\|string\|slot | false |
### Timeline.Item
时间轴的每一个节点。
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| color | 指定圆圈颜色 `blue, red, green`,或自定义的色值 | string | blue |
| dot | 自定义时间轴点 | string\|slot | - |

View File

@ -0,0 +1,2 @@
import '../../style/index.less'
import './index.less'

View File

@ -0,0 +1,93 @@
@import "../../style/themes/default";
@import "../../style/mixins/index";
@timeline-prefix-cls: ~"@{ant-prefix}-timeline";
@timeline-color: @border-color-split;
.@{timeline-prefix-cls} {
.reset-component;
list-style: none;
margin: 0;
padding: 0;
&-item {
position: relative;
padding: 0 0 20px;
list-style: none;
margin: 0;
font-size: @font-size-base;
&-tail {
position: absolute;
left: 4px;
top: 0.75em;
height: 100%;
border-left: 2px solid @timeline-color;
}
&-pending &-head {
font-size: @font-size-sm;
}
&-pending &-tail {
display: none;
}
&-head {
position: absolute;
width: 10px;
height: 10px;
background-color: @component-background;
border-radius: 100px;
border: 2px solid transparent;
&-blue {
border-color: @primary-color;
color: @primary-color;
}
&-red {
border-color: @error-color;
color: @error-color;
}
&-green {
border-color: @success-color;
color: @success-color;
}
}
&-head-custom {
position: absolute;
text-align: center;
line-height: 1;
margin-top: 0;
border: 0;
height: auto;
border-radius: 0;
padding: 3px 0;
transform: translate(-50%, -50%);
top: 5px;
left: 5px;
width: auto;
}
&-content {
padding: 0 0 0 18px;
position: relative;
top: -(@font-size-base * @line-height-base - @font-size-base) + 1px;
}
&-last {
.@{timeline-prefix-cls}-item-tail {
border-left: 2px dotted @timeline-color;
display: none;
}
.@{timeline-prefix-cls}-item-content {
min-height: 48px;
}
}
}
&&-pending &-item-last &-item-tail {
display: block;
}
}

View File

View File

@ -0,0 +1,42 @@
import { Line, Circle } from '../index'
import '../assets/index.less'
export default {
data () {
return {
percent: 0,
}
},
mounted () {
this.$nextTick(() => {
this.increase()
})
},
methods: {
increase () {
const percent = this.percent + 1
if (percent >= 100) {
clearTimeout(this.tm)
return
}
this.percent = percent
this.tm = setTimeout(this.increase, 10)
},
restart () {
clearTimeout(this.tm)
this.percent = 0
this.$nextTick(() => {
this.increase()
})
},
},
render () {
return (
<div style='margin: 10px;width: 200px'>
<Circle strokeWidth='6' percent={this.percent} />
<Line strokeWidth='4' percent={this.percent} />
<button onClick={this.restart}>Restart</button>
</div>
)
},
}

View File

@ -0,0 +1,72 @@
import { Circle } from '../index'
import '../assets/index.less'
export default {
data () {
return {
percent: 30,
color: '#3FC7FA',
}
},
methods: {
changeState () {
const colorMap = ['#3FC7FA', '#85D262', '#FE8C6A']
const value = parseInt(Math.random() * 100, 10)
this.percent = value
this.color = colorMap[parseInt(Math.random() * 3, 10)]
},
},
render () {
const circleContainerStyle = {
width: '200px',
height: '200px',
}
return (
<div>
<div style={circleContainerStyle}>
<Circle
percent={this.percent}
gapDegree='70'
gapPosition='top'
strokeWidth='6'
strokeLinecap='square'
strokeColor={this.color}
/>
</div>
<div style={circleContainerStyle}>
<Circle
percent={this.percent}
gapDegree='70'
gapPosition='bottom'
strokeWidth='6'
strokeLinecap='square'
strokeColor={this.color}
/>
</div>
<div style={circleContainerStyle}>
<Circle
percent={this.percent}
gapDegree='70'
gapPosition='left'
strokeWidth='6'
strokeLinecap='square'
strokeColor={this.color}
/>
</div>
<div style={circleContainerStyle}>
<Circle
percent={this.percent}
gapDegree='70'
gapPosition='right'
strokeWidth='6'
strokeLinecap='square'
strokeColor={this.color}
/>
</div>
<p>
<button onClick={this.changeState}>Change State</button>
</p>
</div>
)
},
}

View File

@ -0,0 +1,49 @@
import { Line, Circle } from '../index'
import '../assets/index.less'
export default {
data () {
return {
percent: 30,
color: '#3FC7FA',
}
},
methods: {
changeState () {
const colorMap = ['#3FC7FA', '#85D262', '#FE8C6A']
const value = parseInt(Math.random() * 100, 10)
this.percent = value
this.color = colorMap[parseInt(Math.random() * 3, 10)]
},
},
render () {
const containerStyle = {
width: '250px',
}
const circleContainerStyle = {
width: '250px',
height: '250px',
display: 'inline-block',
}
return (
<div>
<h3>Line Progress {this.percent}%</h3>
<div style={containerStyle}>
<Line percent={this.percent} strokeWidth='4' strokeColor={this.color} />
</div>
<h3>Circle Progress {this.percent}%</h3>
<div style={circleContainerStyle}>
<Circle
percent={this.percent}
strokeWidth='6'
strokeLinecap='round'
strokeColor={this.color}
/>
</div>
<p>
<button onClick={this.changeState}>Change State</button>
</p>
</div>
)
},
}

View File

@ -0,0 +1,8 @@
import Progress, { Line, Circle } from './src/';
export {
Line,
Circle,
};
export default Progress;

View File

@ -0,0 +1,115 @@
import PropTypes from '../../_util/vue-types'
import { initDefaultProps } from '../../_util/props-util'
import enhancer from './enhancer'
import { propTypes, defaultProps } from './types'
const circlePropTypes = {
...propTypes,
gapPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
gapDegree: PropTypes.number,
}
const circleDefaultProps = {
...defaultProps,
gapPosition: 'top',
}
const Circle = {
props: initDefaultProps(circlePropTypes, circleDefaultProps),
methods: {
getPathStyles () {
const { percent, strokeWidth, gapDegree = 0, gapPosition } = this.$props
const radius = 50 - (strokeWidth / 2)
let beginPositionX = 0
let beginPositionY = -radius
let endPositionX = 0
let endPositionY = -2 * radius
switch (gapPosition) {
case 'left':
beginPositionX = -radius
beginPositionY = 0
endPositionX = 2 * radius
endPositionY = 0
break
case 'right':
beginPositionX = radius
beginPositionY = 0
endPositionX = -2 * radius
endPositionY = 0
break
case 'bottom':
beginPositionY = radius
endPositionY = 2 * radius
break
default:
}
const pathString = `M 50,50 m ${beginPositionX},${beginPositionY}
a ${radius},${radius} 0 1 1 ${endPositionX},${-endPositionY}
a ${radius},${radius} 0 1 1 ${-endPositionX},${endPositionY}`
const len = Math.PI * 2 * radius
const trailPathStyle = {
strokeDasharray: `${len - gapDegree}px ${len}px`,
strokeDashoffset: `-${gapDegree / 2}px`,
transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s',
}
const strokePathStyle = {
strokeDasharray: `${(percent / 100) * (len - gapDegree)}px ${len}px`,
strokeDashoffset: `-${gapDegree / 2}px`,
transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s', // eslint-disable-line
}
return { pathString, trailPathStyle, strokePathStyle }
},
},
render () {
const {
prefixCls, strokeWidth, trailWidth, strokeColor,
trailColor, strokeLinecap, percent, ...restProps
} = this.$props
const { pathString, trailPathStyle, strokePathStyle } = this.getPathStyles()
delete restProps.percent
delete restProps.gapDegree
delete restProps.gapPosition
const pathFirst = {
attrs: {
'd': pathString,
'stroke': trailColor,
'stroke-width': trailWidth || strokeWidth,
'fill-opacity': '0',
},
class: `${prefixCls}-circle-trail`,
style: trailPathStyle,
}
const pathSecond = {
attrs: {
'd': pathString,
'stroke-linecap': strokeLinecap,
'stroke': strokeColor,
'stroke-width': percent === 0 ? 0 : strokeWidth,
'fill-opacity': '0',
},
class: `${prefixCls}-circle-path`,
style: strokePathStyle,
ref: 'svgPathRef',
}
return (
<svg
class={`${prefixCls}-circle`}
viewBox='0 0 100 100'
{...restProps}
>
<path
{...pathFirst}
/>
{
percent > 0 ? (
<path
{...pathSecond}
/>
) : null
}
</svg>
)
},
}
export default enhancer(Circle)

View File

@ -0,0 +1,73 @@
import { initDefaultProps } from '../../_util/props-util'
import enhancer from './enhancer'
import { propTypes, defaultProps } from './types'
const Line = {
props: initDefaultProps(propTypes, defaultProps),
render () {
const {
percent,
prefixCls,
strokeColor,
strokeLinecap,
strokeWidth,
trailColor,
trailWidth,
...restProps
} = this.$props
delete restProps.gapPosition
const pathStyle = {
strokeDasharray: '100px, 100px',
strokeDashoffset: `${(100 - percent)}px`,
transition: 'stroke-dashoffset 0.3s ease 0s, stroke 0.3s linear',
}
const center = strokeWidth / 2
const right = 100 - (strokeWidth / 2)
const pathString =
`M ${strokeLinecap === 'round' ? center : 0},${center}
L ${strokeLinecap === 'round' ? right : 100},${center}`
const viewBoxString = `0 0 100 ${strokeWidth}`
const pathFirst = {
attrs: {
'd': pathString,
'stroke-linecap': strokeLinecap,
'stroke': trailColor,
'stroke-width': trailWidth || strokeWidth,
'fill-opacity': '0',
},
class: `${prefixCls}-line-trail`,
}
const pathSecond = {
attrs: {
'd': pathString,
'stroke-linecap': strokeLinecap,
'stroke': strokeColor,
'stroke-width': strokeWidth,
'fill-opacity': '0',
},
class: `${prefixCls}-line-path`,
style: pathStyle,
ref: 'svgPathRef',
}
return (
<svg
class={`${prefixCls}-line`}
viewBox={viewBoxString}
preserveAspectRatio='none'
{...restProps}
>
<path
{...pathFirst}
/>
<path
{...pathSecond}
/>
</svg>
)
},
}
export default enhancer(Line)

View File

@ -0,0 +1,21 @@
function enhancer (Component) {
return {
mixins: [Component],
updated () {
this.$nextTick(() => {
if (!this.$refs.svgPathRef) {
return
}
const pathStyle = this.$refs.svgPathRef.style
pathStyle.transitionDuration = '.3s, .3s, .3s, .06s'
const now = Date.now()
if (this.prevTimeStamp && now - this.prevTimeStamp < 100) {
pathStyle.transitionDuration = '0s, 0s'
}
this.prevTimeStamp = Date.now()
})
},
}
}
export default enhancer

View File

@ -0,0 +1,12 @@
import Line from './Line'
import Circle from './Circle'
export {
Line,
Circle,
}
export default {
Line,
Circle,
}

View File

@ -0,0 +1,25 @@
import PropTypes from '../../_util/vue-types'
export const defaultProps = {
// className: '',
percent: 0,
prefixCls: 'rc-progress',
strokeColor: '#2db7f5',
strokeLinecap: 'round',
strokeWidth: 1,
// style: {},
trailColor: '#D9D9D9',
trailWidth: 1,
}
export const propTypes = {
// className: PropTypes.string,
percent: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
prefixCls: PropTypes.string,
strokeColor: PropTypes.string,
strokeLinecap: PropTypes.oneOf(['butt', 'round', 'square']),
strokeWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
// style: PropTypes.object,
trailColor: PropTypes.string,
trailWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
}

View File

@ -13,7 +13,6 @@ function noop () {}
export default function createSlider (Component) {
// const displayName = `ComponentEnhancer(${Component.displayName})`
const propTypes = {
...Component.propTypes,
min: PropTypes.number,
max: PropTypes.number,
step: PropTypes.number,
@ -41,7 +40,6 @@ export default function createSlider (Component) {
event: 'change',
},
props: initDefaultProps(propTypes, {
...Component.defaultProps,
prefixCls: 'rc-slider',
min: 0,
max: 100,

View File

@ -33,7 +33,7 @@ Carousel
Mention
##万
Grid | done slider完成后补全playground demo
Grid | done
Layout
Anchor
Tree
@ -50,8 +50,7 @@ Collapse | done
Spin | done
Switch | done
Steps | done
Progress
Slider
Table
Timeline
Progress | done
Slider | done InputNumber做完补全demo
Timeline | done
Transfer

View File

@ -35,3 +35,6 @@ export { default as steps } from 'antd/steps/demo/index.vue'
export { default as calendar } from 'antd/calendar/demo/index.vue'
export { default as datePicker } from 'antd/date-picker/demo/index.vue'
export { default as localeProvider } from 'antd/locale-provider/demo/index.vue'
export { default as slider } from 'antd/slider/demo/index.vue'
export { default as progress } from 'antd/progress/demo/index.vue'
export { default as timeline } from 'antd/timeline/demo/index.vue'

View File

@ -3,7 +3,7 @@ const AsyncComp = () => {
const hashs = window.location.hash.split('/')
const d = hashs[hashs.length - 1]
return {
component: import(`../components/table/demo/${d}`),
component: import(`../components/grid/demo/${d}`),
}
}
export default [