Merge remote-tracking branch 'upstream/2.0' into 2.0

This commit is contained in:
TabEnter 2017-08-16 15:44:48 +08:00
commit f9508bf178
42 changed files with 960 additions and 240 deletions

View file

@ -54,6 +54,8 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; }
<li><router-link to="/modal">Modal</router-link></li>
<li><router-link to="/message">Message</router-link></li>
<li><router-link to="/notice">Notice</router-link></li>
<li><router-link to="/avatar">Avatar</router-link></li>
<li><router-link to="/color-picker">ColorPicker</router-link></li>
</ul>
</nav>
<router-view></router-view>

View file

@ -180,6 +180,14 @@ const router = new VueRouter({
{
path: '/notice',
component: require('./routers/notice.vue')
},
{
path: '/avatar',
component: require('./routers/avatar.vue')
},
{
path: '/color-picker',
component: require('./routers/color-picker.vue')
}
]
});

View file

@ -0,0 +1,47 @@
<template>
<div>
<Avatar icon="person" size="large" style="background-color: #fde3cf;color: #f56a00"></Avatar>
<Avatar icon="person"></Avatar>
<Avatar icon="person" size="small"></Avatar>
<Avatar icon="person" size="large" shape="square"></Avatar>
<Avatar icon="person" shape="square"></Avatar>
<Avatar icon="person" size="small" shape="square"></Avatar>
<br><br>
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" size="large"></Avatar>
<Avatar src="https://avatars2.githubusercontent.com/u/5370542?v=4&s=460"></Avatar>
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" size="small"></Avatar>
<Avatar src="https://avatars2.githubusercontent.com/u/5370542?v=4&s=460" size="large" shape="square"></Avatar>
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" shape="square"></Avatar>
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" size="small" shape="square"></Avatar>
<br><br>
<Avatar size="large">Leo</Avatar>
<Avatar size="large">A</Avatar>
<Avatar size="default">A</Avatar>
<Avatar size="small">A</Avatar>
<Avatar size="large">Tomserm</Avatar>
<Avatar size="large">{{ name }}</Avatar>
{{ name }}
<br><br>
<Badge dot>
<Avatar icon="person" shape="square"></Avatar>
</Badge>
<Badge :count="3">
<Avatar icon="person" shape="square"></Avatar>
</Badge>
<Button @click="change">change</Button>
</div>
</template>
<script>
export default {
data () {
return {
name: 'Aresn'
}
},
methods: {
change () {
this.name = 'Tomserm'
}
}
}
</script>

View file

@ -1,67 +1,61 @@
<template>
<div style="width: 400px;">
<Row>
<i-col span="12">
<Cascader transfer v-model="value3" :data="data" filterable></Cascader>
</i-col>
<i-col span="12">
<Cascader v-model="value3" :data="data" filterable></Cascader>
</i-col>
</Row>
</div>
<Cascader :data="data4" :load-data="loadData"></Cascader>
</template>
<script>
export default {
data () {
return {
data: [{
value: 'beijing',
label: '北京',
children: [
{
value: 'gugong',
label: '故宫'
},
{
value: 'tiantan',
label: '天坛'
},
{
value: 'wangfujing',
label: '王府井'
}
]
}, {
value: 'jiangsu',
label: '江苏',
children: [
{
value: 'nanjing',
label: '南京',
children: [
{
value: 'fuzimiao',
label: '夫子庙',
}
]
},
{
value: 'suzhou',
label: '苏州',
children: [
{
value: 'zhuozhengyuan',
label: '拙政园',
},
{
value: 'shizilin',
label: '狮子林',
}
]
}
],
}],
value3: []
data4: [
{
value: 'beijing',
label: '北京',
children: [],
loading: false
},
{
value: 'hangzhou',
label: '杭州',
children: [],
loading:false
}
]
}
},
methods: {
loadData (item, callback) {
item.loading = true;
setTimeout(() => {
console.log(1)
if (item.value === 'beijing') {
item.children = [
// {
// value: 'talkingdata',
// label: 'TalkingData'
// },
// {
// value: 'baidu',
// label: ''
// },
// {
// value: 'sina',
// label: ''
// }
];
} else if (item.value === 'hangzhou') {
item.children = [
{
value: 'ali',
label: '阿里巴巴'
},
{
value: '163',
label: '网易'
}
];
}
item.loading = false;
callback();
}, 1000);
}
}
}

View file

