add switch fix spin demo

This commit is contained in:
wangxueliang 2018-02-27 12:14:29 +08:00
parent 5471f29705
commit 06cf31cd60
28 changed files with 768 additions and 8 deletions

View File

@ -17,6 +17,7 @@ const md = {
- 对复杂区域进行分组和隐藏保持页面的整洁
- '手风琴' 是一种特殊的折叠面板只允许单个内容区域展开
## 代码演示`,
us: `# When To Use

View File

@ -9,6 +9,7 @@ const md = {
## 何时使用
- 对不同章节的文本段落进行分割
- 对行内文字/链接进行分割例如表格的操作列
## 代码演示`,
us: `# Divider
A divider line separates different content.

View File

@ -76,3 +76,5 @@ const SelectOption = Select.Option
const SelectOptGroup = Select.OptGroup
export { Select, SelectOption, SelectOptGroup }
export { default as Switch } from './switch'

View File

@ -11,6 +11,7 @@ const md = {
## 何时使用
- 可提供成功警告和错误等反馈信息
- 顶部居中显示并自动消失是一种不打断用户操作的轻量级提示方式
## 代码演示`,
us: `# Message
Display global messages as feedback in response to user operations.

View File

@ -16,6 +16,7 @@ const md = {
- 较为复杂的通知内容
- 带有交互的通知给出用户下一步的行动点
- 系统主动推送
## 代码演示`,
us: `# Notification
Display a notification message globally.

View File

@ -20,6 +20,7 @@ const md = {
## 何时使用
- 弹出一个下拉菜单给用户选择操作用于代替原生的选择器或者需要一个更优雅的多选器时
- 当选项少时少于 5 建议直接将选项平铺使用 [Radio](#/cn/components/radio/) 是更好的选择
## 代码演示`,
us: `# Select
Select component to select value from options.

View File

@ -50,13 +50,13 @@ export default {
}
},
watch: {
spinning (val) {
const { delay, stateSpinning, spinning } = this
spinning () {
const { delay, spinning } = this
if (this.debounceTimeout) {
clearTimeout(this.debounceTimeout)
}
if (stateSpinning && !spinning) {
if (!spinning) {
this.debounceTimeout = window.setTimeout(() => this.setState({ stateSpinning: spinning }), 200)
if (this.delayTimeout) {
clearTimeout(this.delayTimeout)

View File

@ -23,7 +23,7 @@ Specifies a delay for loading state. If `spinning` ends during delay, loading st
可以点击‘切换’按钮,延迟显示 loading 效果。当 spinning 状态在 `delay` 时间内结束,则不显示 loading 状态。
</div>
</a-spin>
<a-button @click="changeSpinning" style="margin-top: 5px">切换</a-button>
Loading state<a-switch v-model="spinning"></a-switch>
</div>
</template>
<script>

View File

@ -23,7 +23,7 @@ Embedding content into `Spin` will alter it into loading state.
可以点击切换按钮控制本区域的spin展示。
</div>
</a-spin>
<a-button @click="changeSpinning" style="margin-top: 5px">切换</a-button>
Loading state<a-switch v-model="spinning"></a-switch>
</div>
</template>
<script>

View File

@ -22,3 +22,4 @@ import './notification/style'
import './message/style'
import './spin/style'
import './select/style'
import './switch/style'

View File

@ -0,0 +1,30 @@
<cn>
#### 基本用法
最简单的用法。
</cn>
<us>
#### basic Usage
The most basic usage.
</us>
```html
<template>
<div>
<a-switch defaultChecked @change='onChange'/>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods: {
onChange(checked){
console.log(`a-switch to ${checked}`);
}
},
}
</script>
```

View File

@ -0,0 +1,33 @@
<cn>
#### 不可用
Switch 失效状态。
</cn>
<us>
#### Disabled
Disabled state of `Switch`.
</us>
```html
<template>
<div>
<a-switch defaultChecked :disabled="disabled" style="margin-bottom:5px"/>
<br/>
<a-button type="primary" @click='onToggle'>Toggle disabled</Button>
</div>
</template>
<script>
export default {
data () {
return {
disabled: true,
}
},
methods: {
onToggle(){
this.disabled = !this.disabled
}
},
}
</script>
```

View File

@ -0,0 +1,55 @@
<script>
import Basic from './basic'
import Disabled from './disabled'
import Text from './text'
import Size from './size'
import Loading from './loading'
import CN from '../index.zh-CN.md'
import US from '../index.en-US.md'
const md = {
cn: `# Switch
开关选择器
## 何时使用
- 需要表示开关状态/两种状态之间的切换时
- 'checkbox'的区别是切换 'switch' 会直接触发状态改变 'checkbox' 一般用于状态标记需要和提交操作配合
## 代码演示`,
us: `# Switch
Switching Selector.
## When To Use
- If you need to represent the switching between two states or on-off state.
- The difference between 'Switch' and 'Checkbox' is that 'Switch' will trigger a state change directly when you toggle it, while 'Checkbox' is generally used for state marking, which should work in conjunction with submit operation.`,
}
export default {
render () {
return (
<div>
<md cn={md.cn} us={md.us}/>
<Basic />
<br/>
<Disabled />
<br/>
<Text />
<br/>
<Size />
<br/>
<Loading />
<br/>
<api>
<template slot='cn'>
<CN/>
</template>
<US/>
</api>
</div>
)
},
}
</script>

