Merge remote-tracking branch 'origin/master'

# Conflicts:
#	components/index.js
#	examples/index.js
pull/9/head
wanlei 2017-11-02 19:42:03 +08:00
commit 0548c36866
26 changed files with 1087 additions and 80 deletions

View File

@ -0,0 +1,10 @@
export default function isFlexSupported () {
if (typeof window !== 'undefined' && window.document && window.document.documentElement) {
const { documentElement } = window.document
return 'flex' in documentElement.style ||
'webkitFlex' in documentElement.style ||
'Flex' in documentElement.style ||
'msFlex' in documentElement.style
}
return false
}

View File

@ -14,10 +14,14 @@ export default {
default: 'ant-checkbox-group',
type: String,
},
value: {
defaultValue: {
default: () => [],
type: Array,
},
value: {
default: undefined,
type: Array,
},
options: {
default: () => [],
type: Array,
@ -26,9 +30,15 @@ export default {
model: {
prop: 'value',
},
data () {
const { value, defaultValue } = this
return {
stateValue: value || defaultValue,
}
},
computed: {
checkedStatus () {
return new Set(this.value)
return new Set(this.stateValue)
},
},
created () {
@ -40,17 +50,22 @@ export default {
return false
}
const target = event.target
const { value, checked } = target
const { value: targetValue, checked } = target
const { stateValue, value } = this
let newVal = []
if (checked) {
newVal = [...this.value, value]
newVal = [...stateValue, targetValue]
} else {
newVal = [...this.value]
const index = newVal.indexOf(value)
newVal = [...stateValue]
const index = newVal.indexOf(targetValue)
index >= 0 && newVal.splice(index, 1)
}
this.$emit('input', [...new Set(newVal)])
this.$emit('change', [...new Set(newVal)])
newVal = [...new Set(newVal)]
if (value === undefined) {
this.stateValue = newVal
}
this.$emit('input', newVal)
this.$emit('change', newVal)
},
setChildCheckbox (children = []) {
const { options, $slots, checkedStatus } = this
@ -75,6 +90,7 @@ export default {
},
watch: {
value (val) {
this.stateValue = val
this.setChildCheckbox(this.$slots.default)
},
},

View File

@ -2,7 +2,7 @@
<label :class="classes">
<span :class="checkboxClass">
<input :name="name" type="checkbox" :disabled="disabled"
:class="`${prefixCls}-input`" :checked="!!checked"
:class="`${prefixCls}-input`" :checked="stateChecked"
@change="handleChange"
/>
<span :class="`${prefixCls}-inner`" />
@ -20,7 +20,8 @@ export default {
default: 'ant-checkbox',
type: String,
},
checked: Boolean,
defaultChecked: Boolean,
checked: { type: Boolean, default: undefined },
disabled: Boolean,
isGroup: Boolean,
value: [String, Number, Boolean],
@ -31,6 +32,12 @@ export default {
model: {
prop: 'checked',
},
data () {
const { checked, defaultChecked } = this
return {
stateChecked: checked === undefined ? defaultChecked : checked,
}
},
computed: {
hasDefaultSlot () {
return !!this.$slots.default
@ -42,10 +49,10 @@ export default {
}
},
checkboxClass () {
const { prefixCls, indeterminate, checked, disabled } = this
const { prefixCls, indeterminate, stateChecked, disabled } = this
return {
[`${prefixCls}`]: true,
[`${prefixCls}-checked`]: checked,
[`${prefixCls}-checked`]: stateChecked,
[`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-indeterminate`]: indeterminate,
}
@ -55,13 +62,16 @@ export default {
},
methods: {
handleChange (event) {
const checked = event.target.checked
this.$emit('input', checked)
const { name, value } = this
const targetChecked = event.target.checked
this.$emit('input', targetChecked)
const { name, value, checked } = this
if (checked === undefined) {
this.stateChecked = targetChecked
}
const target = {
name,
value,
checked,
checked: targetChecked,
}
this.$emit('change', {
target,
@ -77,5 +87,10 @@ export default {
}
},
},
watch: {
checked (val) {
this.stateChecked = val
},
},
}
</script>

View File

@ -4,6 +4,7 @@ import './icon/style'
import './radio/style'
import './grid/style'
import './tooltip/style'
import './rate/style'
export { default as Button } from './button'
@ -15,4 +16,6 @@ export { default as Radio } from './radio'
export { default as Grid } from './grid'
export { default as Rate } from './rate'
export { default as ToolTip } from './tooltip'

View File

@ -1,6 +1,6 @@
<template>
<div :class="`${prefixCls}`">
<Radio v-for="item in options" :key="item.value" :checked="item.value === value"
<Radio v-for="item in options" :key="item.value" :checked="item.value === stateValue"
:value="item.value" :disabled="item.disabled" @change="handleChange">{{item.label}}</Radio>
<slot v-if="options.length === 0"></slot>
</div>
@ -14,7 +14,14 @@ export default {
default: 'ant-radio-group',
type: String,
},
value: [String, Number],
defaultValue: {
default: undefined,
type: [String, Number],
},
value: {
default: undefined,
type: [String, Number],
},
size: {
default: 'default',
validator (value) {
@ -27,8 +34,9 @@ export default {
},
},
data () {
const { value, defaultValue } = this
return {
curValue: this.value,
stateValue: value || defaultValue,
}
},
model: {
@ -46,19 +54,22 @@ export default {
return false
}
const target = event.target
const { value } = target
this.$emit('input', value)
this.$emit('change', value)
const { value: targetValue } = target
if (this.value === undefined) {
this.stateValue = targetValue
}
this.$emit('input', targetValue)
this.$emit('change', targetValue)
},
setChildRadio (children = []) {
const { options, $slots, value } = this
const { options, $slots, stateValue } = this
if (options.length === 0 && $slots.default) {
children.forEach(({ componentOptions = {}, children: newChildren }) => {
const { Ctor, propsData } = componentOptions
if (Ctor && Ctor.options.name === 'Radio') {
propsData.isGroup = true
propsData.onGroupChange = this.handleChange
propsData.checked = propsData.value === value
propsData.checked = propsData.value === stateValue
} else {
this.setChildRadio(newChildren)
}
@ -71,6 +82,7 @@ export default {
},
watch: {
value (val) {
this.stateValue = val
this.setChildRadio(this.$slots.default)
},
},

View File

@ -2,7 +2,7 @@
<label :class="classes">
<span :class="checkboxClass">
<input :name="name" type="radio" :disabled="disabled"
:class="`${prefixCls}-input`" :checked="!!checked"
:class="`${prefixCls}-input`" :checked="stateChecked"
@change="handleChange"
/>
<span :class="`${prefixCls}-inner`" />
@ -20,7 +20,8 @@ export default {
default: 'ant-radio',
type: String,
},
checked: Boolean,
defaultChecked: Boolean,
checked: { type: Boolean, default: undefined },
disabled: Boolean,
isGroup: Boolean,
value: [String, Number, Boolean],
@ -30,35 +31,45 @@ export default {
model: {
prop: 'checked',
},
data () {
const { checked, defaultChecked } = this
return {
stateChecked: checked === undefined ? defaultChecked : checked,
}
},
computed: {
hasDefaultSlot () {
return !!this.$slots.default
},
classes () {
const { prefixCls, disabled, checked } = this
const { prefixCls, disabled, stateChecked } = this
return {
[`${prefixCls}-wrapper`]: true,
[`${prefixCls}-wrapper-checked`]: checked,
[`${prefixCls}-wrapper-checked`]: stateChecked,
[`${prefixCls}-wrapper-disabled`]: disabled,
}
},
checkboxClass () {
const { prefixCls, disabled, checked } = this
const { prefixCls, disabled, stateChecked } = this
return {
[`${prefixCls}`]: true,
[`${prefixCls}-checked`]: checked,
[`${prefixCls}-checked`]: stateChecked,
[`${prefixCls}-disabled`]: disabled,
}
},
},
methods: {
handleChange (event) {
const { name, value } = this
this.$emit('input', true)
const targetChecked = event.target.checked
const { name, value, checked } = this
if (checked === undefined) {
this.stateChecked = targetChecked
}
this.$emit('input', targetChecked)
const target = {
name,
value,
checked: true,
checked: targetChecked,
}
this.$emit('change', {
target,
@ -74,5 +85,10 @@ export default {
}
},
},
watch: {
checked (val) {
this.stateChecked = val
},
},
}
</script>

View File

@ -1,41 +0,0 @@
<template>
<div :class="`${prefixCls}`">
<Radio v-for="item in options" :key="item.value" :checked="item.value === value"
:value="item.value" :disabled="item.disabled" @change="handleChange">{{item.label}}</Radio>
<slot v-if="options.length === 0"></slot>
</div>
</template>
<script>
import Radio from './Radio.vue'
export default {
name: 'Radio',
props: {
prefixCls: {
default: 'ant-radio-button',
type: String,
},
value: [String, Number],
size: {
default: 'default',
validator (value) {
return ['large', 'default', 'small'].includes(value)
},
},
options: {
default: () => [],
type: Array,
},
},
data () {
return {
curValue: this.value,
}
},
model: {
prop: 'value',
},
components: {
Radio,
},
}
</script>

134
components/rate/Rate.vue Normal file
View File

@ -0,0 +1,134 @@
<template>
<ul
:class="classes"
@mouseleave="onMouseLeave">
<template v-for="i in count">
<Star
ref="stars"
:index="i"
:disabled="disabled"
:prefix-cls="`${prefixCls}-star`"
:allowHalf="allowHalf"
:value="currentValue"
@onClick="onClick"
@onHover="onHover"
:key="i">
<template slot-scope="props">
<slot>
<span>{{character}}</span>
</slot>
</template>
</Star>
</template>
</ul>
</template>
<script>
import Star from './Star.vue'
import Icon from '../icon/index'
import { getOffsetLeft } from '../util/util'
export default {
name: 'Rate',
props: {
prefixCls: {
type: String,
default: 'ant-rate',
},
count: {
type: Number,
default: 5,
},
value: Number,
defaultValue: {
type: Number,
default: 0,
},
onChange: {
type: Function,
default: () => {},
},
onHoverChange: {
type: Function,
default: () => {},
},
allowHalf: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
character: {
type: String,
default: '★',
},
},
data () {
const { value, defaultValue } = this
const reValue = value === undefined ? defaultValue : value
return {
currentValue: reValue,
stateValue: reValue,
}
},
computed: {
classes () {
const { prefixCls, disabled } = this
return {
[`${prefixCls}`]: true,
[`${prefixCls}-disabled`]: disabled,
}
},
},
methods: {
onClick (event, index) {
const clValue = this.getStarValue(index, event.pageX)
this.stateValue = clValue
this.onMouseLeave()
this.$emit('input', clValue)
this.onChange(clValue)
},
onHover (event, index) {
this.currentValue = this.getStarValue(index, event.pageX)
this.changeValue(this.currentValue)
this.onHoverChange(this.currentValue)
},
getStarDOM (index) {
return this.$refs.stars[index].$el
},
getStarValue (index, x) {
let value = index
if (this.allowHalf) {
const leftEdge = getOffsetLeft(this.getStarDOM(0))
const width = getOffsetLeft(this.getStarDOM(1)) - leftEdge
if ((x - leftEdge - width * (index - 1)) < width / 2) {
value -= 0.5
}
}
return value
},
onMouseLeave () {
this.currentValue = undefined
this.changeValue()
this.onHoverChange()
},
changeValue (val) {
if (val === undefined) {
this.currentValue = this.stateValue
}
},
},
watch: {
value (val = 0) {
this.currentValue = this.stateValue = val
this.$emit('input', val)
},
},
components: {
Star,
Icon,
},
}
</script>

43
components/rate/Star.vue Normal file
View File

@ -0,0 +1,43 @@
<template>
<li
:class="getClassName()"
@click="onClick"
@mousemove="onHover">
<div :class="`${this.prefixCls}-first`"><slot></slot></div>
<div :class="`${this.prefixCls}-second`"><slot></slot></div>
</li>
</template>
<script>
export default {
name: 'Star',
props: {
index: Number,
disabled: Boolean,
prefixCls: String,
allowHalf: Boolean,
value: Number,
},
data () {
return {
}
},
methods: {
getClassName () {
const { prefixCls, index, value, allowHalf } = this
const starValue = index
if (allowHalf && value + 0.5 === starValue) {
return `${prefixCls} ${prefixCls}-half ${prefixCls}-active`
}
return starValue <= value ? `${prefixCls} ${prefixCls}-full` : `${prefixCls} ${prefixCls}-zero`
},
onClick (e) {
if (this.disabled) return
this.$emit('onClick', e, this.index)
},
onHover (e) {
if (this.disabled) return
this.$emit('onHover', e, this.index)
},
},
}
</script>

3
components/rate/index.js Normal file
View File

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

View File

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

View File

@ -0,0 +1,73 @@
@import "../../style/themes/default";
@import "../../style/mixins/index";
@rate-prefix-cls: ~"@{ant-prefix}-rate";
.@{rate-prefix-cls} {
margin: 0;
padding: 0;
list-style: none;
font-size: 20px;
display: inline-block;
vertical-align: middle;
&-disabled &-star {
cursor: not-allowed;
&:hover {
transform: scale(1);
}
}
&-star {
margin: 0;
padding: 0;
display: inline-block;
margin-right: 8px;
position: relative;
transition: all .3s;
color: @rate-star-bg;
cursor: pointer;
&-first,
&-second {
user-select: none;
transition: all .3s;
}
&:hover {
transform: scale(1.1);
}
&-first {
position: absolute;
left: 0;
top: 0;
width: 50%;
height: 100%;
overflow: hidden;
opacity: 0;
}
&-half &-first,
&-half &-second {
opacity: 1;
}
&-half &-first,
&-full &-second {
color: @rate-star-color;
}
&-half:hover &-first,
&-full:hover &-second {
color: tint(@rate-star-color, 20%);
}
}
&-text {
margin-left: 8px;
vertical-align: middle;
display: inline-block;
font-size: @font-size-base;
}
}

View File

View File

0
components/tabs/Tabs.vue Normal file
View File

6
components/tabs/index.js Normal file
View File

@ -0,0 +1,6 @@
import Tabs from './Tabs'
import TabPane from './TabPane'
import TabContent from './TabContent'
export default Tabs
export { TabPane, TabContent }

View File

@ -0,0 +1,142 @@
@import "../../style/themes/default";
@import "../../style/mixins/index";
@tab-prefix-cls: ~"@{ant-prefix}-tabs";
// card style
.@{tab-prefix-cls} {
&&-card > &-bar &-nav-container {
height: 32px;
}
&&-card > &-bar &-ink-bar {
visibility: hidden;
}
&&-card > &-bar &-tab {
margin: 0;
border: @border-width-base @border-style-base @border-color-base;
border-bottom: 0;
border-radius: @border-radius-base @border-radius-base 0 0;
transition: all 0.3s @ease-in-out;
background: @tabs-card-head-background;
margin-right: 2px;
}
&&-card > &-bar &-tab {
padding: 5px 16px 4px;
transition: all 0.3s @ease-in-out;
}
&&-card > &-bar &-tab-active {
background: @component-background;
border-color: @border-color-base;
color: @primary-color;
padding-bottom: 5px;
}
&&-card > &-bar &-tab-inactive {
padding: 0;
}
&&-card > &-bar &-nav-wrap {
margin-bottom: 0;
}
&&-card > &-bar &-tab .@{iconfont-css-prefix}-close {
color: @text-color-secondary;
transition: all .3s;
.iconfont-size-under-12px(10px);
margin-right: 0;
opacity: 0;
position: absolute;
right: 2px;
top: 50%;
margin-top: -5px;
overflow: hidden;
text-align: center;
border-radius: 2px;
width: 14px;
height: 14px;
line-height: 1;
&:hover {
color: @heading-color;
}
}
&&-card &-content > &-tabpane,
&&-editable-card &-content > &-tabpane {
transition: none !important;
&-inactive {
overflow: hidden;
}
}
&&-card > &-bar &-tab:hover .@{iconfont-css-prefix}-close {
opacity: 1;
}
&-extra-content {
line-height: 32px;
.@{tab-prefix-cls}-new-tab {
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
cursor: pointer;
border-radius: @border-radius-base;
border: @border-width-base @border-style-base @border-color-base;
font-size: @font-size-base;
.iconfont-size-under-12px(10px);
color: @text-color-secondary;
transition: all .3s;
&:hover {
color: @primary-color;
border-color: @primary-color;
}
}
}
// https://github.com/ant-design/ant-design/issues/4669
&-vertical&-card > .@{tab-prefix-cls}-bar {
.@{tab-prefix-cls}-nav-container {
height: auto;
}
.@{tab-prefix-cls}-tab {
border-bottom: @border-width-base @border-style-base @border-color-base;
margin-bottom: 8px;
&-active {
padding-bottom: 4px;
}
&:last-child {
margin-bottom: 8px;
}
}
.@{tab-prefix-cls}-new-tab {
width: 90%;
}
}
&-vertical&-card&-left > .@{tab-prefix-cls}-bar {
.@{tab-prefix-cls}-nav-wrap {
margin-right: 0;
}
.@{tab-prefix-cls}-tab {
border-right: 0;
border-radius: @border-radius-base 0 0 @border-radius-base;
margin-right: 1px;
&-active {
margin-right: -1px;
padding-right: 18px;
}
}
}
&-vertical&-card&-right > .@{tab-prefix-cls}-bar {
.@{tab-prefix-cls}-nav-wrap {
margin-left: 0;
}
.@{tab-prefix-cls}-tab {
border-left: 0;
border-radius: 0 @border-radius-base @border-radius-base 0;
margin-left: 1px;
&-active {
margin-left: -1px;
padding-left: 18px;
}
}
}
}

View File

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

View File

@ -0,0 +1,395 @@
@import "../../style/themes/default";
@import "../../style/mixins/index";
@tab-prefix-cls: ~"@{ant-prefix}-tabs";
@import "./card-style";
.@{tab-prefix-cls} {
box-sizing: border-box;
position: relative;
overflow: hidden;
.clearfix;
color: @text-color;
&-ink-bar {
z-index: 1;
position: absolute;
left: 0;
bottom: 1px;
box-sizing: border-box;
height: 2px;
background-color: @primary-color;
transform-origin: 0 0;
}
&-bar {
border-bottom: @border-width-base @border-style-base @border-color-base;
margin-bottom: 16px;
outline: none;
transition: padding .3s @ease-in-out;
}
&-nav-container {
overflow: hidden;
font-size: @tabs-title-font-size;
line-height: @line-height-base;
box-sizing: border-box;
position: relative;
white-space: nowrap;
margin-bottom: -1px;
transition: padding .3s @ease-in-out;
.clearfix;
&-scrolling {
padding-left: 32px;
padding-right: 32px;
}
}
&-tab-prev,
&-tab-next {
user-select: none;
z-index: 2;
width: 0;
height: 100%;
line-height: 32px;
cursor: pointer;
border: 0;
background-color: transparent;
position: absolute;
text-align: center;
color: @text-color-secondary;
transition: width .3s @ease-in-out, opacity .3s @ease-in-out, color .3s @ease-in-out;
opacity: 0;
pointer-events: none;
&.@{tab-prefix-cls}-tab-arrow-show {
opacity: 1;
width: 32px;
height: 100%;
pointer-events: auto;
}
&:hover {
color: @text-color;
}
&-icon {
font-style: normal;
font-weight: bold;
font-variant: normal;
line-height: inherit;
vertical-align: baseline;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
text-transform: none;
&:before {
display: block;
font-family: "anticon" !important;
.iconfont-size-under-12px(10px);
}
}
}
&-tab-btn-disabled {
cursor: not-allowed;
&,
&:hover {
color: @disabled-color;
}
}
&-tab-next {
right: 2px;
&-icon:before {
content: "\e61f";
}
}
&-tab-prev {
left: 0;
&-icon:before {
content: "\e620";
}
:root & {
filter: none;
}
}
&-nav-wrap {
overflow: hidden;
margin-bottom: -1px;
}
&-nav-scroll {
overflow: hidden;
white-space: nowrap;
}
&-nav {
box-sizing: border-box;
padding-left: 0;
transition: transform 0.3s @ease-in-out;
position: relative;
margin: 0;
list-style: none;
display: inline-block;
&:before,
&:after {
display: table;
content: " ";
}
&:after {
clear: both;
}
.@{tab-prefix-cls}-tab-disabled {
pointer-events: none;
cursor: default;
color: @disabled-color;
}
.@{tab-prefix-cls}-tab {
display: inline-block;
height: 100%;
margin-right: 24px;
box-sizing: border-box;
position: relative;
&:last-child {
margin-right: 0;
}
padding: 8px 20px;
transition: color 0.3s @ease-in-out;
cursor: pointer;
text-decoration: none;
&:hover {
color: @primary-5;
}
&:active {
color: @primary-7;
}
.@{iconfont-css-prefix} {
width: 14px;
height: 14px;
margin-right: 8px;
}
}
.@{tab-prefix-cls}-tab-active {
color: @primary-color;
}
}
&-mini &-nav-container {
font-size: @font-size-base;
}
&-mini &-tab {
margin-right: 0;
padding: 8px 16px;
}
&:not(&-vertical) {
> .@{tab-prefix-cls}-content {
width: 100%;
> .@{tab-prefix-cls}-tabpane {
flex-shrink: 0;
width: 100%;
transition: opacity .45s;
opacity: 1;
}
> .@{tab-prefix-cls}-tabpane-inactive {
opacity: 0;
height: 0;
padding: 0 !important;
pointer-events: none;
}
}
> .@{tab-prefix-cls}-content-animated {
display: flex;
flex-direction: row;
will-change: margin-left;
transition: margin-left 0.3s @ease-in-out;
}
}
&-vertical {
> .@{tab-prefix-cls}-bar {
border-bottom: 0;
height: 100%;
&-tab-prev, &-tab-next {
width: 32px;
height: 0;
transition: height .3s @ease-in-out, opacity .3s @ease-in-out, color .3s @ease-in-out;
}
&-tab-prev.@{tab-prefix-cls}-tab-arrow-show,
&-tab-next.@{tab-prefix-cls}-tab-arrow-show {
width: 100%;
height: 32px;
}
.@{tab-prefix-cls}-tab {
float: none;
margin-right: 0;
margin-bottom: 16px;
display: block;
padding: 8px 24px;
&:last-child {
margin-bottom: 0;
}
}
.@{tab-prefix-cls}-extra-content {
text-align: center;
}
.@{tab-prefix-cls}-nav-scroll {
width: auto;
}
.@{tab-prefix-cls}-nav-container,
.@{tab-prefix-cls}-nav-wrap {
height: 100%;
}
.@{tab-prefix-cls}-nav-container {
margin-bottom: 0;
&.@{tab-prefix-cls}-nav-container-scrolling {
padding: 32px 0;
}
}
.@{tab-prefix-cls}-nav-wrap {
margin-bottom: 0;
}
.@{tab-prefix-cls}-nav {
width: 100%;
}
.@{tab-prefix-cls}-ink-bar {
width: 2px;
left: auto;
height: auto;
top: 0;
}
}
> .@{tab-prefix-cls}-content {
overflow: hidden;
width: auto;
margin-top: 0 !important;
}
> .@{tab-prefix-cls}-bar {
.@{tab-prefix-cls}-tab-next {
width: 100%;
bottom: 0;
height: 32px;
&-icon:before {
content: "\e61d";
}
}
.@{tab-prefix-cls}-tab-prev {
top: 0;
width: 100%;
height: 32px;
&-icon:before {
content: "\e61e";
}
}
}
}
&-vertical&-left {
> .@{tab-prefix-cls}-bar {
float: left;
border-right: @border-width-base @border-style-base @border-color-split;
margin-right: -1px;
margin-bottom: 0;
.@{tab-prefix-cls}-tab {
text-align: right;
}
.@{tab-prefix-cls}-nav-container {
margin-right: -1px;
}
.@{tab-prefix-cls}-nav-wrap {
margin-right: -1px;
}
.@{tab-prefix-cls}-ink-bar {
right: 1px;
}
}
> .@{tab-prefix-cls}-content {
padding-left: 24px;
border-left: @border-width-base @border-style-base @border-color-split;
}
}
&-vertical&-right {
> .@{tab-prefix-cls}-bar {
float: right;
border-left: @border-width-base @border-style-base @border-color-split;
margin-left: -1px;
margin-bottom: 0;
.@{tab-prefix-cls}-nav-container {
margin-left: -1px;
}
.@{tab-prefix-cls}-nav-wrap {
margin-left: -1px;
}
.@{tab-prefix-cls}-ink-bar {
left: 1px;
}
}
> .@{tab-prefix-cls}-content {
padding-right: 24px;
border-right: @border-width-base @border-style-base @border-color-split;
}
}
&-bottom > &-bar {
margin-bottom: 0;
margin-top: 16px;
}
}
.@{tab-prefix-cls}-top .@{tab-prefix-cls}-ink-bar-animated,
.@{tab-prefix-cls}-bottom .@{tab-prefix-cls}-ink-bar-animated {
transition: transform .3s @ease-in-out, width .3s @ease-in-out;
}
.@{tab-prefix-cls}-left .@{tab-prefix-cls}-ink-bar-animated,
.@{tab-prefix-cls}-right .@{tab-prefix-cls}-ink-bar-animated {
transition: transform .3s @ease-in-out, height .3s @ease-in-out;
}
.no-flex,
.@{tab-prefix-cls}-no-animation,
.@{tab-prefix-cls}-vertical {
> .@{tab-prefix-cls}-content {
&-animated {
transform: none !important;
margin-left: 0 !important;
}
> .@{tab-prefix-cls}-tabpane-inactive {
display: none;
}
}
}

59
components/tabs/utils.js Normal file
View File

@ -0,0 +1,59 @@
export function setTransform (style, v) {
style.transform = v
style.webkitTransform = v
style.mozTransform = v
}
export function isTransformSupported (style) {
return 'transform' in style ||
'webkitTransform' in style ||
'MozTransform' in style
}
export function setTransition (style, v) {
style.transition = v
style.webkitTransition = v
style.MozTransition = v
}
export function getTransformPropValue (v) {
return {
transform: v,
WebkitTransform: v,
MozTransform: v,
}
}
export function isVertical (tabBarPosition) {
return tabBarPosition === 'left' || tabBarPosition === 'right'
}
export function getTransformByIndex (index, tabBarPosition) {
const translate = isVertical(tabBarPosition) ? 'translateY' : 'translateX'
return `${translate}(${-index * 100}%) translateZ(0)`
}
export function getMarginStyle (index, tabBarPosition) {
const marginDirection = isVertical(tabBarPosition) ? 'marginTop' : 'marginLeft'
return {
[marginDirection]: `${-index * 100}%`,
}
}
export function getStyle (el, property) {
return +window.getComputedStyle(el).getPropertyValue(property).replace('px', '')
}
export function setPxStyle (el, value, vertical) {
value = vertical ? `0px, ${value}px, 0px` : `${value}px, 0px, 0px`
setTransform(el.style, `translate3d(${value})`)
}
export function getDataAttr (props) {
return Object.keys(props).reduce((prev, key) => {
if (key.substr(0, 5) === 'aria-' || key.substr(0, 5) === 'data-' || key === 'role') {
prev[key] = props[key]
}
return prev
}, {})
}

40
components/util/util.js Normal file
View File

@ -0,0 +1,40 @@
function getScroll(w, top) {
let ret = top ? w.pageYOffset : w.pageXOffset;
const method = top ? 'scrollTop' : 'scrollLeft';
if (typeof ret !== 'number') {
const d = w.document;
// ie6,7,8 standard mode
ret = d.documentElement[method];
if (typeof ret !== 'number') {
// quirks mode
ret = d.body[method];
}
}
return ret;
}
function getClientPosition(elem) {
let box;
let x;
let y;
const doc = elem.ownerDocument;
const body = doc.body;
const docElem = doc && doc.documentElement;
box = elem.getBoundingClientRect();
x = box.left;
y = box.top;
x -= docElem.clientLeft || body.clientLeft || 0;
y -= docElem.clientTop || body.clientTop || 0;
return {
left: x,
top: y,
};
}
export const getOffsetLeft = (el) => {
const pos = getClientPosition(el);
const doc = el.ownerDocument;
const w = doc.defaultView || doc.parentWindow;
pos.left += getScroll(w);
return pos.left;
}

View File

@ -1,8 +1,9 @@
<template>
<div>
<Checkbox :checked="true" @change="change" name="test" value="123" />
<Checkbox :defaultChecked="true" @change="change" value="1">1</Checkbox>
<Checkbox v-model="checked" @change="change" value="2">2</Checkbox>
<Checkbox @change="change" v-model="checked" name="test" value="123">Checkbox</Checkbox>
<Checkbox :disabled="true" @change="change" v-model="checked" name="test2" value="222">Checkbox</Checkbox>
<Checkbox @change="change" v-model="checked" name="test2" value="222">Checkbox</Checkbox>
<CheckboxGroup v-model="value" @change="change">
<AntButton @click="handleClick">
@ -18,7 +19,7 @@
<Checkbox name="test3" value="3" @change="change">Checkbox3</Checkbox>
<Checkbox v-if="showMore" name="test4" value="4">Checkbox4</Checkbox>
</CheckboxGroup>
<CheckboxGroup :options="options" v-model="value1" @change="change"></CheckboxGroup>
<CheckboxGroup :options="options" :defaultValue="['Apple']" @change="change"></CheckboxGroup>
</div>
</template>
<script>

View File

@ -5,8 +5,9 @@ import Radio from './radio.vue'
import Grid from './grid.vue'
import ToolTip from './tooltip.vue'
// import Dialog from './dialog.vue'
import Rate from './rate.vue'
import './index.less'
window.root = new Vue({
new Vue({
el: '#app',
template: `
<div>
@ -15,6 +16,7 @@ window.root = new Vue({
<Checkbox />
<AntButton />
<Radio />
<Rate />
</div>
`,
components: {
@ -24,5 +26,6 @@ window.root = new Vue({
Grid,
Radio,
ToolTip,
Rate,
},
})

View File

@ -0,0 +1,3 @@
.icon-test{
font-size: 35px;
}

View File

@ -1,6 +1,6 @@
<template>
<div>
<Radio v-model="checked" @change="change" name="test" value="123">Radio</Radio>
<Radio @change="change" :defaultChecked="true" name="test" value="123">Radio</Radio>
<Radio :checked="false" @change="change" name="test2" value="222">Radio</Radio>
<RadioGroup v-model="value" @change="change">
@ -14,7 +14,7 @@
</RadioGroup>
<RadioGroup :options="options" v-model="value1" @change="change"></RadioGroup>
<div>
<RadioGroup v-model="value2" size="large">
<RadioGroup :defaultValue="'a'" size="large">
<RadioButton value="a">Hangzhou</RadioButton>
<RadioButton value="b">Shanghai</RadioButton>
<RadioButton value="c">Beijing</RadioButton>

70
examples/rate.vue Normal file
View File

@ -0,0 +1,70 @@
<template>
<div>
基本
<Rate class="custom"></Rate>
</br>
半星
<Rate :allowHalf="allowHalf"></Rate>
</br>
默认3颗星
<Rate v-model="initValue"></Rate>
<AntButton type="primary" @click="changeValue"></AntButton>
<AntButton type="primary" @click="getValue"></AntButton>
</br>
只读
<Rate :value="initValue" :disabled="disabled"></Rate>
</br>
回调函数
<Rate
:onChange="onChange"
:onHoverChange="onHoverChange"></Rate>
<span v-if="hoverValue">{{hoverValue}}stars</span>
<span v-if="rValue">{{rValue}}stars</span>
<br/>
<Rate
:allowHalf="allowHalf"
:onHoverChange="onHoverChangeAH"></Rate>
<span v-if="hoverValueAH">{{hoverValueAH}}stars</span>
</br>
自定义
<Rate :value="initValue" :character="character"></Rate>
</div>
</template>
<script>
import { Rate, Icon, Button } from '../components/index'
export default {
data () {
return {
allowHalf: true,
initValue: 3,
disabled: true,
hoverValue: undefined,
rValue: undefined,
hoverValueAH: undefined,
character: '好',
}
},
methods: {
onHoverChange (val) {
this.hoverValue = val
},
onChange (val) {
this.rValue = val
},
onHoverChangeAH (val) {
this.hoverValueAH = val
},
changeValue () {
this.initValue = undefined
},
getValue () {
console.log(this.initValue)
},
},
components: {
Rate,
Icon,
AntButton: Button,
},
}
</script>