@ -1,7 +1,15 @@
<template>
<div>
<div>
<Checkbox true-value="true" false-value="false" v-model="testValue1">test string</Checkbox>
{{ testValue1 }}
</div>
<div>
<Checkbox :true-value="0" :false-value="1" v-model="testValue2">test number</Checkbox>
{{ testValue2 }}
</div>
<Checkbox-group v-model="fruit">
<Checkbox v-for="item in tags" :label="item.label" :key="item"></Checkbox>
<Checkbox v-for="item in tags" :label="item.label" :key="item.label" true-value="true"></Checkbox>
</Checkbox-group>
<div>{{ fruit }}</div>
</div>
@ -12,7 +20,9 @@
return {
social: ['facebook', 'github'],
fruit: ['苹果'],
tags: []
tags: [],
testValue1: null,
testValue2: null
}
},
mounted () {

View file

@ -0,0 +1,21 @@
<template>
<div style="margin: 100px;">
<!--<Input placeholder="请输入..." size="large" style="width: 50px;"></Input>-->
<color-picker placement="bottom-start" size="large"></color-picker>
<!--<Date-picker type="date" placeholder="选择日期" size="large" style="width: 200px"></Date-picker>-->
<color-picker placement="bottom-start" size="default"></color-picker>
<!--<Date-picker type="date" placeholder="选择日期" style="width: 200px"></Date-picker>-->
<color-picker placement="bottom-start" size="small"></color-picker>
<!--<Date-picker type="date" placeholder="选择日期" size="small" style="width: 200px"></Date-picker>-->
</div>
</template>
<script>
export default {
props: {},
data () {
return {};
},
computed: {},
methods: {}
};
</script>

View file

@ -2,12 +2,16 @@
<div>
<Date-picker transfer type="daterange" placeholder="选择日期" style="width: 200px"></Date-picker>
<Date-picker type="daterange" placeholder="选择日期" style="width: 200px"></Date-picker>
<Date-picker type="daterange" placeholder="选择日期" style="width: 200px"></Date-picker>
<Date-picker type="datetimerange" placeholder="选择日期" style="width: 200px" @on-change="changeDate"></Date-picker>
</div>
</template>
<script>
export default {
methods: {
changeDate(date){
console.log(date);
}
}
}
</script>

View file

@ -1,6 +1,7 @@
<template>
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
<Form-item label="姓名" prop="name">
<Form-item prop="name">
<span slot="label"><Icon type="ionic"></Icon></span>
<Input v-model="formValidate.name" placeholder="请输入姓名"></Input>
</Form-item>
<Form-item label="邮箱" prop="mail">

View file

@ -1,8 +1,26 @@
<template>
<Page :total="100" show-sizer show-elevator show-total></Page>
<div>
<Page :total="total" show-sizer show-elevator show-total :current.sync="current"></Page>
{{ current }}
<Button type="primary" @click="subject">- 1</Button>
<Button type="primary" @click="change">Change</Button>
</div>
</template>
<script>
export default {
data () {
return {
current: 1,
total: 21
}
},
methods: {
subject() {
this.total -= 1;
},
change() {
this.current = 1;
}
}
}
</script>

View file

@ -1,21 +1,24 @@
<template>
<div>
<Poptip trigger="hover" title="提示标题" content="提示内容">
<Button>hover 激活</Button>
</Poptip>
<Poptip transfer title="提示标题" content="提示内容">
<Button>click 激活</Button>
</Poptip>
<Poptip trigger="focus" title="提示标题" content="提示内容">
<Button>focus 激活</Button>
</Poptip>
<Poptip trigger="focus" title="提示标题" content="提示内容">
<i-input placeholder="输入框的 focus"></i-input>
<div style="margin: 100px;">
<Poptip
confirm
transfer
title="您确认删除这条内容吗?"
@on-ok="ok"
@on-cancel="cancel">
<Button>删除</Button>
</Poptip>
</div>
</template>
<script>
export default {
methods: {
ok () {
this.$Message.info('点击了确定');
},
cancel () {
this.$Message.info('点击了取消');
}
}
}
</script>

View file

@ -1,11 +1,13 @@
<template>
<div>
<Radio true-value="true" false-value="false" v-model="testValue">test</Radio> {{ testValue }}
<Radio-group v-model="date.sex">
<div v-if="show">
<Radio label="male"></Radio>
<Radio label="female"></Radio>
<Radio label="male" true-value="true" false-value="false"></Radio>
<Radio label="female" true-value="true" false-value="false"></Radio>
</div>
</Radio-group>
{{ date }}
<Button @click="handleChange">change</Button>
</div>
</template>
@ -16,7 +18,8 @@
date: {
sex: 'male'
},
show: false
show: false,
testValue: null
}
},
methods: {

View file

@ -29,7 +29,8 @@
},
{
title: 'child2',
id: '1-2'
id: '1-2',
children: []
}
]
}

View file