View File

@ -0,0 +1,19 @@
<cn>
#### 加载中
标识开关操作仍在执行中。
</cn>
<us>
#### Loading
Mark a pending state of switch.
</us>
```html
<template>
<div>
<a-switch loading defaultChecked/>
<br>
<a-switch size="small" loading/>
</div>
</template>
```

View File

@ -0,0 +1,19 @@
<cn>
#### 两种大小
`size="small"` 表示小号开关。
</cn>
<us>
#### Two sizes
`size="small"` represents a small sized switch.
</us>
```html
<template>
<div>
<a-switch defaultChecked/>
<br>
<a-switch size="small" defaultChecked/>
</div>
</template>
```

View File

@ -0,0 +1,24 @@
<cn>
#### 文字和图标
带有文字和图标。
</cn>
<us>
#### Text & icon
With text and icon.
</us>
```html
<template>
<div>
<a-switch checkedChildren="开" unCheckedChildren="关" defaultChecked/>
<br>
<a-switch checkedChildren="1" unCheckedChildren="0"/>
<br>
<a-switch defaultChecked >
<a-icon type="check" slot="checkedChildren"/>
<a-icon type="cross" slot="unCheckedChildren"/>
</a-switch>
</div>
</template>
```

View File

@ -0,0 +1,20 @@
## API
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| autoFocus | get focus when component mounted | boolean | false |
| checked | determine whether the `Switch` is checked | boolean | false |
| checkedChildren | content to be shown when the state is checked | string\|slot | |
| defaultChecked | to set the initial state | boolean | false |
| disabled | Disable switch | boolean | false |
| loading | loading state of switch | boolean | false |
| size | the size of the `Switch`, options: `default` `small` | string | default |
| unCheckedChildren | content to be shown when the state is unchecked | string\|slot | |
| onChange | a callback function, can be executed when the checked state is changing | Function(checked:Boolean) | |
## Methods
| Name | Description |
| ---- | ----------- |
| blur() | remove focus |
| focus() | get focus |

View File

@ -0,0 +1,75 @@
<script>
import PropTypes from '../_util/vue-types'
import { getOptionProps } from '../_util/props-util'
import VcSwitch from '../vc-switch'
export default {
name: 'vSwitch',
model: {
prop: 'checked',
event: 'change',
},
props: {
prefixCls: PropTypes.string.def('ant-switch'),
// size=default and size=large are the same
size: PropTypes.oneOf(['small', 'default', 'large']),
disabled: PropTypes.bool,
checkedChildren: PropTypes.any,
unCheckedChildren: PropTypes.any,
tabIndex: PropTypes.number,
checked: PropTypes.bool,
defaultChecked: PropTypes.bool,
autoFocus: PropTypes.bool,
loading: PropTypes.bool,
},
monted () {
this.$nextTick(() => {
this.refSwitchNode = this.$refs.refSwitchNode
})
},
methods: {
focus () {
this.refSwitchNode.focus()
},
blur () {
this.refSwitchNode.blur()
},
getChildren () {
return {
checkedChildren: this.$slots.checkedChildren || null,
unCheckedChildren: this.$slots.unCheckedChildren || null,
}
},
},
render () {
const { prefixCls, size, loading, ...restProps } = getOptionProps(this)
const classes = {
[`${prefixCls}-small`]: size === 'small',
[`${prefixCls}-loading`]: loading,
}
const switchProps = {
props: {
...restProps,
prefixCls,
},
on: this.$listeners,
class: classes,
ref: 'refSwitchNode',
}
const children = this.getChildren()
return (
<VcSwitch
{...switchProps}
>
{children.checkedChildren ? (
<template slot='checkedChildren'>{children.checkedChildren}</template>
) : null}
{children.unCheckedChildren ? (
<template slot='unCheckedChildren'>{children.unCheckedChildren}</template>
) : null}
</VcSwitch>
)
},
}
</script>

View File

@ -0,0 +1,20 @@
## API
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| autoFocus | 组件自动获取焦点 | boolean | false |
| checked | 指定当前是否选中 | boolean | false |
| checkedChildren | 选中时的内容 | string\|slot | |
| defaultChecked | 初始是否选中 | boolean | false |
| disabled | 是否禁用 | boolean | false |
| loading | 加载中的开关 | boolean | false |
| size | 开关大小,可选值:`default` `small` | string | default |
| unCheckedChildren | 非选中时的内容 | string\|slot | |
| onChange | 变化时回调函数 | Function(checked:Boolean) | |
## 方法
| 名称 | 描述 |
| --- | --- |
| blur() | 移除焦点 |
| focus() | 获取焦点 |

View File

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

View File

@ -0,0 +1,165 @@
@import "../../style/themes/default";
@import "../../style/mixins/index";
@switch-prefix-cls: ~"@{ant-prefix}-switch";
@switch-duration: .36s;
.@{switch-prefix-cls} {
.reset-component;
position: relative;
display: inline-block;
box-sizing: border-box;
height: @switch-height;
min-width: 44px;
line-height: @switch-height - 2px;
vertical-align: middle;
border-radius: 100px;
border: 1px solid transparent;
background-color: @disabled-color;
cursor: pointer;
transition: all @switch-duration;
user-select: none;
&-inner {
color: #fff;
font-size: @font-size-sm;
margin-left: 24px;
margin-right: 6px;
display: block;
}
&:before,
&:after {
position: absolute;
width: @switch-height - 4px;
height: @switch-height - 4px;
left: 1px;
top: 1px;
border-radius: 18px;
background-color: @component-background;
content: " ";
cursor: pointer;
transition: all @switch-duration @ease-in-out-circ;
}
&:after {
box-shadow: 0 2px 4px 0 rgba(0, 35, 11, .2);
}
&:active:before,
&:active:after {
width: 24px;
}
&:before {
content: "\e64d";
font-family: anticon;
animation: loadingCircle 1s infinite linear;
text-align: center;
background: transprent;
z-index: 1;
display: none;
font-size: 12px;
}
&-loading:before {
display: inline-block;
color: @text-color;
}
&-checked&-loading:before {
color: @switch-color;
}
&:focus {
box-shadow: 0 0 0 2px fade(@switch-color, 20%);
outline: 0;
}
&:focus:hover {
box-shadow: none;
}
&-small {
height: @switch-sm-height;
min-width: 28px;
line-height: @switch-sm-height - 2px;
.@{switch-prefix-cls}-inner {
margin-left: 18px;
margin-right: 3px;
font-size: @font-size-sm;
}
&:before,
&:after {
width: @switch-sm-height - 4px;
height: @switch-sm-height - 4px;
}
&:active:before,
&:active:after {
width: 16px;
}
}
&-small&-checked {
&:before,
&:after {
left: 100%;
margin-left: -12.5px;
}
.@{switch-prefix-cls}-inner {
margin-left: 3px;
margin-right: 18px;
}
}
&-small:active&-checked:before,
&-small:active&-checked:after {
margin-left: -16.5px;
}
&-small&-loading:before {
animation: AntSwitchSmallLoadingCircle 1s infinite linear;
font-weight: bold;
}
&-checked {
background-color: @switch-color;
.@{switch-prefix-cls}-inner {
margin-left: 6px;
margin-right: 24px;
}
&:before,
&:after {
left: 100%;
margin-left: -19px;
}
&:active:before,
&:active:after {
margin-left: -25px;
}
}
&-loading,
&-disabled {
pointer-events: none;
opacity: @switch-disabled-opacity;
}
}
@keyframes AntSwitchSmallLoadingCircle {
0% {
transform-origin: 50% 50%;
transform: rotate(0deg) scale(0.66667);
}
100% {
transform-origin: 50% 50%;
transform: rotate(360deg) scale(0.66667);
}
}