@ -1,6 +1,6 @@
{
"name": "iview",
"version": "2.0.0",
"version": "2.1.0",
"title": "iView",
"description": "A high quality UI components Library with Vue.js",
"homepage": "http://www.iviewui.com",

View file

@ -0,0 +1,93 @@
<template>
<span :class="classes">
<img :src="src" v-if="src">
<Icon :type="icon" v-else-if="icon"></Icon>
<span ref="children" :class="[prefixCls + '-string']" :style="childrenStyle" v-else><slot></slot></span>
</span>
</template>
<script>
import Icon from '../icon';
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-avatar';
export default {
name: 'Avatar',
components: { Icon },
props: {
shape: {
validator (value) {
return oneOf(value, ['circle', 'square']);
},
default: 'circle'
},
size: {
validator (value) {
return oneOf(value, ['small', 'large', 'default']);
},
default: 'default'
},
src: {
type: String
},
icon: {
type: String
}
},
data () {
return {
prefixCls: prefixCls,
scale: 1,
isSlotShow: false
};
},
computed: {
classes () {
return [
`${prefixCls}`,
`${prefixCls}-${this.shape}`,
`${prefixCls}-${this.size}`,
{
[`${prefixCls}-image`]: !!this.src,
[`${prefixCls}-icon`]: !!this.icon
}
];
},
childrenStyle () {
let style = {};
if (this.isSlotShow) {
style = {
msTransform: `scale(${this.scale})`,
WebkitTransform: `scale(${this.scale})`,
transform: `scale(${this.scale})`,
position: 'absolute',
display: 'inline-block',
left: `calc(50% - ${Math.round(this.$refs.children.offsetWidth / 2)}px)`
};
}
return style;
}
},
methods: {
setScale () {
this.isSlotShow = !this.src && !this.icon;
if (this.$slots.default) {
const childrenWidth = this.$refs.children.offsetWidth;
const avatarWidth = this.$el.getBoundingClientRect().width;
// add 4px gap for each side to get better performance
if (avatarWidth - 8 < childrenWidth) {
this.scale = (avatarWidth - 8) / childrenWidth;
} else {
this.scale = 1;
}
}
}
},
mounted () {
this.setScale();
},
updated () {
this.setScale();
}
};
</script>

View file

@ -0,0 +1,2 @@
import Avatar from './avatar.vue';
export default Avatar;

View file

@ -15,7 +15,7 @@
<script>
import Casitem from './casitem.vue';
import Emitter from '../../mixins/emitter';
import { findComponentUpward } from '../../utils/assist';
import { findComponentUpward, findComponentDownward } from '../../utils/assist';
let key = 1;
@ -67,7 +67,9 @@
if (fromUser) {
cascader.isLoadedChildren = true;
}
this.handleTriggerItem(item);
if (item.children.length) {
this.handleTriggerItem(item);
}
});
return;
}
@ -84,6 +86,14 @@
changeOnSelect: this.changeOnSelect,
fromInit: fromInit
});
// #1553
if (this.changeOnSelect) {
const Caspanel = findComponentDownward(this, 'Caspanel');
if (Caspanel) {
Caspanel.$emit('on-clear', true);
}
}
} else {
this.sublist = [];
this.dispatch('Cascader', 'on-result-change', {
@ -135,9 +145,16 @@
}
}
});
this.$on('on-clear', () => {
// deep for #1553
this.$on('on-clear', (deep = false) => {
this.sublist = [];
this.tmpItem = {};
if (deep) {
const Caspanel = findComponentDownward(this, 'Caspanel');
if (Caspanel) {
Caspanel.$emit('on-clear', true);
}
}
});
}
};

View file