View File

@ -0,0 +1,15 @@
import PropTypes from '../_util/vue-types'
export const switchPropTypes = {
prefixCls: PropTypes.string,
disabled: PropTypes.bool.def(false),
checkedChildren: PropTypes.any,
unCheckedChildren: PropTypes.any,
// onChange: PropTypes.func,
// onMouseUp: PropTypes.func,
// onClick: PropTypes.func,
tabIndex: PropTypes.number,
checked: PropTypes.bool.def(false),
defaultChecked: PropTypes.bool.def(false),
autoFocus: PropTypes.bool.def(false),
}

View File

@ -0,0 +1,122 @@
<script>
import { switchPropTypes } from './PropTypes'
import BaseMixin from '../_util/BaseMixin'
import { hasProp, filterEmpty, getOptionProps } from '../_util/props-util'
// function noop () {
// }
export default {
name: 'vc-switch',
mixins: [BaseMixin],
model: {
prop: 'checked',
event: 'change',
},
props: {
...switchPropTypes,
prefixCls: switchPropTypes.prefixCls.def('rc-switch'),
checkedChildren: switchPropTypes.checkedChildren.def(null),
unCheckedChildren: switchPropTypes.unCheckedChildren.def(null),
defaultChecked: switchPropTypes.defaultChecked.def(''),
// onChange: switchPropTypes.onChange.def(noop),
// onClick: switchPropTypes.onClick.def(noop),
},
data () {
let checked = false
if (hasProp(this, 'checked')) {
checked = !!this.checked
} else {
checked = !!this.defaultChecked
}
return {
stateChecked: checked,
}
},
monted () {
this.$nextTick(() => {
const { autoFocus, disabled } = this
if (autoFocus && !disabled) {
this.focus()
}
this.refSwitchNode = this.$refs.refSwitchNode
})
},
watch: {
checked (val) {
this.stateChecked = val
},
},
methods: {
setChecked (checked) {
if (this.disabled) {
return
}
if (!hasProp(this, 'checked')) {
this.stateChecked = checked
}
this.$emit('change', checked)
},
toggle () {
const checked = !this.stateChecked
this.setChecked(checked)
this.$emit('click', checked)
},
handleKeyDown (e) {
if (e.keyCode === 37) { // Left
this.setChecked(false)
} else if (e.keyCode === 39) { // Right
this.setChecked(true)
} else if (e.keyCode === 32 || e.keyCode === 13) { // Space, Enter
this.toggle()
}
},
handleMouseUp (e) {
if (this.refSwitchNode) {
this.refSwitchNode.blur()
}
this.$emit('mouseUp', e)
},
focus () {
this.refSwitchNode.focus()
},
blur () {
this.refSwitchNode.blur()
},
getChildren (slotName) {
if (hasProp(this, slotName)) {
return this[slotName]
}
if (this.$slots && this.$slots[slotName]) {
return filterEmpty(this.$slots[slotName])
}
return null
},
},
render () {
const { prefixCls, disabled, tabIndex, ...restProps } = getOptionProps(this)
const checked = this.stateChecked
const switchTabIndex = disabled ? -1 : (tabIndex || 0)
const switchClassName = {
[prefixCls]: true,
[`${prefixCls}-checked`]: checked,
[`${prefixCls}-disabled`]: disabled,
}
const childrenType = checked ? 'checkedChildren' : 'unCheckedChildren'
return (
<span
{...restProps}
class={switchClassName}
tabIndex={switchTabIndex}
ref='refSwitchNode'
onKeydown={this.handleKeyDown}
onClick={this.toggle}
onMouseup={this.handleMouseUp}
>
<span class={`${prefixCls}-inner`}>
{this.getChildren(childrenType)}
</span>
</span>
)
},
}
</script>