@ -36,7 +36,15 @@
default: false
},
value: {
type: Boolean,
type: [String, Number, Boolean],
default: false
},
trueValue: {
type: [String, Number, Boolean],
default: true
},
falseValue: {
type: [String, Number, Boolean],
default: false
},
label: {
@ -102,21 +110,26 @@
const checked = event.target.checked;
this.currentValue = checked;
this.$emit('input', checked);
let value = checked ? this.trueValue : this.falseValue;
this.$emit('input', value);
if (this.group) {
this.parent.change(this.model);
} else {
this.$emit('on-change', checked);
this.dispatch('FormItem', 'on-form-change', checked);
this.$emit('on-change', value);
this.dispatch('FormItem', 'on-form-change', value);
}
},
updateModel () {
this.currentValue = this.value;
this.currentValue = this.value === this.trueValue;
}
},
watch: {
value () {
value (val) {
if (val !== this.trueValue && val !== this.falseValue) {
throw 'Value should be trueValue or falseValue.';
}
this.updateModel();
}
}

View file

@ -0,0 +1,90 @@
<template>
<Dropdown trigger="click" :transfer="transfer" :placement="placement">
<div :class="wrapClasses">
<i class="ivu-icon ivu-icon-arrow-down-b ivu-input-icon ivu-input-icon-normal"></i>
<div :class="inputClasses">
<div :class="[prefixCls + '-color']" style="background-color: rgb(32, 160, 255);"></div>
</div>
</div>
<Dropdown-menu slot="list">
<p>常用于各种自定义下拉内容的场景</p>
<div style="text-align: right;margin:10px;">
<Button type="primary">关闭</Button>
</div>
</Dropdown-menu>
</Dropdown>
</template>
<script>
import Dropdown from '../dropdown/dropdown.vue';
import DropdownMenu from '../dropdown/dropdown-menu.vue';
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-color-picker';
const inputPrefixCls = 'ivu-input';
export default {
name: 'ColorPicker',
components: { Dropdown, DropdownMenu },
props: {
value: {
type: String
},
alpha: {
type: Boolean,
default: false
},
format: {
validator (value) {
return oneOf(value, ['hsl', 'hsv', 'hex', 'rgb']);
}
},
disabled: {
type: Boolean,
default: false
},
size: {
validator (value) {
return oneOf(value, ['small', 'large', 'default']);
}
},
placement: {
validator (value) {
return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']);
},
default: 'bottom'
},
transfer: {
type: Boolean,
default: false
}
},
data () {
return {
prefixCls: prefixCls,
currentValue: this.value
};
},
computed: {
wrapClasses () {
return [
`${prefixCls}-rel`,
`${inputPrefixCls}-wrapper`,
`${inputPrefixCls}-wrapper-${this.size}`
];
},
inputClasses () {
return [
`${prefixCls}-input`,
`${inputPrefixCls}`,
`${inputPrefixCls}-${this.size}`,
{
[`${inputPrefixCls}-disabled`]: this.disabled
}
];
}
},
methods: {
}
};
</script>

View file

View file

@ -0,0 +1,2 @@
import ColorPicker from './color-picker.vue';
export default ColorPicker;

View file

@ -1,18 +1,18 @@
<template>
<div :class="classes">
<div :class="[prefixCls+ '-list']" ref="hours">
<ul :class="[prefixCls + '-ul']" @click="handleClickHours">
<li :class="getCellCls(item)" v-for="(item, index) in hoursList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li>
<ul :class="[prefixCls + '-ul']">
<li :class="getCellCls(item)" v-for="item in hoursList" v-show="!item.hide" @click="handleClick('hours', item)">{{ formatTime(item.text) }}</li>
</ul>
</div>
<div :class="[prefixCls+ '-list']" ref="minutes">
<ul :class="[prefixCls + '-ul']" @click="handleClickMinutes">
<li :class="getCellCls(item)" v-for="(item, index) in minutesList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li>
<ul :class="[prefixCls + '-ul']">
<li :class="getCellCls(item)" v-for="item in minutesList" v-show="!item.hide" @click="handleClick('minutes', item)">{{ formatTime(item.text) }}</li>
</ul>
</div>
<div :class="[prefixCls+ '-list']" v-show="showSeconds" ref="seconds">
<ul :class="[prefixCls + '-ul']" @click="handleClickSeconds">
<li :class="getCellCls(item)" v-for="(item, index) in secondsList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li>
<ul :class="[prefixCls + '-ul']">
<li :class="getCellCls(item)" v-for="item in secondsList" v-show="!item.hide" @click="handleClick('seconds', item)">{{ formatTime(item.text) }}</li>
</ul>
</div>
</div>
@ -41,10 +41,15 @@
showSeconds: {
type: Boolean,
default: true
},
steps: {
type: Array,
default: () => []
}
},
data () {
return {
spinerSteps: [1, 1, 1].map((one, i) => Math.abs(this.steps[i]) || one),
prefixCls: prefixCls,
compiled: false
};
@ -60,6 +65,7 @@
},
hoursList () {
let hours = [];
const step = this.spinerSteps[0];
const hour_tmpl = {
text: 0,
selected: false,
@ -67,7 +73,7 @@
hide: false
};
for (let i = 0; i < 24; i++) {
for (let i = 0; i < 24; i += step) {
const hour = deepCopy(hour_tmpl);
hour.text = i;
@ -83,6 +89,7 @@
},
minutesList () {
let minutes = [];
const step = this.spinerSteps[1];
const minute_tmpl = {
text: 0,
selected: false,
@ -90,7 +97,7 @@
hide: false
};
for (let i = 0; i < 60; i++) {
for (let i = 0; i < 60; i += step) {
const minute = deepCopy(minute_tmpl);
minute.text = i;
@ -101,11 +108,11 @@
if (this.minutes === i) minute.selected = true;
minutes.push(minute);
}
return minutes;
},
secondsList () {
let seconds = [];
const step = this.spinerSteps[2];
const second_tmpl = {
text: 0,
selected: false,
@ -113,7 +120,7 @@
hide: false
};
for (let i = 0; i < 60; i++) {
for (let i = 0; i < 60; i += step) {
const second = deepCopy(second_tmpl);
second.text = i;
@ -138,24 +145,11 @@
}
];
},
handleClickHours (event) {
this.handleClick('hours', event);
},
handleClickMinutes (event) {
this.handleClick('minutes', event);
},
handleClickSeconds (event) {
this.handleClick('seconds', event);
},
handleClick (type, event) {
const target = event.target;
if (target.tagName === 'LI') {
const cell = this[`${type}List`][parseInt(event.target.getAttribute('index'))];
if (cell.disabled) return;
const data = {};
data[type] = cell.text;
this.$emit('on-change', data);
}
handleClick (type, cell) {
if (cell.disabled) return;
const data = {};
data[type] = cell.text;
this.$emit('on-change', data);
this.$emit('on-pick-click');
},
scroll (type, index) {
@ -183,20 +177,24 @@
},
formatTime (text) {
return text < 10 ? '0' + text : text;
},
getItemIndex(type, val){
const item = this[`${type}List`].find(obj => obj.text == val);
return this[`${type}List`].indexOf(item);
}
},
watch: {
hours (val) {
if (!this.compiled) return;
this.scroll('hours', val);
this.scroll('hours', this.getItemIndex('hours', val));
},
minutes (val) {
if (!this.compiled) return;
this.scroll('minutes', val);
this.scroll('minutes', this.getItemIndex('minutes', val));
},
seconds (val) {
if (!this.compiled) return;
this.scroll('seconds', val);
this.scroll('seconds', this.getItemIndex('seconds', val));
}
},
mounted () {

View file

@ -6,6 +6,7 @@
<time-spinner
ref="timeSpinner"
:show-seconds="showSeconds"
:steps="steps"
:hours="hours"
:minutes="minutes"
:seconds="seconds"
@ -39,6 +40,12 @@
name: 'TimePicker',
mixins: [ Mixin, Locale ],
components: { TimeSpinner, Confirm },
props: {
steps: {
type: Array,
default: () => []
}
},
data () {
return {
prefixCls: prefixCls,

View file

@ -32,7 +32,6 @@
</div>
</template>
<script>
import Vue from 'vue';
import iInput from '../../components/input/input.vue';
import Drop from '../../components/select/dropdown.vue';
import clickoutside from '../../directives/clickoutside';
@ -397,7 +396,7 @@
let isConfirm = this.confirm;
const type = this.type;
this.picker = new Vue(this.panel).$mount(this.$refs.picker);
this.picker = this.Panel.$mount(this.$refs.picker);
if (type === 'datetime' || type === 'datetimerange') {
isConfirm = true;
this.picker.showTime = true;
@ -459,7 +458,7 @@
).formatter;
let newDate = formatter(date, format);
if (type === 'daterange' || type === 'timerange') {
if (type === 'daterange' || type === 'timerange' || type === 'datetimerange') {
newDate = [newDate.split(RANGE_SEPARATOR)[0], newDate.split(RANGE_SEPARATOR)[1]];
}
return newDate;

View file

@ -1,3 +1,4 @@
import Vue from 'vue';
import Picker from '../picker.vue';
import DatePanel from '../panel/date.vue';
import DateRangePanel from '../panel/date-range.vue';
@ -31,6 +32,7 @@ export default {
}
}
this.panel = getPanel(this.type);
const panel = getPanel(this.type);
this.Panel = new Vue(panel);
}
};

View file

@ -1,3 +1,4 @@
import Vue from 'vue';
import Picker from '../picker.vue';
import TimePanel from '../panel/time.vue';
import TimeRangePanel from '../panel/time-range.vue';
@ -21,6 +22,10 @@ export default {
},
default: 'time'
},
steps: {
type: Array,
default: () => []
},
value: {}
},
created () {
@ -31,6 +36,11 @@ export default {
this.currentValue = '';
}
}
this.panel = getPanel(this.type);
const Panel = Vue.extend(getPanel(this.type));
this.Panel = new Panel({
propsData: {
steps: this.steps
}
});
}
};

View file

@ -1,6 +1,6 @@
<template>
<div :class="classes">
<label :class="[prefixCls + '-label']" :style="labelStyles" v-if="label"><slot name="label">{{ label }}</slot></label>
<label :class="[prefixCls + '-label']" :style="labelStyles" v-if="label || $slots.label"><slot name="label">{{ label }}</slot></label>
<div :class="[prefixCls + '-content']" :style="contentStyles">
<slot></slot>
<transition name="fade">
@ -177,6 +177,7 @@
callback(this.validateMessage);
});
this.validateDisabled = false;
},
resetField () {
this.validateState = '';

View file

@ -74,7 +74,7 @@
},
size: {
validator (value) {
return oneOf(value, ['small', 'large']);
return oneOf(value, ['small', 'large', 'default']);
}
},
placeholder: {

View file

@ -135,6 +135,12 @@
};
},
watch: {
total (val) {
let maxPage = Math.ceil(val / this.currentPageSize);
if (maxPage < this.currentPage && maxPage > 0) {
this.currentPage = maxPage;
}
},
current (val) {
this.currentPage = val;
},
@ -208,6 +214,7 @@
changePage (page) {
if (this.currentPage != page) {
this.currentPage = page;
this.$emit('update:current', page);
this.$emit('on-change', page);
}
},

View file

@ -22,7 +22,15 @@
mixins: [ Emitter ],
props: {
value: {
type: Boolean,
type: [String, Number, Boolean],
default: false
},
trueValue: {
type: [String, Number, Boolean],
default: true
},
falseValue: {
type: [String, Number, Boolean],
default: false
},
label: {
@ -83,7 +91,9 @@
const checked = event.target.checked;
this.currentValue = checked;
this.$emit('input', checked);
let value = checked ? this.trueValue : this.falseValue;
this.$emit('input', value);
if (this.group && this.label !== undefined) {
this.parent.change({
@ -92,16 +102,19 @@
});
}
if (!this.group) {
this.$emit('on-change', checked);
this.dispatch('FormItem', 'on-form-change', checked);
this.$emit('on-change', value);
this.dispatch('FormItem', 'on-form-change', value);
}
},
updateValue () {
this.currentValue = this.value;
this.currentValue = this.value === this.trueValue;
}
},
watch: {
value () {
value (val) {
if (val !== this.trueValue && val !== this.falseValue) {
throw 'Value should be trueValue or falseValue.';
}
this.updateValue();
}
}

View file

@ -41,7 +41,7 @@ const csv = {
_getDownloadUrl (text) {
const BOM = '\uFEFF';
// Add BOM to text for open in excel correctly
if (window.Blob && window.URL && window.URL.createObjectURL && !has('Safari')) {
if (window.Blob && window.URL && window.URL.createObjectURL) {
const csvData = new Blob([BOM + text], { type: 'text/csv' });
return URL.createObjectURL(csvData);
} else {
@ -66,7 +66,6 @@ const csv = {
const link = document.createElement('a');
link.download = filename;
link.href = this._getDownloadUrl(text);
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

View file

@ -71,7 +71,7 @@
// init checked status
function reverseChecked(data) {
if (!data.nodeKey) data.nodeKey = key++;
if (data.children) {
if (data.children && data.children.length) {
let checkedLength = 0;
data.children.forEach(node => {
if (node.children) node = reverseChecked(node);

View file

@ -3,6 +3,7 @@ import 'core-js/fn/array/find-index';
import Affix from './components/affix';
import Alert from './components/alert';
import Avatar from './components/avatar';
import BackTop from './components/back-top';
import Badge from './components/badge';
import Breadcrumb from './components/breadcrumb';
@ -13,6 +14,7 @@ import Cascader from './components/cascader';
import Checkbox from './components/checkbox';
import Circle from './components/circle';
import Collapse from './components/collapse';
import ColorPicker from './components/color-picker';
import DatePicker from './components/date-picker';
import Dropdown from './components/dropdown';
import Form from './components/form';
@ -49,6 +51,7 @@ import locale from './locale';
const iview = {
Affix,
Alert,
Avatar,
BackTop,
Badge,
Breadcrumb,
@ -63,6 +66,10 @@ const iview = {
Checkbox,
CheckboxGroup: Checkbox.Group,
iCircle: Circle,
Col,
iCol: Col,
Collapse,
ColorPicker,
DatePicker,
Dropdown,
DropdownItem: Dropdown.Item,
@ -70,9 +77,6 @@ const iview = {
Form,
iForm: Form,
FormItem: Form.Item,
Col,
iCol: Col,
Collapse,
Icon,
Input,
iInput: Input,

96
src/locale/lang/pt-PT.js Normal file
View file

@ -0,0 +1,96 @@
export default {
i: {
select: {
placeholder: 'Selecionar',
noMatch: 'Não encontrado',
loading: 'A carregar'
},
table: {
noDataText: 'Sem dados',
noFilteredDataText: 'Sem dados filtrados',
confirmFilter: 'Confirmar',
resetFilter: 'Limpar',
clearFilter: 'Todos'
},
datepicker: {
selectDate: 'Selecione a data',
selectTime: 'Selecione a hora',
startTime: 'Hora inicial',
endTime: 'Hora final',
clear: 'Limpar',
ok: 'Confirmar',
month: 'Mês',
month1: 'Janeiro',
month2: 'Fevereiro',
month3: 'Março',
month4: 'Abril',
month5: 'Maio',
month6: 'Junho',
month7: 'Julho',
month8: 'Agosto',
month9: 'Setembro',
month10: 'Outubro',
month11: 'Novembro',
month12: 'Dezembro',
year: 'Ano',
weeks: {
sun: 'Dom',
mon: 'Seg',
tue: 'Ter',
wed: 'Qua',
thu: 'Qui',
fri: 'Sex',
sat: 'Sáb'
},
months: {
m1: 'Jan',
m2: 'Fev',
m3: 'Mar',
m4: 'Abr',
m5: 'Mai',
m6: 'Jun',
m7: 'Jul',
m8: 'Ago',
m9: 'Set',
m10: 'Out',
m11: 'Nov',
m12: 'Dez'
}
},
transfer: {
titles: {
source: 'Origem',
target: 'Destino'
},
filterPlaceholder: 'Pesquise aqui',
notFoundText: 'Não encontrado'
},
modal: {
okText: 'Confirmar',
cancelText: 'Cancelar'
},
poptip: {
okText: 'Confirmar',
cancelText: 'Cancelar'
},
page: {
prev: 'Página anterior',
next: 'Próxima página',
total: 'Total',
item: 'item',
items: 'itens',
prev5: 'Voltar 5 páginas',
next5: 'Avançar 5 páginas',
page: '/page',
goto: 'Ir para',
p: ''
},
rate: {
star: 'Estrela',
stars: 'Estrelas'
},
tree: {
emptyText: 'Sem dados'
}
}
};

96
src/locale/lang/sv-SE.js Normal file
View file

@ -0,0 +1,96 @@
export default {
i: {
select: {
placeholder: 'Välj',
noMatch: 'Ingen träff',
loading: 'Ladar'
},
table: {
noDataText: 'Ingen data',
noFilteredDataText: 'Ingen filter data',
confirmFilter: 'Bekräfta',
resetFilter: 'Återställ filter',
clearFilter: 'Rensa filter'
},
datepicker: {
selectDate: 'Välj datum',
selectTime: 'Välj tidpunkt',
startTime: 'Start tid',
endTime: 'Slut tid',
clear: 'Rensa',
ok: 'Ok',
month: 'Månad',
month1: 'Januari',
month2: 'Februari',
month3: 'Mars',
month4: 'April',
month5: 'Maj',
month6: 'Juni',
month7: 'Juli',
month8: 'Augusti',
month9: 'September',
month10: 'Oktober',
month11: 'November',
month12: 'December',
year: 'År',
weeks: {
sun: 'Sön',
mon: 'Mån',
tue: 'Tis',
wed: 'Ons',
thu: 'Tor',
fri: 'Fre',
sat: 'Lör'
},
months: {
m1: 'Jan',
m2: 'Feb',
m3: 'Mar',
m4: 'Apr',
m5: 'Maj',
m6: 'Jun',
m7: 'Jul',
m8: 'Aug',
m9: 'Sep',
m10: 'Okt',
m11: 'Nov',
m12: 'Dec'
}
},
transfer: {
titles: {
source: 'Källa',
target: 'Mål'
},
filterPlaceholder: 'Sök här',
notFoundText: 'Hittade inte'
},
modal: {
okText: 'Ok',
cancelText: 'Avbryt'
},
poptip: {
okText: 'Ok',
cancelText: 'Avbryt'
},
page: {
prev: 'Föregående sida',
next: 'Nästa sida',
total: 'Totalt',
item: 'objekt',
items: 'objekt',
prev5: 'Föregående 5 sidor',
next5: 'Nästa 5 sidor',
page: '/page',
goto: 'Gå till',
p: ''
},
rate: {
star: 'Stjärna',
stars: 'Stjärnor'
},
tree: {
emptyText: 'Ingen data'
}
}
};

View file

@ -1,96 +1,96 @@
export default {
i: {
select: {
placeholder: 'Chọn',
noMatch: 'Không tìm thấy',
loading: 'Đang tải'
},
table: {
noDataText: 'Không có dữ liệu',
noFilteredDataText: 'Không có dữ liệu lọc',
confirmFilter: 'Xác nhận',
resetFilter: 'Làm lại',
clearFilter: 'Xóa hết'
},
datepicker: {
selectDate: 'Chọn ngày',
selectTime: 'Chọn giờ',
startTime: 'Ngày bắt đầu',
endTime: 'Ngày kết thúc',
clear: 'Xóa',
ok: 'Đồng ý',
month: '',
month1: 'Tháng 1',
month2: 'Tháng 2',
month3: 'Tháng 3',
month4: 'Tháng 4',
month5: 'Tháng 5',
month6: 'Tháng 6',
month7: 'Tháng 7',
month8: 'Tháng 8',
month9: 'Tháng 9',
month10: 'Tháng 10',
month11: 'Tháng 11',
month12: 'Tháng 12',
year: '',
weeks: {
sun: 'CN',
mon: 'T2',
tue: 'T3',
wed: 'T4',
thu: 'T5',
fri: 'T6',
sat: 'T7'
},
months: {
m1: 'Th.1',
m2: 'Th.2',
m3: 'Th.3',
m4: 'Th.4',
m5: 'Th.5',
m6: 'Th.6',
m7: 'Th.7',
m8: 'Th.8',
m9: 'Th.9',
m10: 'Th.10',
m11: 'Th.11',
m12: 'Th.12'
}
},
transfer: {
titles: {
source: 'Nguồn',
target: 'Đích'
},
filterPlaceholder: 'Nhập từ khóa',
notFoundText: 'Không tìm thấy'
},
modal: {
okText: 'Đồng ý',
cancelText: 'Hủy bỏ'
},
poptip: {
okText: 'Đồng ý',
cancelText: 'Hủy bỏ'
},
page: {
prev: 'Trang trước',
next: 'Trang kế',
total: 'Tổng',
item: 'kết quả',
items: 'kết quả',
prev5: '5 trang trước',
next5: '5 trang kế',
page: '/trang',
goto: 'Tới trang',
p: ''
},
rate: {
star: 'Sao',
stars: 'Sao'
},
tree: {
emptyText: 'Không có dữ liệu'
i: {
select: {
placeholder: 'Chọn',
noMatch: 'Không tìm thấy',
loading: 'Đang tải'
},
table: {
noDataText: 'Không có dữ liệu',
noFilteredDataText: 'Không có dữ liệu lọc',
confirmFilter: 'Xác nhận',
resetFilter: 'Làm lại',
clearFilter: 'Xóa hết'
},
datepicker: {
selectDate: 'Chọn ngày',
selectTime: 'Chọn giờ',
startTime: 'Ngày bắt đầu',
endTime: 'Ngày kết thúc',
clear: 'Xóa',
ok: 'Đồng ý',
month: '',
month1: 'Tháng 1',
month2: 'Tháng 2',
month3: 'Tháng 3',
month4: 'Tháng 4',
month5: 'Tháng 5',
month6: 'Tháng 6',
month7: 'Tháng 7',
month8: 'Tháng 8',
month9: 'Tháng 9',
month10: 'Tháng 10',
month11: 'Tháng 11',
month12: 'Tháng 12',
year: '',
weeks: {
sun: 'CN',
mon: 'T2',
tue: 'T3',
wed: 'T4',
thu: 'T5',
fri: 'T6',
sat: 'T7'
},
months: {
m1: 'Th.1',
m2: 'Th.2',
m3: 'Th.3',
m4: 'Th.4',
m5: 'Th.5',
m6: 'Th.6',
m7: 'Th.7',
m8: 'Th.8',
m9: 'Th.9',
m10: 'Th.10',
m11: 'Th.11',
m12: 'Th.12'
}
},
transfer: {
titles: {
source: 'Nguồn',
target: 'Đích'
},
filterPlaceholder: 'Nhập từ khóa',
notFoundText: 'Không tìm thấy'
},
modal: {
okText: 'Đồng ý',
cancelText: 'Hủy bỏ'
},
poptip: {
okText: 'Đồng ý',
cancelText: 'Hủy bỏ'
},
page: {
prev: 'Trang trước',
next: 'Trang kế',
total: 'Tổng',
item: 'kết quả',
items: 'kết quả',
prev5: '5 trang trước',
next5: '5 trang kế',
page: '/trang',
goto: 'Tới trang',
p: ''
},
rate: {
star: 'Sao',
stars: 'Sao'
},
tree: {
emptyText: 'Không có dữ liệu'
}
}
}
};

View file

@ -0,0 +1,45 @@
@avatar-prefix-cls: ~"@{css-prefix}avatar";
.@{avatar-prefix-cls} {
display: inline-block;
text-align: center;
background: @avatar-bg;
color: @avatar-color;
white-space: nowrap;
position: relative;
overflow: hidden;
.avatar-size(@avatar-size-base, @avatar-font-size-base);
&-large {
.avatar-size(@avatar-size-lg, @avatar-font-size-lg);
}
&-small {
.avatar-size(@avatar-size-sm, @avatar-font-size-sm);
}
&-square {
border-radius: @avatar-border-radius;
}
& > img {
width: 100%;
height: 100%;
}
}
.avatar-size(@size, @font-size) {
width: @size;
height: @size;
line-height: @size;
border-radius: @size / 2;
& > * {
line-height: @size;
}
&.@{avatar-prefix-cls}-icon {
font-size: @font-size;
}
}

View file

@ -0,0 +1,12 @@
@color-picker-prefix-cls: ~"@{css-prefix}color-picker";
.@{color-picker-prefix-cls} {
&-rel{
line-height: 0;
}
&-color{
width: 20px;
height: 100%;
border: 1px solid @text-color;
}
}

View file

@ -39,3 +39,5 @@
@import "rate";
@import "upload";
@import "tree";
@import "avatar";
@import "color-picker";

View file

@ -6,6 +6,7 @@
.@{radio-group-prefix-cls} {
display: inline-block;
font-size: @font-size-small;
vertical-align: middle;
&-vertical{
.@{radio-prefix-cls}-wrapper {
display: block;

View file

@ -162,3 +162,14 @@
@slider-button-wrap-size : 18px;
@slider-button-wrap-offset : -4px;
@slider-disabled-color : #ccc;
// Avatar
@avatar-size-base: 32px;
@avatar-size-lg: 40px;
@avatar-size-sm: 24px;
@avatar-font-size-base: 18px;
@avatar-font-size-lg: 24px;
@avatar-font-size-sm: 14px;
@avatar-bg: #ccc;
@avatar-color: #fff;
@avatar-border-radius: @border-radius-small;

View file

@ -0,0 +1,28 @@
import { createVue, destroyVM } from '../util';
describe('DatePicker.vue', () => {
let vm;
afterEach(() => {
destroyVM(vm);
});
it('should create a DatePicker component and open the calendar with the current month', done => {
vm = createVue(`
<Date-Picker></Date-Picker>
`);
const picker = vm.$children[0];
picker.showPicker();
vm.$nextTick(() => {
const calendarBody = vm.$el.querySelector('.ivu-picker-panel-body .ivu-date-picker-cells:first-of-type');
const calendarCells = [...calendarBody.querySelectorAll('.ivu-date-picker-cells-cell')].filter(el => {
const prevMonth = el.classList.contains('ivu-date-picker-cells-cell-prev-month');
const nextMonth = el.classList.contains('ivu-date-picker-cells-cell-next-month');
return !prevMonth && !nextMonth;
});
const today = new Date();
const daysInCurrentMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate();
expect(daysInCurrentMonth).to.equal(calendarCells.length);
done();
});
});
});

View file

@ -0,0 +1,60 @@
import { createVue, destroyVM } from '../util';
describe('TimePicker.vue', () => {
let vm;
afterEach(() => {
destroyVM(vm);
});
it('should create a TimePicker component with hours, minutes and seconds', done => {
vm = createVue(`
<Time-Picker></Time-Picker>
`);
const picker = vm.$children[0];
picker.handleIconClick(); // open the picker panels
vm.$nextTick(() => {
const spiners = picker.$el.querySelectorAll('.ivu-time-picker-cells-list');
expect(spiners.length).to.equal(3); // hh:mm:ss
expect(spiners[0].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(24);
expect(spiners[1].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
expect(spiners[2].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
done();
});
});
it('should create a TimePicker component with only hours and minutes', done => {
vm = createVue(`
<Time-Picker format="HH:mm"></Time-Picker>
`);
const picker = vm.$children[0];
picker.handleIconClick(); // open the picker panels
vm.$nextTick(() => {
const spiners = picker.$el.querySelectorAll('.ivu-time-picker-cells-list');
expect([...spiners].filter(el => el.style.display != 'none').length).to.equal(2); // hh:mm
expect(spiners[0].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(24);
expect(spiners[1].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
done();
});
});
it('should create a TimePicker component with steps of 15 minutes', done => {
vm = createVue(`
<Time-Picker :steps="[1, 15]"></Time-Picker>
`);
const picker = vm.$children[0];
picker.handleIconClick(); // open the picker panels
vm.$nextTick(() => {
const spiners = picker.$el.querySelectorAll('.ivu-time-picker-cells-list');
const minutesList = [...spiners[1].querySelectorAll('.ivu-time-picker-cells-cell')];
expect(spiners[0].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(24);
expect(minutesList.map(el => el.textContent).join(',')).to.equal('00,15,30,45');
expect(spiners[1].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(4);
expect(spiners[2].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
done();
});
});
});