View File

@ -0,0 +1,115 @@
@switchPrefixCls: rc-switch;
@duration: .3s;
.@{switchPrefixCls} {
position: relative;
display: inline-block;
box-sizing: border-box;
width: 44px;
height: 22px;
line-height: 20px;
vertical-align: middle;
border-radius: 20px 20px;
border: 1px solid #ccc;
background-color: #ccc;
cursor: pointer;
transition: all @duration cubic-bezier(0.35, 0, 0.25, 1);
&-inner {
color: #fff;
font-size: 12px;
position: absolute;
left: 24px;
}
&:after {
position: absolute;
width: 18px;
height: 18px;
left: 2px;
top: 1px;
border-radius: 50% 50%;
background-color: #fff;
content: " ";
cursor: pointer;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
transform: scale(1);
transition: left @duration cubic-bezier(0.35, 0, 0.25, 1);
animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1);
animation-duration: @duration;
animation-name: rcSwitchOff;
}
&:hover:after {
transform: scale(1.1);
animation-name: rcSwitchOn;
}
&:focus {
box-shadow: 0 0 0 2px tint(#2db7f5, 80%);
outline: none;
}
&-checked {
border: 1px solid #87d068;
background-color: #87d068;
.@{switchPrefixCls}-inner {
left: 6px;
}
&:after {
left: 22px;
}
}
&-disabled {
cursor: no-drop;
background: #ccc;
border-color: #ccc;
&:after {
background: #9e9e9e;
animation-name: none;
cursor: no-drop;
}
&:hover:after {
transform: scale(1);
animation-name: none;
}
}
&-label {
display: inline-block;
line-height: 20px;
font-size: 14px;
padding-left: 10px;
vertical-align: middle;
white-space: normal;
pointer-events: none;
user-select: text;
}
}
@keyframes rcSwitchOn {
0% {
transform: scale(1);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1.1);
}
}
@keyframes rcSwitchOff {
0% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}

View File

@ -0,0 +1,35 @@
<script>
import VcSwitch from '../index'
import '../assets/index.less'
export default {
data () {
return {
disabled: false,
}
},
methods: {
toggle () {
this.disabled = !this.disabled
},
onChange (value) {
console.log(`switch checked: ${value}`); // eslint-disable-line
},
},
render () {
return (
<div style='margin: 20px'>
<VcSwitch
onChange={this.onChange}
disabled={this.disabled}
checkedChildren={'开'}
unCheckedChildren={'关'}
/>
<div style='margin-top: 20px'>
<button onClick={this.toggle}>toggle disabled</button>
</div>
</div>
)
},
}
</script>

View File

@ -0,0 +1,3 @@
import Switch from './Switch'
export default Switch

View File

@ -47,12 +47,11 @@ Badge | done
Breadcrumb | done
Card | done
Collapse | done
LocaleProvider
Progress
Slider
Spin
Spin | done
Steps
Switch
Switch | done
Table
Timeline
Transfer

View File

@ -23,4 +23,5 @@ export { default as collapse } from 'antd/collapse/demo/index.vue'
export { default as notification } from 'antd/notification/demo/index.vue'
export { default as message } from 'antd/message/demo/index.vue'
export { default as spin } from 'antd/spin/demo/index.vue'
export { default as switch } from 'antd/switch/demo/index.vue'